Stripe for web
Web checkout with a restricted key, and a webhook Contrast registers for you.
Stripe covers the web side of monetization: checkout, web subscriptions, and one-time payments. It pairs with RevenueCat rather than competing with it; the architecture the installed skills build reconciles both providers into the same app-owned subscription row, so a user who subscribes on the web is premium in the native app and vice versa.
Create the keys
In the Stripe dashboard, collect two keys. Use test mode first; switch both keys to live together only after the checkout and webhook flow pass end to end.
- A restricted key, not the unrestricted secret key. Grant only what the integration uses: Account read, Checkout Sessions write, Customers write, Prices and Products read, Subscriptions read and write, Invoices and Charges read (for revenue metrics), and Webhook Endpoints read and write (for deploy-time registration).
- The publishable key for Stripe.js in the browser.
Connect
Open Project Settings → Integrations, pick Stripe, paste both values, and press Verify:
| Secret | Runtime | Purpose |
|---|---|---|
STRIPE_RESTRICTED_KEY | Server only | Checkout sessions, subscription reconciliation, revenue metrics |
VITE_STRIPE_PUBLISHABLE_KEY | Client | Stripe.js in the app client |
Verification probes the Stripe API with the restricted key and reports
exactly what is missing if it fails. A third secret,
STRIPE_WEBHOOK_SECRET, is created for you at deploy time; you never make it
by hand.
What connecting teaches your agents
The installed skill has agents build checkout the way Stripe’s own docs recommend and most first implementations get wrong:
- Checkout Sessions are created on the server with the restricted key, from a server-owned map of plan names to Stripe price ids. The client never chooses a price or amount the server trusts.
- Success pages are confirmation UI, not proof of payment. Durable access comes from the webhook-reconciled subscription row.
- The webhook route verifies the
Stripe-Signatureheader on the raw body before acting, handles events idempotently by recorded event id, and upserts the samesubscriptionrow RevenueCat writes.
The deploy-time webhook
When a project with verified Stripe deploys to production, Contrast registers
the Stripe webhook endpoint for the deployed app’s /api/webhooks/stripe
route, stores the signing secret as the server-only STRIPE_WEBHOOK_SECRET,
and injects it into the deployed worker. A redeploy updates the existing
endpoint rather than adding another. Do not create a second endpoint for the
same route in the Stripe dashboard.
This is the piece that makes web subscriptions durable in production without manual webhook setup: the deploy is what wires payment events to your app’s subscription row.
Revenue
A verified Stripe integration feeds the Revenue pane in the Production section the same way RevenueCat does: MRR, 7/30/90-day revenue, active subscriptions, and trials. A Live or Sandbox pill on the pane says which mode the numbers come from, so test-mode revenue is never mistaken for real money.