Skip to content

Quickstart

End-to-end path: feature → plan → subscriber → subscription → check.

You need:

  • An account and organization at e10s.io
  • A member API key on a service account (shown once when you create it)
  • Your organization id

API host: https://api.e10s.io. See Authentication.

1. Create features

POST /api/organizations/{organization_id}/features
X-API-Key: e10s-mk-1-…
Content-Type: application/json
{
  "key": "sso",
  "name": "SSO",
  "kind": "flag",
  "description": "SAML/OIDC single sign-on"
}
{
  "key": "seats",
  "name": "Seats",
  "kind": "limit"
}

2. Create a catalog plan

POST /api/organizations/{organization_id}/plans
X-API-Key: e10s-mk-1-…
Content-Type: application/json
{
  "key": "pro",
  "name": "Pro",
  "kind": "catalog",
  "grants": [
    { "feature": "sso", "kind": "flag" },
    { "feature": "seats", "kind": "limit", "limit": 10 }
  ]
}

3. Create a subscriber

When a customer appears in your product:

POST /api/organizations/{organization_id}/subscribers
X-API-Key: e10s-mk-1-…
Content-Type: application/json
{
  "external_id": "cust_123",
  "name": "Acme Corp"
}

Save the returned id (or look up by external_id later).

4. Subscribe them to Pro

POST /api/organizations/{organization_id}/subscribers/{subscriber_id}/subscriptions
X-API-Key: e10s-mk-1-…
Content-Type: application/json
{
  "plan_id": "{plan_id}"
}

5. Check access from your backend

Flag

POST /api/organizations/{organization_id}/subscribers/{subscriber_id}/entitlements/check
X-API-Key: e10s-mk-1-…
Content-Type: application/json
{ "feature": "sso" }
{
  "feature": "sso",
  "kind": "flag",
  "allowed": true,
  "source": "plan"
}

Limit

{ "feature": "seats" }
{
  "feature": "seats",
  "kind": "limit",
  "limit": 10,
  "source": "plan"
}

6. Gate in your product

// flag
if (result.kind === "flag" && !result.allowed) {
  return res.status(403).json({ error: "sso_not_entitled" })
}

// limit — usage lives in your DB
if (result.kind === "limit") {
  const used = await countSeats(customerId)
  if (result.limit !== null && used >= result.limit) {
    return res.status(403).json({ error: "seat_limit_reached" })
  }
}

Next