Entitlements
Entitlements are the access records your app owns after a payer completes delegated checkout: orders, memberships, subscriptions, credits, seats, downloads, or anything else your product unlocks.
A merchant Proxy webhook endpoint is not required to create a handoff or open a payment-level checkout. Add one when your app needs Proxy events to grant or update access, especially for production fulfillment and subscriptions.
Configure The Endpoint
Section titled “Configure The Endpoint”Create a webhook endpoint in Proxy that points to your backend:
https://app.example.com/api/proxy/webhookSave the endpoint signing secret as PROXY_WEBHOOK_SIGNING_SECRET.
For one-time purchases, subscribe to:
proxy_session.paidproxy_session.provisionableproxy_session.cancelledproxy_session.failedproxy_session.expired
For subscriptions, also subscribe to:
subscription.renewedsubscription.payment_failedsubscription.cancel_scheduledsubscription.cancelled
Handle Entitlement Events
Section titled “Handle Entitlement Events”Use the server SDK to verify the webhook and resolve the latest Proxy state before updating access.
import { createProxyCheckoutServerClient, type ResolvedProxyEvent,} from "@proxy-checkout/server-js";
const proxy = createProxyCheckoutServerClient({ apiKey: process.env.PROXY_SECRET_KEY!,});
// POST /api/proxy/webhookexport async function POST(request: Request) { return proxy.webhooks.handle(request, { secret: process.env.PROXY_WEBHOOK_SIGNING_SECRET!, async onResolved(resolved) { await updateEntitlements(resolved); }, });}
async function updateEntitlements(resolved: ResolvedProxyEvent) { switch (resolved.kind) { case "initial_provision": // Grant access for resolved.session.buyerReference. // Key the write by resolved.session.id so repeated deliveries are safe. return; case "subscription_renewed": // Extend or confirm subscription access. return; case "subscription_cancel_scheduled": // Keep access through the current period and mark non-renewing. return; case "subscription_cancelled": // End access according to your product policy. return; case "payment_risk": // Apply your dunning or restricted-access policy. return; case "terminal_session": // Mark the delegated purchase failed, expired, or unavailable. return; case "ignored": case "payment_attempt": return; }}Do not grant access from raw webhook payload fields alone. The handler verifies the signature and re-reads current Proxy state before calling onResolved.
Idempotency
Section titled “Idempotency”Webhook deliveries can repeat. Make entitlement writes idempotent by keying them to your own access record plus the Proxy object that caused the update:
- one-time access:
resolved.session.id - subscription access:
resolved.subscription.id - buyer-owned access:
resolved.session.buyerReference
For a Proxy-mediated delegated purchase, do not also grant access from a direct Stripe webhook path for the same order or subscription. Stripe should send payment evidence to Proxy, and Proxy should send normalized, signed events to your backend.