API · 2.0.0

Billing

Plan, credits, top-ups, Stripe checkout.

4 operations. All requests need Authorization: Bearer sk_.... Responses use the standard envelope; see overview for shapes and error codes.

post/billing/checkout

Start a Stripe checkout

Returns a Stripe checkout URL the caller redirects to. Owner-only.

Request body

FieldTypeRequiredDescription
plan"pro" | "team" | "enterprise"yes
interval"monthly" | "annual"no
successUrlstring (uri)no
cancelUrlstring (uri)no

Responses

  • 200Checkout URL.
  • 400Validation failed. `error.code = VALIDATION_ERROR`. `error.details.errors` lists per-field issues from zod.
  • 401Missing or invalid auth. `error.code = AUTH_ERROR`.
  • 403Authenticated but not allowed (wrong role, not a member, or org scope mismatch). `error.code = FORBIDDEN`.
  • 404Resource does not exist or is invisible to the caller. `error.code = NOT_FOUND`.
  • 409Conflict — duplicate slug, race condition, or invalid state transition. `error.code = CONFLICT`.
  • 429Rate limit exceeded. `error.code = RATE_LIMIT`. Retry after the window listed in `Retry-After`.
  • 500Unexpected server error. `error.code = INTERNAL_ERROR`. Logged with the `requestId` echoed in metadata.
cURL example
curl -X POST https://switchy.build/api/billing/checkout \
  -H 'Authorization: Bearer sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{ ... }'
get/billing/credits

Get the active org's credit balance

Responses

  • 200Credit balance.
  • 400Validation failed. `error.code = VALIDATION_ERROR`. `error.details.errors` lists per-field issues from zod.
  • 401Missing or invalid auth. `error.code = AUTH_ERROR`.
  • 403Authenticated but not allowed (wrong role, not a member, or org scope mismatch). `error.code = FORBIDDEN`.
  • 404Resource does not exist or is invisible to the caller. `error.code = NOT_FOUND`.
  • 409Conflict — duplicate slug, race condition, or invalid state transition. `error.code = CONFLICT`.
  • 429Rate limit exceeded. `error.code = RATE_LIMIT`. Retry after the window listed in `Retry-After`.
  • 500Unexpected server error. `error.code = INTERNAL_ERROR`. Logged with the `requestId` echoed in metadata.
cURL example
curl -X GET https://switchy.build/api/billing/credits \
  -H 'Authorization: Bearer sk_live_...' \
post/billing/portal

Open the Stripe customer portal

Request body

FieldTypeRequiredDescription
returnUrlstring (uri)no

Responses

  • 200Portal URL.
  • 400Validation failed. `error.code = VALIDATION_ERROR`. `error.details.errors` lists per-field issues from zod.
  • 401Missing or invalid auth. `error.code = AUTH_ERROR`.
  • 403Authenticated but not allowed (wrong role, not a member, or org scope mismatch). `error.code = FORBIDDEN`.
  • 404Resource does not exist or is invisible to the caller. `error.code = NOT_FOUND`.
  • 409Conflict — duplicate slug, race condition, or invalid state transition. `error.code = CONFLICT`.
  • 429Rate limit exceeded. `error.code = RATE_LIMIT`. Retry after the window listed in `Retry-After`.
  • 500Unexpected server error. `error.code = INTERNAL_ERROR`. Logged with the `requestId` echoed in metadata.
cURL example
curl -X POST https://switchy.build/api/billing/portal \
  -H 'Authorization: Bearer sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{ ... }'
post/billing/topup

Buy a credit top-up

Either pick a fixed `pack` (small/medium/large) or pass a custom credit amount. Top-up credits never expire.

Request body

one of:
  • FieldTypeRequiredDescription
    pack"small" | "medium" | "large"yes
  • FieldTypeRequiredDescription
    creditsintegeryes

Responses

  • 200Stripe checkout URL.
  • 400Validation failed. `error.code = VALIDATION_ERROR`. `error.details.errors` lists per-field issues from zod.
  • 401Missing or invalid auth. `error.code = AUTH_ERROR`.
  • 403Authenticated but not allowed (wrong role, not a member, or org scope mismatch). `error.code = FORBIDDEN`.
  • 404Resource does not exist or is invisible to the caller. `error.code = NOT_FOUND`.
  • 409Conflict — duplicate slug, race condition, or invalid state transition. `error.code = CONFLICT`.
  • 429Rate limit exceeded. `error.code = RATE_LIMIT`. Retry after the window listed in `Retry-After`.
  • 500Unexpected server error. `error.code = INTERNAL_ERROR`. Logged with the `requestId` echoed in metadata.
cURL example
curl -X POST https://switchy.build/api/billing/topup \
  -H 'Authorization: Bearer sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{ ... }'