Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.caibo.digital/llms.txt

Use this file to discover all available pages before exploring further.

Overview

A checkout session token is a short-lived secret that lets the embedded checkout iframe authenticate against the Caibo payment API without ever seeing your merchant apiKey. Your backend mints the token using your apiKey, hands it to the browser, and the SDK passes it to the checkout page in the paymentUrl.
Never embed your merchant apiKey in the iframe URL, in client-side code, in browser history, or in any URL that leaves your server. The apiKey is a long-lived bearer secret with full merchant access. Always exchange it for a checkout session token on the server.

Security model

PropertyMerchant apiKeyCheckout session token
LifetimeLong-lived (until rotated)15 minutes from issuance
ScopeFull merchant API accessRead one payment request + submit its payment
Bound toThe merchantA single paymentRequestId
Where it livesMerchant backend onlyBrowser session (sessionStorage) and a single URL/header
Where to transmit itX-API-Key header — server-to-serverX-Checkout-Token header, or ?token= in the iframe src URL
Mintable from a token?n/aNo — tokens cannot mint more tokens
A leaked checkout token can only act on the bound payment request, and only for the next 15 minutes. A leaked apiKey can drain the account.

Endpoint

POST {api_base}/payment-requests/{paymentRequestId}/checkout-session
Header: X-API-Key: <your-merchant-api-key>
Content-Type: application/json
ParameterInTypeDescription
paymentRequestIdpathnumberThe id returned by Create a Payment Request.
The request body is empty ({}). The token derives its scope entirely from the path id and the authenticated merchant.
This call MUST originate from your backend. The browser must never see your apiKey. The whole point of this endpoint is to keep the long-lived secret on the server.

Response

{
  "token": "bhMlOWTW16rHxnmOugI9Uu1qNJk4IzD0-EZfGsRLJDU",
  "paymentRequestId": 17784899067150744,
  "expiresAt": "2026-05-11T13:25:33Z",
  "ttlSeconds": 900
}
FieldTypeDescription
tokenstringURL-safe base64 secret. 32 random bytes ≈ 43 characters.
paymentRequestIdnumberThe payment request the token is bound to.
expiresAtstringISO-8601 UTC timestamp when the token stops being accepted.
ttlSecondsnumberTotal lifetime of the token in seconds (currently 900 = 15 minutes).

Using the token

As a URL parameter (iframe src)

The iframe must boot from a URL — it cannot set a custom header on its initial document load — so the SDK accepts the token as a ?token= query parameter. The Caibo checkout page consumes the value on bootstrap, stores it in sessionStorage, then sends it on every subsequent request as X-Checkout-Token.
https://pay.caibo.digital/main?requestId=REQUEST_ID&token=TOKEN
Notice there is no apiKey and no merchantId in the URL. The token already binds the merchant and the request server-side.

As a header (server-to-server calls from a non-browser client)

If your integration calls a permitted endpoint outside the iframe SDK, send the token as a header instead:
X-Checkout-Token: bhMlOWTW16rHxnmOugI9Uu1qNJk4IzD0-EZfGsRLJDU

What a token is allowed to do

A request bearing a checkout session token is authorised for a small, fixed allow-list of endpoints, and every endpoint that carries a paymentRequestId (in the path or query string) must match the bound id exactly. Anything else returns 403 Forbidden.
MethodPathNotes
GET/payment-requests/{id}Must equal the bound id.
GET/users/settings/{merchantId}Branding / theme.
GET/users/payment-methods/{merchantId}?requestId={id}requestId must equal the bound id.
GET/users/logos/{merchantId}Merchant logo.
GET/users/addresses/{merchantId}Merchant address (used by Apple Pay domain check).
GET/payments/wallet-configApple / Google Pay configuration.
POST/payments/creditCard/{id}Must equal the bound id. Same for creditCardToken, googlePay, applePay.
GET/payments/creditCard/status/{transactionId}Polling.
GET/payments/threeds/status/{transactionId}3DS polling.
GET/payments/threeds/redirect/{transactionId}3DS redirect.
POST/payments/threeds/ddc/{transactionId}3DS device data collection.
A checkout token explicitly cannot call POST /payment-requests/{id}/checkout-session — tokens cannot mint additional tokens. Use your apiKey to re-mint when one expires.

Lifecycle

1

Create the payment request (server, apiKey)

POST /payment-requests with X-API-Key. Save the returned id.
2

Mint the token (server, apiKey)

POST /payment-requests/{id}/checkout-session with X-API-Key. Save token and expiresAt.
3

Deliver the token to the browser

Return the token (and requestId) to your frontend via your own authenticated endpoint. The browser must not see the apiKey.
4

Open the iframe (browser, token)

Construct paymentUrl = .../main?requestId=…&token=… and call CaiboCheckout.init({ paymentUrl, ... }).
5

Token expires after 15 minutes

If the customer is still on the page when the token expires, mint a fresh one server-side and re-open the iframe. The token is not auto-refreshed.

Error responses

StatusCause
401apiKey missing or invalid on the mint call.
403Caller authenticated with a checkout token (cannot mint another token).
404No payment request with the given paymentRequestId.
Once issued, errors when using a token surface as:
StatusCause
401Token unknown, expired, revoked, or exhausted.
403Endpoint is not on the token’s allow-list, or the path/query paymentRequestId mismatches.

Backward compatibility

Legacy integrations that still pass ?apiKey= in the paymentUrl continue to work, but the checkout page emits a console.warn deprecation notice on every load. Plan a migration to the token flow — leaking an apiKey through the browser history or Referer header is a serious incident.

Next Steps