Checkout Sessions
Create and manage Tokeflow checkout sessions — snapshot offers and prices, identify the customer, track buyer behavior, and hand off to a transaction for charging.
A checkout session is the server-side state of a single purchase in progress. It snapshots the offers and prices a buyer is about to pay, captures who they are, records what they do, and becomes the single source of truth for the amount and currency that will eventually be charged.
Sessions decouple building the cart from charging it. You assemble line items and identify the customer over the life of the session, then create one transaction that references the session by ID. The amount and currency are derived from the session, so the charge always matches what the buyer saw.
Because a session snapshots offer prices at creation time, later catalog edits never change the price of a checkout already in flight — the buyer pays exactly what was quoted.
Tokeflow orchestrates payments; it does not process or settle funds. A checkout session models the purchase intent and items; authorization, capture, and settlement happen on the connected payment provider once you create the transaction that charges the session.
How a session flows
The checkout session object
| Field | Type | Description |
|---|---|---|
id | string | Session identifier, prefixed cks_. |
merchant_id | string | Owning merchant, prefixed mrc_. |
offer_id | string | Primary offer that initiated the checkout, prefixed ofr_. |
customer_id | string | null | Set once the customer is identified, prefixed cust_. |
customer_email | string | null | Customer email, populated on identify. |
customer_name | string | null | Customer name, when known. |
selected_currency | string | null | ISO 4217 currency for the session. Defaults to the offer's default currency. |
status | enum | Session lifecycle state. See Statuses. |
external_session_id | string | null | Your own session or account reference. Unique per merchant when set. |
expires_at | string | null | ISO 8601 time after which the session is treated as expired. |
completed_at | string | null | Set when the session transitions to completed. |
created_at | string | ISO 8601 creation timestamp. |
updated_at | string | ISO 8601 last-update timestamp. |
items | array | Line items. Included by default on get-by-id; see Line items. |
events | array | Tracking events. Included when requested; see Events. |
Statuses
| Status | Meaning |
|---|---|
initiated | Session created; no customer identified yet. |
customer_identified | A customer has been attached to the session. |
payment_pending | A charge has been started against the session. |
completed | The session was paid; completed_at is set. |
expired | The session passed expires_at without completing. |
abandoned | The session was explicitly marked abandoned. |
Endpoints
All endpoints are under https://api.tokeflow.com/api/v1.
Checkout endpoints are merchant-scoped. With an Organization key, identify the target merchant with the merchant_id query parameter (on list/get) or body field (on create); with a Merchant key the merchant is inferred. Reads require the checkout:read scope; writes require checkout:write.
POST/api/v1/checkout-sessions
Create a checkout session.
Auth: Organization key (with merchant_id) or Merchant key.
Provide a primary offer_id. Identify the buyer with either an existing customer_id or an inline customer object (provide exactly one) — the inline customer is resolved idempotently by email, so an existing customer with the same email is reused. Omit items to let Tokeflow snapshot a single default item from offer_id, or pass an explicit items array.
| Field | Type | Required | Description |
|---|---|---|---|
offer_id | string | Yes | Primary offer that initiated the checkout. |
customer_id | string | Conditional | Existing customer id. Provide this or customer. |
customer | object | Conditional | Inline customer to create/reuse. Provide this or customer_id. |
selected_currency | string | No | ISO 4217 code. Omit to use the offer's default currency. |
external_session_id | string | No | Your session/account reference. Unique per merchant. |
expires_at | string | No | ISO 8601 timestamp; must be in the future. |
items | array | No | Line items (see below). Omit for a single default item. |
Each entry in items:
| Field | Type | Required | Description |
|---|---|---|---|
offer_id | string | Yes | Offer to include as a line item. |
quantity | integer | No | Units of this offer. Min 1, default 1. |
installments | integer | No | Installments selected by the buyer. Min 1, default 1 (single charge). |
The inline customer object accepts email, name, phone (E.164), document_type (cpf, cnpj, passport, tax_id), document_number, billing_address, and optional metadata. See Customers for the full shape.
Send an Idempotency-Key header on create so a retried request returns the original session instead of creating a duplicate. See Idempotency & rate limits.
curl -X POST https://api.tokeflow.com/api/v1/checkout-sessions \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1d2c9a-2b8e-4c3a-9f0d-7a1e2b3c4d5e" \
-d '{
"offer_id": "ofr_a1b2c3d4e5",
"customer": {
"email": "joao@example.com",
"name": "Joao da Silva",
"phone": "+5511999990000",
"document_type": "cpf",
"document_number": "123.456.789-00",
"billing_address": {
"line_1": "Av Paulista, 1000",
"line_2": "Apto 42",
"zip_code": "01310-100",
"city": "Sao Paulo",
"state": "SP",
"country": "BR"
}
},
"selected_currency": "BRL",
"external_session_id": "sess_external_42",
"expires_at": "2026-05-20T18:00:00Z",
"items": [
{ "offer_id": "ofr_a1b2c3d4e5", "quantity": 1, "installments": 1 }
]
}'Response 201 Created (a replayed idempotent request returns 200 OK):
{
"success": true,
"data": {
"id": "cks_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"offer_id": "ofr_a1b2c3d4e5",
"customer_id": "cust_a1b2c3d4e5",
"customer_email": "joao@example.com",
"customer_name": "Joao da Silva",
"selected_currency": "BRL",
"status": "customer_identified",
"external_session_id": "sess_external_42",
"expires_at": "2026-05-20T18:00:00.000Z",
"completed_at": null,
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-19T12:00:00.000Z",
"items": [
{
"id": "cki_a1b2c3d4e5",
"checkout_session_id": "cks_a1b2c3d4e5",
"offer_id": "ofr_a1b2c3d4e5",
"currency": "BRL",
"amount": 15000,
"first_charge_amount": null,
"quantity": 1,
"installments": 1,
"created_at": "2026-05-19T12:00:00.000Z"
}
]
},
"request_id": "req_8f3c2a1b",
"timestamp": "2026-05-19T12:00:00.000Z"
}GET/api/v1/checkout-sessions
List checkout sessions, newest first.
Auth: Organization key (with merchant_id) or Merchant key.
| Query param | Type | Description |
|---|---|---|
page | integer | Page number, 1-indexed. Default 1. |
limit | integer | Items per page. Default 20, max 100. |
status | enum | Filter by session status. |
offer_id | string | Sessions tied to a specific primary offer. |
customer_id | string | Sessions for a specific customer. |
customer_email | string | Sessions matching a customer email. |
external_session_id | string | Lookup by your external session reference. |
merchant_id | string | Required with an Organization key to target a merchant. |
curl -G https://api.tokeflow.com/api/v1/checkout-sessions \
-H "Authorization: Bearer sk_live_mer_…" \
--data-urlencode "status=initiated" \
--data-urlencode "offer_id=ofr_a1b2c3d4e5" \
--data-urlencode "page=1" \
--data-urlencode "limit=20"Response 200 OK:
{
"success": true,
"data": [
{
"id": "cks_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"offer_id": "ofr_a1b2c3d4e5",
"customer_id": null,
"customer_email": null,
"customer_name": null,
"selected_currency": "BRL",
"status": "initiated",
"external_session_id": "sess_external_42",
"expires_at": "2026-05-20T18:00:00.000Z",
"completed_at": null,
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-19T12:00:00.000Z"
}
],
"meta": {
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"total_pages": 1,
"has_next": false,
"has_prev": false
}
},
"request_id": "req_3a9d7c2e",
"timestamp": "2026-05-19T12:05:00.000Z"
}GET/api/v1/checkout-sessions/:id
Retrieve a single checkout session.
Auth: Organization key (with merchant_id) or Merchant key.
| Query param | Type | Description |
|---|---|---|
include_items | boolean | Include the items array. Defaults to true; pass false to omit. |
include_events | boolean | Include the events array. Defaults to false; pass true to include. |
curl -G https://api.tokeflow.com/api/v1/checkout-sessions/cks_a1b2c3d4e5 \
-H "Authorization: Bearer sk_live_mer_…" \
--data-urlencode "include_items=true" \
--data-urlencode "include_events=true"Response 200 OK:
{
"success": true,
"data": {
"id": "cks_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"offer_id": "ofr_a1b2c3d4e5",
"customer_id": "cust_a1b2c3d4e5",
"customer_email": "jane@acme.com",
"customer_name": "Jane Doe",
"selected_currency": "BRL",
"status": "customer_identified",
"external_session_id": "sess_external_42",
"expires_at": "2026-05-20T18:00:00.000Z",
"completed_at": null,
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-19T12:03:00.000Z",
"items": [
{
"id": "cki_a1b2c3d4e5",
"checkout_session_id": "cks_a1b2c3d4e5",
"offer_id": "ofr_a1b2c3d4e5",
"currency": "BRL",
"amount": 15000,
"first_charge_amount": null,
"quantity": 1,
"installments": 1,
"created_at": "2026-05-19T12:00:00.000Z"
}
],
"events": [
{
"id": "cke_a1b2c3d4e5",
"checkout_session_id": "cks_a1b2c3d4e5",
"event_type": "customer_identified",
"source_url": "https://acme.com/checkout",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "spring_sale",
"ip_address": "203.0.113.42",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15",
"metadata": null,
"created_at": "2026-05-19T12:03:00.000Z"
}
]
},
"request_id": "req_5c1e8b4f",
"timestamp": "2026-05-19T12:10:00.000Z"
}PATCH/api/v1/checkout-sessions/:id
Update mutable session fields. The primary offer_id and items are immutable here — manage line items with the item endpoints.
Auth: Organization key (with merchant_id) or Merchant key.
| Field | Type | Required | Description |
|---|---|---|---|
customer_id | string | No | Attach an existing customer. |
customer | object | No | Inline customer to create/reuse. |
selected_currency | string | No | Change the session currency (ISO 4217). |
external_session_id | string | No | Update your external reference. |
expires_at | string | No | Push out the expiry (must be in the future). |
curl -X PATCH https://api.tokeflow.com/api/v1/checkout-sessions/cks_a1b2c3d4e5 \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-d '{ "selected_currency": "USD", "expires_at": "2026-05-21T18:00:00Z" }'Response 200 OK — returns the updated session object (same shape as get-by-id).
POST/api/v1/checkout-sessions/:id/identify
Attach a customer to the session. Provide customer_id or customer_email (required when no id is given). When only an email is supplied, Tokeflow looks up or creates the matching customer for the merchant. On success the session moves to customer_identified.
Auth: Organization key (with merchant_id) or Merchant key.
| Field | Type | Required | Description |
|---|---|---|---|
customer_id | string | Conditional | Existing customer id. Provide this or customer_email. |
customer_email | string | Conditional | Customer email; resolves or creates the customer. |
customer_name | string | No | Optional display name. |
curl -X POST https://api.tokeflow.com/api/v1/checkout-sessions/cks_a1b2c3d4e5/identify \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-d '{ "customer_email": "jane@acme.com", "customer_name": "Jane Doe" }'Response 200 OK — returns the session with customer_id, customer_email, and status: customer_identified.
POST/api/v1/checkout-sessions/:id/abandon
Mark a session as abandoned, for example when the buyer leaves the page. The session moves to abandoned. Takes no body.
Auth: Organization key (with merchant_id) or Merchant key.
curl -X POST https://api.tokeflow.com/api/v1/checkout-sessions/cks_a1b2c3d4e5/abandon \
-H "Authorization: Bearer sk_live_mer_…"Response 200 OK — returns the session with status: abandoned.
Line items
Each line item snapshots an offer's price at the moment it is added, in integer minor units. Editing your catalog afterward never changes an existing session's totals.
| Field | Type | Description |
|---|---|---|
id | string | Item identifier, prefixed cki_. |
checkout_session_id | string | Parent session, prefixed cks_. |
offer_id | string | Offer this line item references. |
currency | string | ISO 4217 currency of the snapshot. |
amount | integer | Recurring/standard price snapshot, in minor units. |
first_charge_amount | integer | null | First-charge price snapshot (when the offer has a setup charge), in minor units. |
quantity | integer | Units of this offer. |
installments | integer | Installments selected by the buyer (1 = single charge). |
created_at | string | ISO 8601 creation timestamp. |
POST/api/v1/checkout-sessions/:id/items
Add a line item.
Auth: Organization key (with merchant_id) or Merchant key.
| Field | Type | Required | Description |
|---|---|---|---|
offer_id | string | Yes | Offer to add. |
quantity | integer | No | Min 1, default 1. |
installments | integer | No | Min 1, default 1. |
curl -X POST https://api.tokeflow.com/api/v1/checkout-sessions/cks_a1b2c3d4e5/items \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-d '{ "offer_id": "ofr_f6g7h8i9j0", "quantity": 2, "installments": 1 }'Response 201 Created:
{
"success": true,
"data": {
"id": "cki_f6g7h8i9j0",
"checkout_session_id": "cks_a1b2c3d4e5",
"offer_id": "ofr_f6g7h8i9j0",
"currency": "BRL",
"amount": 4990,
"first_charge_amount": null,
"quantity": 2,
"installments": 1,
"created_at": "2026-05-19T12:08:00.000Z"
},
"request_id": "req_9b2f4d6a",
"timestamp": "2026-05-19T12:08:00.000Z"
}PATCH/api/v1/checkout-sessions/:id/items/:itemId
Update a line item's quantity or installments. The offer_id is immutable; remove and re-add to swap offers.
Auth: Organization key (with merchant_id) or Merchant key.
| Field | Type | Required | Description |
|---|---|---|---|
quantity | integer | No | Min 1. |
installments | integer | No | Min 1. |
curl -X PATCH https://api.tokeflow.com/api/v1/checkout-sessions/cks_a1b2c3d4e5/items/cki_f6g7h8i9j0 \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-d '{ "quantity": 3 }'Response 200 OK — returns the updated item object.
DELETE/api/v1/checkout-sessions/:id/items/:itemId
Remove a line item.
Auth: Organization key (with merchant_id) or Merchant key.
curl -X DELETE https://api.tokeflow.com/api/v1/checkout-sessions/cks_a1b2c3d4e5/items/cki_f6g7h8i9j0 \
-H "Authorization: Bearer sk_live_mer_…"Response 204 No Content — empty body.
Events
Events are an append-only behavioral log for a session — useful for conversion analytics, funnel tracking, and debugging drop-off. Recording an event never changes the session status by itself; status transitions are driven by the lifecycle endpoints and by charging.
| Field | Type | Description |
|---|---|---|
id | string | Event identifier, prefixed cke_. |
checkout_session_id | string | Parent session, prefixed cks_. |
event_type | enum | Type of event (see below). |
source_url | string | null | URL the buyer was on when the event fired. |
utm_source | string | null | Attribution source. |
utm_medium | string | null | Attribution medium. |
utm_campaign | string | null | Attribution campaign. |
ip_address | string | null | Buyer IP at event time. |
user_agent | string | null | Buyer user agent at event time. |
metadata | object | null | Free-form payload for event-specific context. |
created_at | string | ISO 8601 creation timestamp. |
Event types
event_type | When to record it |
|---|---|
initiated | Checkout page first loaded. |
customer_identified | Buyer provided identifying details. |
currency_changed | Buyer switched the display/charge currency. |
payment_started | Buyer submitted payment details. |
payment_failed | A charge attempt was declined or errored. |
payment_succeeded | A charge attempt succeeded. |
completed | The checkout finished successfully. |
expired | The session lapsed past its expiry. |
abandoned | The buyer left without completing. |
POST/api/v1/checkout-sessions/:id/events
Record an event.
Auth: Organization key (with merchant_id) or Merchant key.
| Field | Type | Required | Description |
|---|---|---|---|
event_type | enum | Yes | One of the event types above. |
source_url | string | No | Page URL when the event fired. |
utm_source | string | No | Attribution source. |
utm_medium | string | No | Attribution medium. |
utm_campaign | string | No | Attribution campaign. |
ip_address | string | No | Valid IP address. |
user_agent | string | No | Buyer user agent. |
metadata | object | No | Free-form context (for example a decline reason). |
curl -X POST https://api.tokeflow.com/api/v1/checkout-sessions/cks_a1b2c3d4e5/events \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-d '{
"event_type": "payment_failed",
"source_url": "https://acme.com/checkout",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "spring_sale",
"ip_address": "203.0.113.42",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15",
"metadata": { "decline_code": "insufficient_funds" }
}'Response 201 Created:
{
"success": true,
"data": {
"id": "cke_a1b2c3d4e5",
"checkout_session_id": "cks_a1b2c3d4e5",
"event_type": "payment_failed",
"source_url": "https://acme.com/checkout",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "spring_sale",
"ip_address": "203.0.113.42",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15",
"metadata": { "decline_code": "insufficient_funds" },
"created_at": "2026-05-19T12:12:00.000Z"
},
"request_id": "req_2e7a9c5d",
"timestamp": "2026-05-19T12:12:00.000Z"
}Charging a checkout session
A checkout session never charges itself. When the buyer pays, create a transaction that references the session by its checkout_session_id. Tokeflow derives the amount and currency from the session, and builds the order from the session's line items — so the charge always matches the snapshot the buyer saw.
When checkout_session_id is provided, any amount and currency sent on the transaction request are ignored.
curl -X POST https://api.tokeflow.com/api/v1/transactions \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0a9b8c7d-6e5f-4a3b-2c1d-0e9f8a7b6c5d" \
-d '{
"checkout_session_id": "cks_a1b2c3d4e5",
"payment_method": "credit_card",
"charge_type": "payment",
"country": "BR"
}'On success, the session transitions to completed and completed_at is set. Collect card details safely on the client first: Tokeflow's secure fields run inside isolated, cross-origin iframes; card data is encrypted in the browser and never touches your servers. See Transactions for the full charge flow.
Send an Idempotency-Key on the charge so a retried request returns the original transaction instead of double-charging.
Errors
Checkout endpoints use the standard error envelope. Common cases:
| HTTP | type | When |
|---|---|---|
400 | validation_error | Missing/invalid fields, or neither customer_id nor customer/customer_email provided. |
401 | authentication_error | Missing or invalid API key. |
403 | authorization_error | Key lacks checkout:read / checkout:write. |
404 | not_found_error | Session, item, offer, or customer not found for this merchant. |
409 | conflict_error | Duplicate external_session_id for the merchant. |
Related
- Transactions — charge a session and run the payment.
- Customers — the customer records sessions attach to.
- Offers — the priced offers that line items snapshot.
- Idempotency & rate limits — safe retries on create and charge.
- API reference overview — envelopes, IDs, money, and pagination.