Skip to content

Get a customer's entitlements

The customers.entitlements.get operation: GET /api/v1/customers/{id}/entitlements in the REST API and the customers_entitlements_get tool in the MCP server.

GET/api/v1/customers/{id}/entitlements

Returns what a customer of the brand may use, in the mode of the request: one value per feature of the brand (values), where each value comes from (sources) and when it was resolved (computedAt).

Values are resolved from the customer's subscriptions (active, trialing, past_due during the grace period, paused when the brand keeps entitlements during a pause), one-time purchases of products with lifetimeEntitlements, overrides set by your team, and feature defaults, merged with each feature's combine rule. A perUnit limit is multiplied by the quantity.

Ownrecord stores the result and recomputes it within one job cycle of every change; the customer.entitlements.updated webhook says when it changed. A read never returns a set known to be out of date: while a recompute is pending it resolves the values from the sources. Enforcing them is up to your product. For one feature, entitlements.check is lighter.

At a glance

  • REST: GET /api/v1/customers/{id}/entitlements
  • MCP tool: customers_entitlements_get
  • Operation ID: customers.entitlements.get
  • Scope: Brand
  • Permission: customers:read
  • Risk tier: read
  • Dry run: Not supported
  • Idempotency: Not needed (read only)
  • Modes: Test and live
  • Authentication: API key with the customers:read scope
  • Since: M5

Request

Path parameters

FieldTypeDescription
idcus_… IDThe customer's ID (cus_…).

Query parameters

This operation takes no query parameters.

Response

200 OK with a JSON object:

FieldTypeDescription
object"customer_entitlements"
customerIdcus_… ID
brandIdbrd_… ID
livemodeboolean
valuesobjectOne value per feature of the brand; defaults fill what nothing grants.
sourcesarray of objectEvery source that granted a value, per feature in precedence order (overrides, subscriptions, purchases); the feature's combine rule merges them. A feature nothing grants lists its default.
sources[].typeone of override, subscription, purchase, default
sources[].refstringThe override (ceo_…), subscription (sub_…), payment of a lifetime purchase (pay_…) or, for a default, the feature (feat_…).
sources[].featureKeystring
sources[].valueboolean or number or stringWhat this source grants (per-unit limits already multiplied by the quantity).
computedAtdate-timeWhen the values were resolved.

Examples

A subscriber with an override

Three seats of a plan granting 5 seats per unit (15), raised to 20 by an override (seats.max combines with max); support.level has its default.

HTTP
GET /api/v1/customers/cus_01m4ty3c2b5qx7mhd9k8w6s0aa/entitlements
Authorization: Bearer or_test_…

Response (200):

JSON
{
  "object": "customer_entitlements",
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "values": {
    "feature.export": true,
    "seats.max": 20,
    "support.level": "community"
  },
  "sources": [
    {
      "type": "subscription",
      "ref": "sub_01m4ty3c2b5qx7mhd9k8w6s0b0",
      "featureKey": "feature.export",
      "value": true
    },
    {
      "type": "override",
      "ref": "ceo_01m4ty3c2b5qx7mhd9k8w6s0b2",
      "featureKey": "seats.max",
      "value": 20
    },
    {
      "type": "subscription",
      "ref": "sub_01m4ty3c2b5qx7mhd9k8w6s0b0",
      "featureKey": "seats.max",
      "value": 15
    },
    {
      "type": "default",
      "ref": "feat_01m4tx5nj8emwbyf7y9vcf47y8",
      "featureKey": "support.level",
      "value": "community"
    }
  ],
  "computedAt": "2026-10-14T10:00:05.000Z"
}

A lifetime purchase

HTTP
GET /api/v1/customers/cus_01m4ty3c2b5qx7mhd9k8w6s0ab/entitlements
Authorization: Bearer or_test_…

Response (200):

JSON
{
  "object": "customer_entitlements",
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0ab",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "values": {
    "feature.export": true,
    "seats.max": 1,
    "support.level": "community"
  },
  "sources": [
    {
      "type": "purchase",
      "ref": "pay_01m4ty3c2b5qx7mhd9k8w6s0b1",
      "featureKey": "feature.export",
      "value": true
    },
    {
      "type": "default",
      "ref": "feat_01m4tx5nj8emwbyf7y9vcf47y6",
      "featureKey": "seats.max",
      "value": 1
    },
    {
      "type": "default",
      "ref": "feat_01m4tx5nj8emwbyf7y9vcf47y8",
      "featureKey": "support.level",
      "value": "community"
    }
  ],
  "computedAt": "2026-10-14T10:00:05.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400id isn't a customer ID (cus_…).Fix the fields listed in details.issues and send the request again.
resource_not_found404This brand has no such customer in this mode (customers belong to one brand and one mode).Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
scope_required400The request names no brand (an org or entity key without Ownrecord-Brand).Call the operation with credentials or a target at its level: an organization, a legal entity, a brand or the platform (details.required_scope).
livemode_not_allowed403You have no live-mode access, so you can't act on live customers.Use test mode, or credentials for the target's mode. Developers need live access granted by an organization owner or admin.
permission_denied403You can't read this brand's customers (customers:read).Ask an organization owner or admin for a role or scope that allows this action.

It can also return these common errors: api_version_unsupported, authentication_required, api_key_invalid, dry_run_not_supported, rate_limited, internal_error.