The Billing API integrates with Stripe to handle subscription checkout, customer portal access, subscription queries, and lifecycle events. All billing endpoints are mounted underDocumentation Index
Fetch the complete documentation index at: https://docs.shipfastai.dev/llms.txt
Use this file to discover all available pages before exploring further.
/api/billing/. Protected endpoints require a valid Bearer token for the authenticated user.
You must configure
STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET in your backend environment variables before these endpoints will work. See your backend .env for the required keys.POST /api/billing/create-checkout-session
Create a Stripe Checkout session for a subscription. If the authenticated user does not yet have a Stripe customer record, one is created automatically using their name and email. Returns the Stripe-hosted checkout URL to redirect the user to. Headers:Bearer <access_token>The Stripe Price ID for the subscription plan (e.g.,
price_1OqXxxxxxYYYYYYYY). You can find price IDs in the Stripe Dashboard or via the Stripe CLI.The Stripe-hosted checkout URL. Redirect the user’s browser to this URL to complete payment.
{FRONTEND_URL}/dashboard?success=true. If the user cancels, Stripe redirects to {FRONTEND_URL}/pricing?canceled=true.
POST /api/billing/create-portal-session
Create a Stripe Customer Portal session for the authenticated user. The portal lets the user manage their subscription, update payment methods, view invoices, and cancel. The user must have an existing Stripe customer record (created automatically at checkout). Headers:Bearer <access_token>stripe_customer_id stored on the authenticated user.
The Stripe-hosted billing portal URL. Redirect the user’s browser to this URL.
{FRONTEND_URL}/dashboard.
Returns 400 with {"detail": "No billing account found"} if the user has never completed a checkout session and therefore has no Stripe customer ID.
GET /api/billing/subscription
Return the current subscription status for the authenticated user. Headers:Bearer <access_token>Current subscription status (e.g.,
free, active, cancelled, past_due).Current subscription tier (e.g.,
free, pro).The Stripe customer ID associated with the user, or
null if no Stripe record exists.GET /api/billing/plans
Return the list of available subscription plans with their features. This endpoint does not require authentication.Array of available subscription plans.
POST /api/billing/webhook
Stripe webhook endpoint. This endpoint is called directly by Stripe — not by your application. Stripe sends signed events here to notify your backend of subscription changes. Headers required by Stripe:The
Stripe-Signature header added automatically by Stripe. The backend verifies this signature against your STRIPE_WEBHOOK_SECRET to confirm the event is authentic.Handled events
| Event type | Effect |
|---|---|
checkout.session.completed | Sets subscription_status to active and determines subscription_tier from the checkout line items using the configured price-to-tier mapping. |
customer.subscription.updated | Updates subscription_status on the matching user to the new Stripe subscription status. |
customer.subscription.deleted | Sets subscription_status to cancelled and subscription_tier to free for the customer. |
invoice.payment_failed | Sets subscription_status to past_due for the customer. |
400 for an invalid payload or a failed signature verification.
Local testing with the Stripe CLI
To test webhooks locally, forward events from Stripe to your running dev server:STRIPE_WEBHOOK_SECRET in your local .env while testing.