Skip to main content
POST
Error

Authorizations

Authorization
string
header
required

A staff session token, uk_st_…. Minted by sign-up, sign-in or the two-factor exchange.

Headers

X-Organization-Id
string

The organization the caller is acting on — the org_… code that appears in the panel URL. It identifies; the membership JOIN is what authorizes, so a forged code reads nothing. Absent, the session's default organization answers.

Idempotency-Key
string

A key you choose that makes starting a checkout safe to retry, end to end.

A repeat under the same key does not start a second checkout: it answers the same subscription and the same gateway session as the first attempt, with Idempotent-Replay: true. That is what a lost response needs — the first attempt's session is live and payable, and the answer that went missing carries the only id tying a payment to a row.

The key names one act. Sent with a different customer, price or quantity it is refused (422, idempotency_key_reused), and once the checkout it started has been paid it is refused (409, checkout_already_completed) rather than putting a second session in front of somebody who is already subscribed. Send a fresh key per checkout you mean to start: two checkouts for one customer on one price are two real checkouts, and the key is the only thing that can say otherwise.

It is forwarded to the gateway as its idempotency key too, so the retry and the original arrive there as one request. Retry with the body unchanged — the gateway compares every parameter, including success_url and cancel_url, and answers a mismatch with a refusal of its own.

Maximum string length: 255

Query Parameters

environment
enum<string>
default:live

Which environment to act in. A view parameter, valid only on the staff surface — a machine credential never chooses its environment, it is resolved from the key.

Available options:
live,
test

Body

application/json
customer_id
string<uuid>
required

Who is being billed. Must be a customer of this environment.

price_id
string<uuid>
required

The catalogue price to sell, in this environment. Recurring, not archived, and mapped onto the gateway.

success_url
string<uri>
required

Where the payer lands after paying. Required, and it has to be an http(s) URL.

quantity
integer<int64>
default:1

Seats or units. 1 when omitted; 0 is refused, because a line for none of something is not a line.

Required range: x >= 1
cancel_url
string<uri>

Where they land if they back out. Optional — a gateway with no cancel destination returns them itself.

trial_days
integer

Free days before the first charge. Omit or 0 for none.

Required range: x >= 0
provider
enum<string>

Which gateway to charge through. Only needed when the environment has more than one connected: with one there is nothing to disambiguate, and with two picking for you would be choosing whose merchant account collects.

Available options:
stripe

Response

The subscription row and where to send the payer. expires_at is null when the gateway does not say — a made-up expiry would be a countdown to a moment nothing happens at.

subscription
object

What one of your customers is paying, mirrored from the gateway.

That word decides how to read every field below. The gateway is the source of truth about money; this is a local copy kept so an entitlement can be answered without a network call, joined to the rest of your data, and read while the gateway is unreachable. provider_synced_at is when the copy was last confirmed — null means never, which is what a checkout that was started and not completed looks like.

checkout
object