Skip to content

Override an entitlement

The customers.entitlement_overrides.create operation: POST /api/v1/customers/{id}/entitlement_overrides in the REST API and the customers_entitlement_overrides_create tool in the MCP server.

POST/api/v1/customers/{id}/entitlement_overrides

Grants a customer a value of one feature, with a reason and an optional expiry, e.g. 20 extra seats while a team migrates or feature.export = true as a goodwill gesture. The override is one more source of the customer's entitlements and merges with the others by the feature's combine rule: with max it raises a limit, with sum it adds to it, with or it can only switch a feature on, and with first it decides (the newest override comes first).

It applies until expiresAt (exclusive), or until deleted; for a customer on a test clock, expiresAt is a time on the clock (#541). The customer's entitlements are recomputed within one job cycle, and customer.entitlements.updated is sent when a value changes. Needs customers:write (owners, admins and support); the reason goes to the override and the audit log.

At a glance

  • REST: POST /api/v1/customers/{id}/entitlement_overrides
  • MCP tool: customers_entitlement_overrides_create
  • Operation ID: customers.entitlement_overrides.create
  • Scope: Brand
  • Permission: customers:write
  • Risk tier: write
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the customers:write scope
  • Since: M5

Request

Path parameters

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

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
featureKeystringYesThe feature to grant a value of, e.g. seats.max.
valueboolean or number or stringYesThe value to grant: true/false for a boolean feature, a whole number ≥ 0 for a limit, one of the values of an enum feature. It merges with the customer's other values by the feature's combine rule.
reasonstringYesWhy the customer gets this; stored on the override and in the audit log.
expiresAtdate-timeNoWhen the override stops applying (exclusive). Must be in the future. Omit for no expiry.

Response

201 Created with a JSON object:

FieldTypeDescription
idceo_… ID
object"entitlement_override"
customerIdcus_… ID
brandIdbrd_… ID
livemodeboolean
featureKeystring
valueboolean or number or string
reasonstring
setByobjectWho granted it.
setBy.typestring
setBy.idstring
expiresAtdate-time or null
activebooleanWhether the override applies at the time of the request (not expired).
createdAtdate-time

Examples

Extra seats for a month

HTTP
POST /api/v1/customers/cus_01m4ty3c2b5qx7mhd9k8w6s0aa/entitlement_overrides
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "featureKey": "seats.max",
  "value": 20,
  "reason": "Goodwill while their team migrates (ticket 4821)",
  "expiresAt": "2026-11-14T00:00:00.000Z"
}

Response (201):

JSON
{
  "id": "ceo_01m4ty3c2b5qx7mhd9k8w6s0b2",
  "object": "entitlement_override",
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "featureKey": "seats.max",
  "value": 20,
  "reason": "Goodwill while their team migrates (ticket 4821)",
  "setBy": {
    "type": "user",
    "id": "usr_01m4ty3c2b5qx7mhd9k8w6s0b4"
  },
  "expiresAt": "2026-11-14T00:00:00.000Z",
  "active": true,
  "createdAt": "2026-10-14T10:00:00.000Z"
}

Switch a feature on for good

HTTP
POST /api/v1/customers/cus_01m4ty3c2b5qx7mhd9k8w6s0aa/entitlement_overrides
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "featureKey": "feature.export",
  "value": true,
  "reason": "Beta tester"
}

Response (201):

JSON
{
  "id": "ceo_01m4ty3c2b5qx7mhd9k8w6s0b3",
  "object": "entitlement_override",
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "featureKey": "feature.export",
  "value": true,
  "reason": "Beta tester",
  "setBy": {
    "type": "user",
    "id": "usr_01m4ty3c2b5qx7mhd9k8w6s0b4"
  },
  "expiresAt": null,
  "active": true,
  "createdAt": "2026-10-14T10:00:00.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400A field is missing or malformed, the reason is empty, or expiresAt isn't in the future.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.
customer_deleted400The customer was deleted.Create a new customer for this buyer. Deleted customers stay readable for the records they belong to, but can't be changed.
entitlement_feature_not_found400The brand has no feature with this key in this mode.Check the feature key against features.list (test and live mode have separate features), or create the feature first with features.create.
entitlement_value_invalid400The value doesn't fit the feature: true/false for booleans, a whole number ≥ 0 for limits, a listed value for enums.Use true or false for boolean features, a whole number of 0 or more for limits, and one of the listed values for enum features.
entitlement_override_limit409The customer already has 100 active overrides.Delete overrides the customer no longer needs (customers.entitlement_overrides.delete), or let expiring ones run out, then try again.
idempotency_key_reused409The idempotency key was used before with another input.Use a new Idempotency-Key for a different request, or resend the original request unchanged.
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 change this brand's customers' entitlements (customers:write: owners, admins and support).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, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_key_required, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.