A valid request URL is required to generate request examples{
"subscription": {},
"checkout": {
"url": "<string>",
"session_ref": "<string>",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Buy from the pricing page
The self-serve purchase: puts one of the tenant’s live prices in front of this team’s owner and answers with somewhere to send the browser. Owner-only.
The price must be one GET /v1/pricing/{publishable_key} would show — live, on a live plan. The checkout refuses anything that read would not show, because this caller was shown the offer there: an archived price answers price_archived, whatever a stale page still renders.
A recurring price starts a subscription. The trial is the price’s own — there is no override field down here; granting a longer trial is a staff act — and on a per_seat price the quantity is the team’s member count, derived, never chosen. Retrying with an Idempotency-Key answers the same subscription and the same URL instead of starting a second checkout, exactly as the staff surface promises.
A one_time price is a payment, not a subscription — the credit pack, the lifetime deal. Nothing exists here until the money lands: the gateway session carries the tie, the paid invoice is mirrored with the price on its invoice.paid fact, and a pack’s credits are granted from that fact, once per payment however often it is retold. For this half the Idempotency-Key is forwarded to the gateway, whose replay answers a retry with the same session.
A valid request URL is required to generate request examples{
"subscription": {},
"checkout": {
"url": "<string>",
"session_ref": "<string>",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Authorizations
A contact session token, uk_ct_…. Belongs to one of the developer's own users, and reads only that user's data.
Headers
The customer this call is acting inside — the same arrangement as X-Organization-Id, one plane down. Switching customers is navigation, not a mutation: nothing is stored, you send a different header, and the membership JOIN behind it decides what you may do there. An id you are not a member of matches no row and answers 404. Absent, the contact's oldest membership answers.
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.
255Body
A price from the public pricing read.
Where the payer lands after paying. Required, http(s) only.
Where they land if they back out. Optional.
Which gateway, only when the environment has more than one connected.
stripe