The billing endpoints are thin wrappers around Stripe. Use them to start a paid subscription, manage an existing one, or accept Stripe webhooks.
POST /api/billing/checkout
Opens a Stripe Checkout session for upgrading to a paid plan.
curl -X POST https://www.mnueron.com/api/billing/checkout \
-H "Authorization: Bearer $MNUERON_API_TOKEN"
Returns { url } — redirect the user to that URL.
400 when the org is already on a paid plan. The Stripe session has metadata.mnueron_org_id stamped on it so the webhook can attribute the eventual subscription back to your org.
POST /api/billing/portal
Opens the Stripe Customer Portal for an existing customer (change card, view invoices, cancel).
curl -X POST https://www.mnueron.com/api/billing/portal \
-H "Authorization: Bearer $MNUERON_API_TOKEN"
Returns { url }. 404 when the org has no Stripe customer attached.
POST /api/billing/webhook
Receives Stripe events. Not for general use — only Stripe calls this. Signature verification uses stripe-signature (HMAC-SHA256 over the raw body).
Handled events:
checkout.session.completed— upgrade the org's plancustomer.subscription.created/updated/deletedinvoice.payment_failedcharge.refunded
Returns { ok: true, processed | duplicate | recorded: false }. Idempotent via billing_events.stripe_event_id UNIQUE constraint — replay storms are safe.