Billing
Keel uses Stripe-hosted Checkout and Billing Portal flows with webhook sync.
Required environment keys
STRIPE_SECRET_KEY=
STRIPE_PUBLISHABLE_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_PRICE_PRO_MONTHLY=
Routes
$router->get('/billing/upgrade', [BillingController::class, 'showPlans']);
$router->post('/billing/checkout', [BillingController::class, 'checkout']);
$router->post('/billing/portal', [BillingController::class, 'portal']);
$router->post('/webhooks/stripe', [StripeWebhookController::class, 'handle']);
Operational notes
- Checkout sessions are created in
BillingService::createCheckoutSession(). - Portal sessions are created in
BillingService::createPortalSession(). - Webhook signatures are verified against
STRIPE_WEBHOOK_SECRETbefore sync logic runs. - Billing state is mirrored into the local
subscriptionstable. - Raw card data never passes through Keel application code.