This guide will show how to gate premium features on an end user’s effective entitlement and flip a user from free to pro after they purchase. Your users pay you — through StoreKit, Google Play Billing, or whatever in-app purchase you use. Roadie is not in that payment path. Its job is to meter, entitle, and limit: you tell Roadie the outcome of a purchase, and it enforces the matching per-plan limits from then on. See Billing & plans for why these two money flows stay separate.

The two plan axes

An end user has two independent plan axes (full detail):
  • Asserted plan — the plan a client or client token claims. Convenient for selecting per-plan limits, but a client controls it, so it can never be the source of truth for paid access.
  • Authoritative entitlement — a tier your backend grants that a client can never set itself. This is what you gate paid features on.
When both are present, the authoritative entitlement wins. It is stamped into the client token’s plan claim at the next mint, so the existing per-plan policy engine enforces it with no gateway change.

1. Define per-plan limits

Gating is enforced through usage controls keyed on the plan. Configure end_user_plan policies — a generous pro tier and a tighter free one — so the plan a user resolves to actually changes what they can do:
Do the same for pro with the higher allowance. Gating premium models is just an allowed_models difference expressed through the plan’s policies.

2. Grant the entitlement after a purchase

When a user buys, your purchase handler — typically an App Store Server Notification or Play RTDN handler — calls the entitlement setter with your secret key:
  • tier — the authoritative tier (pro, free, or your own names). Last-write-wins per user.
  • expires_at — optional; past it, the effective tier falls back to the asserted plan on the next mint.
  • source — optional provenance (storekit, manual, …).
This is the anti-self-upgrade gate: it accepts a secret key only. A client token or a publishable key is rejected with a permission_error, so a client or device can never raise its own tier by calling it. The grant is always stamped with the caller’s own tenant, so cross-tenant writes are impossible.
The call is idempotent and records a “customer since” marker on the first non-free grant that survives later downgrades. See the entitlement endpoint reference.

3. Let the client pick up its new tier

The entitlement takes effect on the next client-token mint. A returning client re-mints when its short-lived token expires (RoadieKit does this automatically), and the new token carries the pro plan claim — at which point the pro limits apply. No app deploy, no gateway change.

4. Downgrades and refunds

To downgrade — a cancellation, refund, or lapse — grant tier: "free". An explicit free entitlement is an authoritative downgrade that overrides an asserted pro, so a client that keeps claiming pro still resolves to free. The “customer since” marker is preserved for your records.

The reserved free_exhausted tier (mobile guard)

free_exhausted is a reserved tier that resolves to an intrinsic hard requests = 0 / month deny — request #1 is refused with a quota_error the instant it is stamped, without any configured policy. The mobile free-tier guard uses it to paywall a device that has burned its monthly free allotment. The deny self-heals when the UTC month rolls over, and a pro grant overrides it at any time — so a device that pays flips straight to pro on its next mint.
Entitlement is read-only in the dashboard — there is no entitlement editor. A grant is always an authenticated PUT from your backend, which keeps your server the sole authority over who is a paying user.

End users & entitlements

The entitlement model in depth.

Free-to-Pro with StoreKit

The end-user monetization flow end to end.

Mobile device auth

Anonymous free devices that can upgrade.

Set usage controls

Define the per-plan limits you gate on.