Skip to content

Entitlements

All endpoints require a valid API key in the Authorization header.

Check entitlement

The fastest way to check if a customer has access to a product. Optimized for low latency.

Terminal window
GET /v1/entitlements/check?customer_id={customer_id}&product_id={product_id}

Scope: entitlements:read

Query parameters

ParameterDescription
customer_idCustomer ID (or use shopify_customer_id)
shopify_customer_idShopify customer ID (alternative to customer_id)
product_idProduct ID (or use shopify_product_id)
shopify_product_idShopify product ID (alternative to product_id)

Response

{
"data": {
"entitled": true,
"entitlement": {
"id": "ent_abc123",
"product_id": "prod_xyz",
"status": "active",
"granted_at": "2026-01-15T10:00:00.000Z",
"expires_at": null,
"metadata": {},
"access_type": "direct"
}
},
"meta": { "request_id": "req_abc123", "timestamp": "2026-03-01T12:00:00.000Z" }
}

Returns { "entitled": false, "entitlement": null } if the customer does not have access — never a 404.


List entitlements

Terminal window
GET /v1/entitlements

Scope: entitlements:read

Requires at least one filter parameter.

Query parameters

ParameterDefaultDescription
customer_idFilter by customer ID
shopify_customer_idFilter by Shopify customer ID
product_idFilter by product ID
statusFilter by status: ACTIVE, EXPIRED, REVOKED, SUSPENDED, PENDING
sourceFilter by source: ORDER, MANUAL, RULE, API, BUNDLE, SUBSCRIPTION, FLOW, IMPORT
granted_afterISO 8601 timestamp
granted_beforeISO 8601 timestamp
limit25Number of results (1–100)
cursorPagination cursor

Response

{
"data": [
{
"id": "ent_abc123",
"customer_id": "cust_123",
"shopify_customer_id": "7890",
"product_id": "prod_xyz",
"status": "active",
"granted_at": "2026-01-15T10:00:00.000Z",
"expires_at": null,
"revoked_at": null,
"revocation_reason": null,
"usage_count": 0,
"usage_limit": null,
"source": "order",
"shopify_order_id": "6001234567890",
"metadata": {},
"created_at": "2026-01-15T10:00:00.000Z",
"updated_at": "2026-01-15T10:00:00.000Z"
}
],
"meta": { "request_id": "req_abc123", "timestamp": "2026-03-01T12:00:00.000Z" },
"pagination": {
"total": 1,
"limit": 25,
"has_more": false,
"next_cursor": null
}
}

Get entitlement

Terminal window
GET /v1/entitlements/{entitlement_id}

Scope: entitlements:read

Response

Returns the full entitlement object (same shape as list items, plus shopify_line_item_id and parent_entitlement_id).


Create entitlement

Terminal window
POST /v1/entitlements

Scope: entitlements:write

Request body

{
"customer_id": "cust_123",
"product_id": "prod_xyz",
"expires_at": "2026-06-01T00:00:00.000Z",
"usage_limit": 10,
"metadata": { "campaign": "spring-launch" },
"idempotency_key": "unique-key-123"
}
FieldRequiredDescription
customer_idYes*Customer ID (*or shopify_customer_id)
shopify_customer_idYes*Shopify customer ID (*or customer_id)
product_idYes*Product ID (*or shopify_product_id)
shopify_product_idYes*Shopify product ID (*or product_id)
expires_atNoISO 8601 expiration timestamp
usage_limitNoMaximum number of uses
metadataNoArbitrary JSON object
idempotency_keyNoPrevents duplicate creation

Response

201 Created

{
"data": {
"id": "ent_abc123",
"customer_id": "cust_123",
"product_id": "prod_xyz",
"status": "active",
"granted_at": "2026-03-01T12:00:00.000Z",
"expires_at": "2026-06-01T00:00:00.000Z",
"source": "api",
"metadata": { "campaign": "spring-launch" },
"created_at": "2026-03-01T12:00:00.000Z"
},
"meta": { "request_id": "req_abc123", "timestamp": "2026-03-01T12:00:00.000Z" }
}

Update entitlement

Terminal window
PATCH /v1/entitlements/{entitlement_id}

Scope: entitlements:write

Request body

{
"expires_at": "2026-12-31T23:59:59.000Z",
"metadata": { "campaign": "extended" }
}

Both fields are optional. Only provided fields are updated.


Revoke entitlement

Terminal window
POST /v1/entitlements/{entitlement_id}/revoke

Scope: entitlements:write

Request body

{
"reason": "Refund processed"
}

The reason field is optional. Publishes an entitlement.revoked webhook event.


Suspend entitlement

Terminal window
POST /v1/entitlements/{entitlement_id}/suspend

Scope: entitlements:write

Request body

{
"reason": "Payment dispute"
}

The reason field is optional. Publishes an entitlement.suspended webhook event. Use reactivate to restore access.


Reactivate entitlement

Terminal window
POST /v1/entitlements/{entitlement_id}/reactivate

Scope: entitlements:write

Reactivates a suspended or expired entitlement. Publishes an entitlement.reactivated webhook event.


Status transitions

Not all status transitions are valid. The API returns 409 Conflict for invalid transitions.

FromAllowed transitions
ACTIVEsuspended, revoked, expired
SUSPENDEDactive (reactivate), revoked
EXPIREDactive (reactivate)
REVOKED— (terminal)
PENDINGactive, revoked