Hype StackHypeStack

Billing (Stripe)

Stripe integration, subscriptions, and billing flows. This is the pack-billing-stripe pack.

What you need

  • A Stripe account. Sign up at dashboard.stripe.com.
  • Postgres and Valkey (subscription status is cached in Valkey, keyed by organization).
  • Optionally Resend for receipt emails. If RESEND_API_KEY is set, the pack sends receipts; otherwise it skips email.

Stripe credentials

From the Stripe dashboard, grab:

  • Secret key (STRIPE_SECRET_KEY) from API Keys.
  • Webhook signing secret (STRIPE_WEBHOOK_SECRET) from Webhooks, or create one locally with the Stripe CLI (below).
  • Price IDs for the plans you sell (STRIPE_PRICE_PRO, STRIPE_PRICE_PREMIER in the pack's env schema).

Data model

There is no Prisma "subscriptions" table in this pack. Billing state is org-scoped and stored in Valkey:

Key patternMeaning
stripe:org:{organizationId}Stripe customer id for that organization
stripe:customer:{customerId}Cached subscription / billing status

Checkout, portal, and webhook sync code live under apps/backend/src/features/billing/ and apps/backend/src/libs/stripe/. Organization admins get MANAGE:BILLING through the pack's permission grants.

Checkout and portal flow

Subscribe an organization

  1. Create checkout

    The frontend calls the billing module. The backend creates a Stripe Checkout session for the org's customer (creating one if needed).

  2. Customer pays in Stripe

    Stripe hosts the checkout UI. Success returns to the pack's checkout-success route.

  3. Webhook sync

    POST /checkout/webhook verifies the signature, then syncs customer and subscription status into Valkey.

  4. Customer portal

    create-billing-portal opens Stripe's portal for plan changes and invoices against the same org customer.

Webhook endpoint

The pack exposes a Stripe webhook receiver at:

POST /checkout/webhook

In production, create a webhook endpoint in Stripe pointing at https://your-api-origin/checkout/webhook, subscribe to the events the pack handles (checkout, subscription, customer), and copy the signing secret into STRIPE_WEBHOOK_SECRET.

Local development with the Stripe CLI

Stripe cannot reach localhost over the internet, so use the Stripe CLI to forward events. Install it from stripe.com/docs/stripe-cli, then:

bash
stripe listen --forward-to localhost:3000/checkout/webhook

The CLI prints a whsec_... signing secret. Put it in STRIPE_WEBHOOK_SECRET.

Failure and retry notes

  • Signature verification failures reject the webhook. Fix the secret before debugging business logic.
  • Sync helpers update the Valkey cache from Stripe's customer / subscription objects. If the UI looks stale after a portal change, confirm the webhook events are arriving and the org → customer mapping exists.
  • Receipt email is best-effort: without RESEND_API_KEY the send path returns early and checkout still succeeds.

Environment variables

VariablePurpose
STRIPE_SECRET_KEYStripe API secret key
STRIPE_WEBHOOK_SECRETSigning secret for the webhook endpoint
STRIPE_PRICE_PROStripe Price ID for Pro
STRIPE_PRICE_PREMIERStripe Price ID for Premier
RESEND_API_KEYOptional. Enables receipt emails

In the admin

On top of a starter, this pack adds a revenue row to the admin app dashboard, a billing card on the organization details page, and /admin/billing API routes. Nothing extra to configure beyond Stripe env vars; the UI shows up once both packs are installed.

Sponsor open source

Every purchase and sponsorship funds my 8+ years of work on open source given freely to the community. It keeps the lights on, funds new packs, and keeps the ecosystem alive. Even a small tier means a lot. Thank you!

Sponsor on GitHub