Check Entitlements

Entitlements enable you to gate features based on what Plans a Grantee has subscribed to in your product. Checking entitlements instead of hardcoding Plan logic is what lets you change your pricing without changing your code.

Related Sales can agree a bespoke deal, move that customer to a bespoke Plan with its own features and price, and your application keeps gating access correctly with no redeployment. Moving a feature between tiers, launching a new Plan, or running a promotion all work the same way.

Prerequisites

First, we need to configure a Plan with at least one Entitlement attached, create one Entitlement per feature in your application. Then subscribe a customer to that Plan, either through a checkout link or by creating a Salable Only Subscription.

The Grantee's ID

This is what identifies the entity consuming the feature. If a user is accessing the feature, the granteeId is their ID in your system, but this value can be any string you wish to check access against, like a workspace ID or a project ID.

Run the check

Call GET /api/entitlements/check with the Grantee's ID. The response returns every Entitlement that the Grantee currently holds, so gate your feature by checking whether the Entitlement's slug appears in the set.

import { Salable } from '@salable/sdk';
const salable = new Salable(process.env.SALABLE_SECRET_KEY);
 
const { data } = await salable.api.entitlements.check.get({
    queryParameters: {
        granteeId: 'user_01HX...'
    }
});
 
const hasAccess = data.entitlements.some(entitlement => entitlement.value === 'advanced_analytics');

Tip Optionally add an owner query param to scope the check to a single tenant, like a team or organisation ID. Passing owner also returns the Plan's meter slugs (type: 'meter'), which you use to record usage against that tenant.

Returned Entitlements come from every active or trialing Subscription associated with a Group the Grantee belongs to. Each Entitlement's expiryDate is the latest expiry across the Subscription Plan's Line Items, or null for perpetual Subscriptions. The response also carries a signature; verify it to confirm the payload has not been tampered with.

Important If there has been a payment failure on a customer's Subscription for a reason like an expired card, the Subscription status moves to past_due. If you don't want Grantees to lose their access during Stripe's automatic retry period, enable the Past Due Entitlements setting on the Plan's Product. To let the customer update their billing details, create a billing portal with the paymentMethodUpdate option enabled.

Anonymous users have no Grantee in Salable yet, so a check returns 404, as does an owner value that matches no Owner.

An existing Grantee in Salable with no valid Subscription returns 200 with an empty entitlements array rather than a 404, so treat an empty array as unentitled instead of an error.

Debug a response

When a check returns a response you don't expect, open the dashboard's Entitlement Check page. Enter the Grantee's ID, and the dashboard returns the same Entitlements the API would, so you can confirm whether the bug lives in your call site or in the Plan configuration.