API reference
Checkout sessions
A payment request plus the hand-back — the only part of checkout that crosses between two organisations.
A session is a payment request plus the two things a merchant flow needs and a bare link does not: where to send the payer back, and where to notify the merchant.
POST /checkout/sessions
Requires a member credential.
{
"request_reference": "7fk2m9pq3vx8",
"success_url": "https://store.example.com/thanks?order=10482",
"cancel_url": "https://store.example.com/cart",
"webhook_url": "https://store.example.com/hooks/path",
"expires_at": "2026-09-09T10:30:00Z"
}{
"id": "cs_4b81f2c7",
"status": "open",
"request_reference": "7fk2m9pq3vx8",
"success_url": "https://store.example.com/thanks?order=10482",
"cancel_url": "https://store.example.com/cart",
"expires_at": "2026-09-09T10:30:00Z"
}Only the issuer of the request may open a session on it, and only while the request is created.
GET /checkout/sessions/{id}
Public.
{
"id": "cs_4b81f2c7",
"status": "open",
"success_url": "https://store.example.com/thanks?order=10482",
"cancel_url": "https://store.example.com/cart",
"payer_member": null,
"attempts": 0,
"expires_at": "2026-09-09T10:30:00Z",
"completed_at": null
}payer_member
The wallet completing the session — and where this stops being theoretical.
Today a checkout completes only inside the wallet its provider chose. Under PATH it may be a wallet at another member entirely, and the merchant integrates nothing extra. That field being populated with a name the merchant has never heard of is the protocol working.
POST /checkout/sessions/{id}/attempt
Called by the payer's wallet when it starts.
{ "payer_member": "member-b" }{ "id": "cs_4b81f2c7", "attempts": 1 }Attempts are counted, never overwritten. A payer who tries three wallets before one works is a normal story, and a merchant investigating a complaint needs all three.
Lifecycle
What is not here, and why
Partial payments, several concurrent attempts against one session, and refunds tied to an order are RESERVED for a later version.
The line that keeps this pillar small: PATH specifies what crosses between the merchant's provider and the payer's wallet. The basket, tax, shipping, inventory, promotion codes and the payment page belong to whoever built the store — which is where products should differ.
If the session later acquires a lifecycle of its own — partial settlement, dispute tied to delivery — that is the signal to reconsider whether the demand deserves richer treatment. It is a decision to take with evidence, not in advance.
Webhooks
DRAFT| Event | When |
|---|---|
checkout.session.completed | The session completed |
checkout.session.expired | It expired unpaid |
request.paid | The underlying request was marked paid |
receipt.issued | A settlement receipt was issued |
Deliveries are signed with the operator's key, same envelope as everything else, so a receiver verifies them the way it verifies anything.
Treat delivery as at-least-once. Duplicates happen; make handlers idempotent on the event id. Re-marking a paid request as paid is deliberately not an error, for exactly this reason.