Build
Connect Stripe
Stripe is required. UsageGate does not replace Checkout — you keep collecting money in your Stripe. We listen for paid invoices and subscription updates, refill balances, and set the billing period end (resetAt) from Stripe's current_period_end.
Why Stripe is required
- Paid plan refills happen on
invoice.paid/customer.subscription.updated - The billing period clock comes from Stripe — see How billing periods work
- Cancel / unpaid status zeros entitlements so access stops with the subscription
You still use grant() for free-tier seeds, trials, and admin overrides — but every paid renewal path goes through Stripe.
1. Add a webhook on your Stripe account
https://YOUR_USAGEGATE_HOST/api/webhooks/stripeEvents: invoice.paid, customer.subscription.updated. Save the signing secret (whsec_…) on Stripe in UsageGate, or via the SDK:
await gate.configureStripe({
webhookSecret: "whsec_...",
accountHint: "acct_your_stripe",
});2. Local testing
stripe listen --forward-to localhost:43123/api/webhooks/stripe
stripe trigger invoice.paid3. Bridge paying customers to end users
Put your app’s user id and grant map on the Stripe subscription:
{
"end_user_id": "usr_maya",
"feature_grants": "{\"ai_credits\":50000,\"export_pdf\":1}"
}When Maya upgrades or renews: Stripe fires the event → we verify the signature → set balances absolutely → set resetAt to current_period_end → next canAccess succeeds until that period ends. Duplicate events are claimed idempotently.
What you stop doing
- Parsing invoices in your app to toggle features
- Storing credit balances in your own DB by hand
- Debugging “did this webhook already run?” race bugs
- Building your own month-end reset job
