Subscriptions
Subscriptions connect organizations to plans through the active payment gateway. The billing system handles checkout, cancellation, resumption, invoices, and webhook events.
API Routes
POST /api/billing/subscribe # Create checkout session
GET /api/billing/subscription # Current subscription details
DELETE /api/billing/subscription # Cancel at period end
POST /api/billing/subscription/resume # Resume cancelled subscription
GET /api/billing/invoices # List invoices
POST /api/billing/portal # Get billing portal URL
Checkout Flow
When a user subscribes to a plan:
- The client sends
POST /api/billing/subscribewith the plan slug and billing interval - The server resolves the active gateway driver and calls
checkoutUrl() - The gateway returns a hosted checkout URL (Stripe Checkout, Paddle overlay, etc.)
- The user is redirected to complete payment on the gateway's hosted page
- On success, the gateway sends a webhook to confirm the subscription
{
"plan": "pro",
"interval": "monthly"
}
The response contains the checkout URL for the client to redirect to:
{
"checkout_url": "https://checkout.stripe.com/c/cs_live_..."
}
Cancellation
Cancelling a subscription does not take effect immediately. The subscription remains active until the end of the current billing period:
DELETE /api/billing/subscription
- The subscription is marked as cancelling (ends at period end)
- The user retains full access until the period expires
- A
SubscriptionCancelledNotificationis sent to the organization owner
Resumption
A cancelled subscription can be resumed before the current period ends:
POST /api/billing/subscription/resume
- Only works if the subscription has not yet expired
- Removes the cancellation flag and continues billing normally
Webhook Handling
The BillingWebhookController processes events from the active gateway. Each gateway sends different event names, but the controller normalizes them into common actions:
- payment_succeeded — Activates or renews the subscription
- subscription_cancelled — Marks the subscription as cancelled
- payment_failed — Flags the subscription and notifies the owner
- subscription_updated — Syncs plan changes made outside the app
POST /api/billing/webhook # Gateway webhook endpoint
Webhook signatures are verified using the gateway's webhook secret to prevent spoofed events.
Notifications
Billing events trigger notifications to the organization owner:
SubscriptionActivatedNotification— Sent when a subscription is successfully created or renewedSubscriptionCancelledNotification— Sent when a subscription is cancelledPaymentFailedNotification— Sent when a payment attempt fails, prompting the user to update their payment method