Entitlements

Check from your own app whether a customer has access to a benefit, and list what they are entitled to, with the Entitlements API.

An entitlement is a customer's right to a benefit they bought. RevKeen grants entitlements when a customer buys a product with benefits attached, and works out whether each one still gives access from the state of the customer's subscription.

Use the Entitlements API to gate features in your own app: before you show a feature, ask RevKeen whether the customer has access to it.

Before you start

  • A secret API key with the customers:read scope. Call the API from your server, never from a browser.
  • The RevKeen customer ID of the signed-in user. Store it against your own user record when the customer first buys.
  • The benefit key of each benefit you gate on, from the benefit's settings in Dashboard > Products > Benefits.

Check access to one benefit

GET /v2/entitlements/check is the call to make before showing a gated feature.

import { RevKeen } from "@revkeen/sdk";

const client = new RevKeen({
  apiKey: process.env.REVKEEN_API_KEY!,
  baseUrl: "https://staging-api.revkeen.com/v2",
});

const { data: check } = await client.entitlements.check({
  customer_id: "3f0c5b2e-8a41-4d6f-9c1e-2b7a9d4e6f10",
  benefit_key: "video_library",
});

if (check.has_access) {
  // Show the feature.
} else {
  // Show an upgrade or payment prompt. check.reason says why.
}
curl "https://staging-api.revkeen.com/v2/entitlements/check?customer_id=3f0c5b2e-8a41-4d6f-9c1e-2b7a9d4e6f10&benefit_key=video_library" \
  -H "x-api-key: $REVKEEN_API_KEY"

The response data contains:

FieldMeaning
has_accesstrue if the customer can use the benefit now
access_levelfull, partial or none
statusThe entitlement status (below), or null if the customer has no entitlement
reasonWhy access is denied, or null when has_access is true
benefitThe benefit, or null if no benefit has that key

An unknown benefit key is not an error. The response has has_access: false, benefit: null and reason: "Benefit not found". Check your keys if you see that reason.

Statuses

Access follows the customer's subscription, so a missed payment does not cut access off at once.

statushas_accessaccess_levelMeaning
activetruefullPaid up
trialingtruefullIn a free trial
gracetruefullA payment is overdue; access continues while the customer updates their payment method
past_duetruefullAccess continues while the payment is retried
restrictedtruepartialPayment significantly overdue; limited access
suspendedfalsenoneAccess suspended until the customer pays
canceledfalsenoneThe subscription has ended

Access follows the latest subscription

The access status is worked out from the customer's most recent subscription. A customer who has an entitlement but no subscription, for example from a one-time purchase, is currently reported as canceled with no access. Test your own products in staging before you gate on them.

Decide in your app what partial means for your product, for example read-only access. Payment retries and grace periods follow your dunning settings.

List a customer's entitlements

Use GET /v2/entitlements to show a customer everything they have, for example on an account page.

const { data: entitlements, pagination } = await client.entitlements.list({
  customer_id: "3f0c5b2e-8a41-4d6f-9c1e-2b7a9d4e6f10",
  limit: 50,
});

for (const entitlement of entitlements) {
  console.log(entitlement.benefit.name, entitlement.status, entitlement.has_access);
}

Expired entitlements are left out unless you pass include_expired=true. You can also filter by benefit_type and category, and page with limit (up to 100) and offset.

Caching

Access can change when a payment fails, a subscription is cancelled or a trial ends. If you cache check results to save requests, keep the cache short, for example a minute, and check again before anything that matters, such as starting a download or a paid action.

Errors

StatusMeaning
400customer_id missing or not a valid ID
401Missing, invalid or revoked API key
404No customer with that ID in your account
429Too many requests; wait for the Retry-After seconds

Owner: david · Reviewed 30 Sep 2026 · Next review 30 Oct 2026

On this page