Checkout Session Token
Authenticate continuation calls to /v1/checkouts/* by echoing the session nonce as the x-checkout-session-token header.
Checkout Session Token
Every continuation call against the /v1/checkouts/* API is authenticated with the session nonce issued at session-create time. Clients send the nonce as the x-checkout-session-token request header, and the billing API matches it against checkout_session.nonce for the session id on the URL.
The session-create endpoint (POST /v1/checkouts/sessions) is the only /v1/checkouts/* route that does not require the header — it issues the nonce.
When the SDK creates the session for you (@flopay/js, @flopay/react, or @flopay/node), you do not need to manage the header by hand — it reads CheckoutSessionResponseDto.nonce from the create response and attaches it to every subsequent request automatically.
When you instead hand the SDK a session your backend created — e.g. the sessionId prop on FloPayAutomaticPaymentButton or FloPayCheckout — pass the session's nonce via the matching nonce prop. A session read does not echo the nonce back, so the SDK cannot recover it on its own; omit it and the continuation calls fail with 401.
Capture the nonce
The session-create response returns the nonce as nonce on CheckoutSessionResponseDto. Stash it alongside the session id; you'll need it on every follow-up call for the lifetime of the session.
const res = await fetch(`${billingApiUrl}/v1/checkouts/sessions`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
clientId,
currency: 'USD',
products: [{ code: 'pro_plan', totalAmount: 49.99 }],
account: { userId, email },
successUrl: '/success',
cancelUrl: '/cancel',
}),
});
const { id: sessionId, nonce } = await res.json();Echo as x-checkout-session-token
Send the nonce as the x-checkout-session-token header on every continuation call. The header value is the raw nonce string — no Bearer prefix, no encoding.
await fetch(`${billingApiUrl}/v1/checkouts/sessions/${sessionId}/process`, {
method: 'POST',
headers: {
'content-type': 'application/json',
'x-checkout-session-token': nonce,
'x-user-id': userId,
},
body: JSON.stringify({ tokenizedData, accountData }),
});A missing or mismatched header is rejected with 401 Unauthorized before any business logic runs.
Protected routes
The header is required on every /v1/checkouts/* route below. For routes that include :id, that session id must match the session that issued the nonce.
| Method | Route | Purpose |
|---|---|---|
GET | /v1/checkouts/sessions/:id | Fetch the checkout session. |
GET | /v1/checkouts/sessions/:id/products | List the products attached to the session. Replaces the removed GET /v1/checkouts/items. |
POST | /v1/checkouts/sessions/:id/process | Submit a tokenized payment. Moved from POST /v1/checkouts/sessions/process. |
POST | /v1/checkouts/sessions/:id/vault/error | Report a vault-side failure for the session. Moved from POST /v1/checkouts/sessions/vault/error. |
POST | /v1/checkouts/payments/intents | Create the PaymentIntent for the session. |
POST | /v1/checkouts/payments/setup-intents | Create the SetupIntent for the session. |
Two routes were renamed in this release. Update any client code that still posts to /v1/checkouts/sessions/process or /v1/checkouts/sessions/vault/error — both now live under /v1/checkouts/sessions/:id/.... GET /v1/checkouts/items has been removed; use GET /v1/checkouts/sessions/:id/products instead.
Lifetime
The nonce is bound to the session row and lives as long as the session does — it does not rotate per request. Persist it next to the session id wherever your client tracks checkout state (component state, sessionStorage, server-side cache) so that downstream calls can read it back.
There is no separate refresh endpoint. If you lose the nonce, the session can no longer be continued and the buyer must restart at session-create.
Errors
| Status | Meaning |
|---|---|
401 | Header missing, or the value does not match checkout_session.nonce for the session id on the URL. |
404 | The session id on the URL does not exist. |
In the SDK these surface as FloPayError with type: 'authentication_error' (401) or type: 'api_error' (404). See the Error Handling guide.