Introduction
This page is for a specific integration problem: payment looks successful, but access is still not active yet.
A common real-world scenario looks like this: the user completes Stripe Checkout, lands on a success page, and then immediately tries to use the product, but access is still not active.
That is usually expected when billing confirmation and webhook-driven backend state have not fully settled yet. The browser may already show a successful payment flow while your runtime access state is still waiting for webhook processing to finish.
In this model, access must come from backend runtime state, not from a frontend redirect or success URL. Licenzy answers that post-payment access decision from entitlements updated after billing webhooks are processed.
Why payment and access are different decisions
Stripe confirms payment flow. Your product still needs a separate decision about access.
- Stripe handles payment collection and billing events.
- Licenzy processes webhook-confirmed billing updates.
- Licenzy updates entitlement-backed runtime state.
- Your backend should verify access from that resulting state.
That separation is what keeps access reliable when retries happen, billing changes, or frontend state becomes stale.
Licenzy solves this by making access a direct function of entitlement state updated by Stripe webhooks, removing the need for custom billing-to-access logic.
Recommended flow
- Create checkout through checkout session.
- Let Stripe and Licenzy process billing updates through webhooks.
- Check access from your backend with
POST /v1/access/check. - If needed, read richer customer or entitlement state through
GET /v1/customer/access/:subject_reforGET /v1/entitlements/:subject_ref.
This keeps the access decision server-side and tied to the same commercial state used everywhere else in the runtime API.
Example access check
A clean backend access check is usually enough for protected routes, paid features, or post-purchase verification.
const response = await fetch("https://api.licenzy.app/v1/access/check", {
method: "POST",
headers: {
Authorization: "Bearer lz_test_***",
"Content-Type": "application/json",
},
body: JSON.stringify({
subject_ref: "user_123",
}),
});
const result = await response.json();
// { subject_ref: "user_123", allowed: true }{
"subject_ref": "user_123",
"allowed": false
}When you need more than a boolean answer, use customer access or entitlement reads for support views, account pages, or debugging.
Common mistakes
- Trusting a browser success page as proof that access is already active.
- Enabling access too early, before webhook-driven entitlement updates finish.
- Checking access from the frontend only instead of from a backend runtime path.
- Reading payment success as if it were the same thing as current access state.