Stripe setup and operations
Supacharger uses Stripe-hosted Checkout and Customer Portal with an account-based billing model. Stripe is authoritative; Supabase stores a secured, recoverable projection for application reads and access decisions.
Supported contract
- Stripe Node SDK
22.5.0, API and event destinations2026-07-29.dahlia. - New subscriptions use flexible billing mode.
- A billing account represents a user, organisation, team, tenant, or custom billable party.
- Users receive owner, billing-administrator, or member access through billing-account membership.
- One Stripe Customer is mapped per billing account, Stripe account, and live/test mode.
- A Customer can own multiple Subscriptions; each Subscription can contain multiple Items.
- Stripe and application entitlements are projected separately from Prices.
- One-time fulfilment and Stripe Connect are extension contracts, not implicit starter behaviour.
Do not key billing records directly to a login user, assume the first Subscription Item is the plan, or use a Price ID as application authorisation.
Environment
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_EVENT_PROCESSOR_SECRET=<long-random-value>
STRIPE_RECONCILIATION_SECRET=<different-long-random-value>
Secrets are server-only and distinct per environment and purpose. Hosted Checkout does not require Stripe.js, so the canonical application has no browser publishable-key requirement.
SC_CONFIG.BILLING controls Automatic Tax, billing-address collection, and promotion codes. Automatic Tax still requires correct Stripe registrations and Product tax codes. Payment methods are configured in Stripe Dashboard.
Dynamic Payment Methods and Checkout
Supacharger deliberately omits payment_method_types. Stripe therefore presents eligible cards, wallets, bank debits, and local methods according to Dashboard settings, currency, customer location, and payment-flow compatibility.
createCheckoutAction accepts 1–20 line items. The server retrieves every Price from Stripe and requires:
- an active recurring Price;
- a positive integer quantity; and
- one currency across all Items.
Checkout creates or reuses the Customer belonging to the selected billing account, verifies that the current user can manage it, and creates a flexible-mode Subscription. The success redirect is informational; only Stripe events and reconciliation update the billing projection.
Event destination
Create a Sandbox destination for https://<host>/api/webhooks, pin it to 2026-07-29.dahlia, and select only:
product.created,product.updated,product.deleted;price.created,price.updated,price.deleted;checkout.session.completed,checkout.session.async_payment_succeeded,checkout.session.async_payment_failed;customer.subscription.created,customer.subscription.updated,customer.subscription.deleted;customer.subscription.paused,customer.subscription.resumed;entitlements.active_entitlement_summary.updated.
For local development:
stripe listen --forward-to localhost:3000/api/webhooks
Use the signing secret printed for that process. Never select all events.
Processing and reconciliation
The webhook verifies the raw request, atomically records the Event and snapshot payload, acknowledges duplicates, and returns after durable acceptance. A protected worker claims records with leases and retry state. Subscription handlers retrieve current Stripe state and atomically replace the complete Item set because Stripe delivery can be duplicated or out of order.
Schedule authenticated POST requests to:
POST /api/stripe/process-events
Authorization: Bearer <STRIPE_EVENT_PROCESSOR_SECRET>
POST /api/stripe/reconcile
Authorization: Bearer <STRIPE_RECONCILIATION_SECRET>
The reconciliation job enumerates mapped Customers, refreshes all Subscriptions and Items, then replaces Stripe-origin entitlement grants. It reports failures per Customer and leaves manual/promotional grants untouched. Monitor non-empty failures and failed event rows.
Supabase model and security
Internal app tables include:
billing_accountsandbilling_account_members;stripe_customer_mappings, whose localstripe_customer_mapping_idis distinct from Stripe's externalstripe_customer_id;products,prices,subscriptions, andsubscription_items;billing_features,product_features, andentitlement_grants;stripe_eventsandstripe_event_payloads.
Browser reads go through deliberate api functions. Stripe ingestion uses service-only api_edge functions. Tables have explicit grants and RLS; browser roles cannot mutate projections, Customer mappings, entitlements, payment summaries, or event payloads.
After migration:
npx supabase migration list --linked
npm run generate-types
npx supabase db advisors --linked
Test grants and RLS separately as anonymous, authenticated, and service roles.
Customer Portal and advanced changes
Portal sessions are created only after verifying billing-account management authority. Configure supported payment-method changes, invoice history, upgrades, downgrades, and cancellation in Stripe.
Use separately authorised application services for seat allocation, organisation membership, quotes, subscription schedules, complex prorations, or coordinated changes across multiple Subscriptions. Portal configuration must not be treated as the application's access-control policy.
Release verification
Before production, test:
- one user with multiple billing accounts and an organisation with multiple members;
- multiple Subscriptions and multiple Items, including quantities and mixed intervals;
- Dynamic Payment Methods, including delayed methods enabled for the account;
- duplicate, reversed, failing, leased, and replayed events;
- Stripe Entitlement replacement and persistence of manual grants;
- Portal authorisation and return paths;
- flexible-mode upgrade/downgrade and proration behaviour;
- trials, test clocks, renewal, failure, pause, cancellation, and reconciliation;
- fresh and upgrade migrations, generated types, advisors, grants, RLS, lint, tests, and build.
Create independent live destinations and secrets. Stripe Sync Engine is not the default; adopting it requires a separate architecture, access-control, deployment, and operational review.