Checking paid access in your app's server code

Check the signed-in buyer’s current plans before running a paid server feature.

A paid feature should check access on the server before doing its work. Hiding a button in the browser is not enough.

The platform's server-side getEntitlements(request, env) helper checks the signed-in caller's current purchases for the app. It derives the buyer from their signed request; your app should not accept a user ID supplied by a visitor as proof of payment.

Ask the builder for the outcome

For example: Require sign-in and an active entitlement to this product before running this paid feature. If purchase verification is unavailable, ask the user to try again and do not run the paid work.

The helper throws an error when sign-in is absent or purchase verification is unavailable. Do not convert a verification failure into free access.

Purchases and cancellations

The platform handles the payment provider's membership events. Your app can check the resulting current access without keeping a second, independently maintained list of paid members.

Cancellation normally stops renewal while preserving the already-paid period. Check the actual current entitlement rather than assuming that a cancellation request means immediate loss of access.

Publish and test with a buyer who has the plan and an account that does not. The editor's $0 test order can test a grant, but it is not a real provider checkout: see Test your checkout without paying.

This is an access check, not a transaction ledger or a documented subscription-event feed for your own billing system. If you need a grant for every purchase or paid period, verify that separate contract before building it.

Purchase IDs and custom consumable allowances

The current entitlement result includes membership_id, plan_id, product_plan_id, kind, status, entitlement_type, period_end and other display fields. membership_id is the platform's membership record ID, not a payment-provider transaction ID. Distinct one-time purchases can have distinct membership IDs even when they use the same plan.

If an existing custom ledger grants a one-time allowance from a membership, deduplicate by the membership ID rather than just the plan ID. The grant and its deduplication record need to be atomic; a browser-only check cannot guarantee that.

This result is a current-access view, capped at 50 entitlements. It is not a complete purchase-history API. It does not supply a unique successful-payment ID for every renewal, purchase quantity, both paid-period boundaries, or a refund/chargeback event linked to the original transaction. period_end alone does not prove that a new paid period has settled, and trial access is not proof of a paid charge.

Do not build a renewable consumable balance by treating each access check as a new purchase. Confirm a supported fulfillment contract for that use case first. Built-in buyer AI credits are a separate feature for metered AI usage.

Was this helpful?

Thanks for the signal — it helps us improve the docs.

More in Payments and selling

Selling your app

Charge for access to your app with subscriptions or one-time purchases. Share a free remix link when you want others to make their own copy.

Identity verification not working

If your payout identity verification keeps failing or looping, here's what to check — and how we escalate to our payments partner if it's still stuck.

Setting prices and subscriptions

Pick a price model that fits your app — monthly, yearly, one-time, tiered, or all of the above.

Still need help?

If this didn't answer your question, our team is one click away.