Billing

Start a self-serve Community -> Cloud upgrade

Changed on

Owner-only (bunkai_is_workspace_owner) — an admin/member/viewer is rejected before any Stripe call. Idempotency-Key is REQUIRED (ADR-0002). Plan activation happens asynchronously via the Stripe webhook once payment is confirmed — this endpoint never writes workspaces.plan itself. At most one open Checkout Session may exist per workspace at a time (a partial unique index backs this); a second concurrent request either reuses the existing session's URL or answers 409.

post/api/v1/workspaces/{id}/billing/checkout

Request

  • Base URL: http://localhost:3000
  • URL: http://localhost:3000/api/v1/workspaces/{id}/billing/checkout
  • Auth: one of:
    • API key in cookie sb-fmbpikzpkafptqximhxn-auth-token
    • HTTP bearer

Path parameters

idstring uuid required

Headers

Idempotency-Keystring required

Required. 8–128 chars, [a-zA-Z0-9_-]. A replay with the same key and payload returns the stored response; the same key with a different payload returns 409 conflict. This is the HTTP-level replay guard — distinct from the DB-level one-open-session-per-workspace guard that covers two different tabs/keys racing for the same workspace.

Request body

seat_quantityinteger required

Minimum is the workspace's current active_seats count (no seat-reduction path exists in this Story); maximum is the Cloud tier's seatLimit (25, see lib/billing/plan-tiers.ts).

Response

Checkout Session URL (freshly created, or replayed/reused).

urlstring uri required

The Stripe-hosted Checkout URL to redirect the browser to. No card data ever reaches this app (Stripe Checkout, hosted — zero PCI scope).

Changes