Skip to main content
POST
Create a checkout

Authorizations

Authorization
string
header
required

Authorization: Bearer ck_test_… or ck_live_…. There is no other auth scheme — no query-string keys, no request signing, no OAuth.

Headers

Idempotency-Key
string

Makes a create safe to retry. A second request with the same key returns the original checkout with 200 instead of starting a second run; the same key with a different body is a 409.

Strongly recommended on every create. A POST that times out after the server accepted it is indistinguishable, from the caller's side, from one that never landed, and every autonomous caller retries a timeout by default — so without this header the worst failure mode of the product is reachable by an ordinary network blip.

The request body is hashed with its object keys sorted and its defaults applied, so key order does not matter and "constraints": {} matches an omitted constraints. Keys are namespaced per (tenant, subject) and live 24 hours, measured from the creation of the checkout that claimed one. Inside the window a retry replays; outside it the key is released and the same string starts a new purchase. Release is an hourly background sweep, so the boundary is approximate to within an hour, and it clears the key off the checkout without otherwise touching the row. An empty or whitespace-only value is treated as absent.

Read by POST /v1/checkouts only; every other endpoint ignores it.

Body

application/json

The top level is strict: an unrecognised field is a 400 with an unrecognized_keys issue, not a field the server drops for you. The field most worth misspelling here is subject, and a 201 carrying an untagged row is an isolation control that failed open on a typo.

target, constraints and metadata stay permissive inside — they are extension points, and unknown keys within them are ignored.

target
CheckoutTarget · object
required
buyerProfileId
string<uuid>

Must belong to your tenant, or the request is a 400. Without one the agent has no address, and on most merchants that is where the run stops — or it raises a shipping action.

Checked against this checkout's subject, not the authenticating key's. A subject-bound key naming another end user's profile gets the same 400 buyerProfileId not found — from where it stands the profile does not exist. A tenant-wide key naming one end user's profile alongside another's subject gets a 403 naming both. An untagged profile on a tagged checkout is allowed, and so is the reverse, so subjects can be adopted incrementally.

subject
string

Your own opaque id for one of your end users. 1 to 200 characters after trimming; never parsed, never validated against anything, and never sent to a merchant. An empty or whitespace-only value is a 400 — a subject that means nothing reads as isolation you do not have.

On a key bound to a subject this is filled in for you: omit it and the row is stamped with the key's subject, name a different one and the request is a 403. On a tenant-wide key it is how a row gets tagged in the first place.

It also namespaces the Idempotency-Key: two end users may pick the same key string without colliding. GET /v1/checkouts?subject= filters the list by it, and checkout.status_changed deliveries carry it.

Required string length: 1 - 200
Example:

"user_a91f"

constraints
CheckoutConstraints · object
metadata
object

Anything you want echoed back on every poll.

Response

An Idempotency-Key replay: this key has already been used with this body. The original checkout, as it is now — not a recording of the original 201, so the status may have moved on and a pendingUserAction may already be waiting. Nothing was created, no quota was consumed, and no second browser was launched.

The whole state of one run. This is what you poll.

id
string<uuid>
required
status
enum<string>
required

succeeded, failed and cancelled are terminal; nothing leaves them.

Available options:
queued,
running,
awaiting_user_action,
succeeded,
failed,
cancelled
target
CheckoutTarget · object
required
constraints
CheckoutConstraints · object
required
metadata
object
required

Yours. Stored and echoed back untouched; never sent to a merchant, and not searchable.

progressItems
ProgressItem · object[]
required

Append-only, ordered by sequence. Build your UI around this rather than a spinner.

createdAt
string<date-time>
required
updatedAt
string<date-time>
required
subject
string

Your own id for the end user this purchase is for. Absent when the checkout is not tagged to one. Set explicitly at creation, or stamped from the authenticating key's binding.

Example:

"user_a91f"

buyerProfileId
string<uuid>

Absent when no profile was attached, and absent after the referenced profile was deleted.

browser
object

Present once a browser session exists. Not a URL you can watch at — a pointer to the endpoint that mints one.

pendingUserAction
PendingUserAction · object

Present only while the run is blocked. At most one per checkout at a time.

failure
object
receipt
Receipt · object

Present only on a succeeded checkout.