Skip to main content
BunShip integrates Stripe to handle subscriptions, checkout, usage tracking, and customer self-service. Every organization starts on the Free plan and can upgrade through Stripe Checkout.

Plans and Pricing

Three plans are defined in packages/config/src/billing.ts: All paid plans offer monthly and yearly billing. Yearly billing saves roughly 17%.

Configuring Plans

Plan configuration lives in a single file. Each plan defines its Stripe price IDs, usage limits, and feature list:
Set the STRIPE_PRO_MONTHLY_PRICE_ID, STRIPE_PRO_YEARLY_PRICE_ID, STRIPE_ENTERPRISE_MONTHLY_PRICE_ID, and STRIPE_ENTERPRISE_YEARLY_PRICE_ID environment variables to match the price IDs in your Stripe dashboard.

Checkout Flow

When a user upgrades, BunShip creates a Stripe Checkout Session linked to the organization:
1

User selects a plan

Your frontend calls POST /api/v1/billing/checkout with the desired priceId.
2

BunShip creates a Stripe customer

If the organization does not yet have a Stripe customer, one is created automatically and stored in the subscriptions table.
3

Redirect to Stripe Checkout

The API returns a Checkout Session URL. Redirect the user to complete payment.
4

Stripe webhook confirms subscription

After payment, Stripe sends a checkout.session.completed webhook. BunShip updates the local subscription record with the plan ID, status, and billing period.

Customer Portal

Stripe’s Customer Portal lets users manage their payment methods, view invoices, and cancel subscriptions without any custom UI:
Call POST /api/v1/billing/portal to generate a portal session URL, then redirect the user.

Usage Tracking and Limits

BunShip tracks resource usage per organization and compares it against the current plan’s limits. The getUsage function queries counts in parallel:
The response includes current usage, plan limits, and a percentage for each resource:
A limit of -1 means unlimited (Enterprise plan). Use the helper functions from @bunship/config:

Webhook Handling

BunShip automatically processes Stripe webhook events to keep subscription state in sync. The following events are handled:
Set STRIPE_WEBHOOK_SECRET in your environment to verify webhook signatures. Without it, BunShip cannot validate that events come from Stripe.

Cancellation

Subscriptions cancel at the end of the current billing period rather than immediately. This gives users access to paid features until their prepaid time expires:

Invoices

Retrieve an organization’s invoice history from Stripe:
Each invoice includes the amount, status, PDF download link, and hosted payment page URL.

Testing with Stripe Test Mode

During development, BunShip uses Stripe’s test mode. No real charges are made.
1

Set test keys

Use your Stripe test secret key and webhook secret in .env: bash STRIPE_SECRET_KEY=sk_test_... STRIPE_WEBHOOK_SECRET=whsec_...
2

Use test card numbers

Stripe provides test card numbers for different scenarios: - 4242 4242 4242 4242 — Successful payment - 4000 0000 0000 3220 — 3D Secure required - 4000 0000 0000 0002 — Declined
3

Forward webhooks locally

Use the Stripe CLI to forward webhook events to your local server: bash stripe listen --forward-to localhost:3000/api/v1/webhooks/stripe
4

Trigger test events

stripe trigger checkout.session.completed stripe trigger customer.subscription.updated

Environment Variables