Checkout Sessions API
Create checkout sessions from your backend.
Create a checkout session from your backend when your customer is ready to pay. The response contains a hosted checkout URL that you can redirect to, open in a new tab, or pass to the Stafiel widget.
Endpoint
POST /api/v1/checkout/sessions
Request Fields
| Field | Required | Default | Description |
|---|---|---|---|
merchantId |
Yes | None | Must match the merchant bound to the API key. |
chainName |
Yes | None | Mainnet chain label. See Chain Labels. |
tokenSymbol |
Yes | None | Use USDC or USDT, subject to the selected chain and merchant configuration. |
amountUsd |
Yes | None | Dollar-denominated checkout amount as a string. Use at most 2 decimal places, such as 49, 49.9, or 49.90; extra decimal places are rejected. |
expiresIn |
No | Merchant default | Payment window in seconds. The value must be inside the merchant's configured allowed range. |
idempotencyKey |
No | None | Recommended. Use your internal order ID so retries do not create duplicate checkout sessions. |
metadata |
No | None | Your own order reference, customer reference, return URL, or other non-sensitive metadata. See Metadata Reserved Fields and Rules. |
Chain Labels
Use these mainnet chainName values when creating live checkout sessions:
| chainName | Chain ID | Description |
|---|---|---|
eth |
1 |
Ethereum mainnet for USDT and USDC payments. |
base |
8453 |
Base mainnet for lower-cost EVM payments. |
bsc |
56 |
BNB Smart Chain mainnet for EVM payments. |
polygon |
137 |
Polygon mainnet for EVM payments. |
solana |
101 |
Solana mainnet for SPL stablecoin payments. |
tron |
728126428 |
Tron mainnet for TRC20 stablecoin payments. |
Available chains and tokens depend on merchant configuration.
Request Example
The example includes the currently supported reserved metadata fields.
curl -X POST https://api.stafiel.com/api/v1/checkout/sessions \
-H "X-API-Key: mk_live_your_api_key" \
-H "X-App-Client: merchant-client" \
-H "Content-Type: application/json" \
-d '{
"merchantId": "mch_your_merchant_id",
"chainName": "base",
"tokenSymbol": "USDC",
"amountUsd": "49.00",
"expiresIn": 1800,
"idempotencyKey": "order_10001",
"metadata": {
"returnToUrl": "https://merchant.example.com/orders/10001",
"productName": "Annual Pro Plan",
"productDescription": "One-year subscription for the merchant workspace.",
"quantity": "1",
"unitLabel": "year",
"customerReference": "CUS-8842"
}
}'
Success Response
{
"success": true,
"data": {
"orderId": "ord_your_order_id",
"status": "awaiting_payment",
"checkoutSessionUrl": "https://pay.stafiel.com/pay/ps_live_example",
"expiresAt": "2026-05-19T12:00:00.000Z",
"amountUsd": "49.00",
"chainName": "base",
"tokenSymbol": "USDC",
"tokenAddress": "0x..."
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
orderId |
string | Stafiel order ID for later order, payment, refund, settlement, and document lookups. |
status |
string | Initial order status. New checkout sessions return awaiting_payment. |
checkoutSessionUrl |
string | Hosted checkout URL. Treat it as opaque and use it exactly as returned. |
expiresAt |
string | ISO 8601 timestamp when the checkout session expires. |
amountUsd |
string | Accepted checkout amount, stored with up to 2 decimal places. |
chainName |
string | Canonical public chain label used for the checkout session. |
tokenSymbol |
string | Token symbol selected for the checkout session. |
tokenAddress |
string | Token contract or mint address used for the selected chain. |
Treat checkoutSessionUrl as opaque. Do not build payment URLs yourself.
Idempotency Key
idempotencyKey provides short-window duplicate protection for checkout session
creation retries. A stable internal order ID is a good key because it maps one
merchant-side order attempt to one checkout creation attempt.
Rules:
- Use 1-128 visible ASCII characters.
- Reuse the same key when retrying the same request.
- Do not reuse the same key for a different checkout payload.
- If the same key is already being processed, or if the key is reused with a
conflicting payload, the API returns
409 CHECKOUT_SESSION_CREATE_FAILED. - Do not use idempotency keys as a permanent order lookup mechanism.
Metadata Reserved Fields and Rules
metadata is an optional JSON object for merchant business context, such as
your internal order ID or customer reference. Do not put secrets, private keys,
access tokens, full payment credentials, or unnecessary sensitive personal data
in metadata.
Stafiel currently interprets these reserved metadata fields for checkout return behavior, hosted checkout display, and generated documents:
| Field | Required | Default | Description |
|---|---|---|---|
metadata.returnToUrl |
No | None | Checkout return URL, used only when allowed by the merchant return URL policy. |
metadata.productName |
No | None | Product or service name for hosted checkout and documents. |
metadata.productDescription |
No | None | Short product or order description for hosted checkout and documents. |
metadata.quantity |
No | None | Product quantity for hosted checkout and documents. |
metadata.unitLabel |
No | None | Unit label after quantity, such as seat, month, or year. |
General metadata rules:
- Use a flat object. Nested objects and arrays are ignored.
- Stafiel stores up to 20 accepted top-level fields, processed in request object order. Invalid fields are ignored and do not count toward the limit.
- Keys must be 1-100 characters and may use ASCII letters, numbers, dots, underscores, and hyphens.
- Values may be strings, finite numbers, booleans, or
null. Objects, arrays, invalid values, and unsupported value types are ignored. - String values may be up to 1,000 characters and may contain letters, numbers, punctuation, spaces, and line breaks.
metadata.returnToUrl rules:
- The value must be an absolute
https://URL. - Unsafe or blocklisted URLs are rejected.
- If the URL is not allowed by merchant return URL policy, it will not be used.
Error Responses
Error responses use this shape:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request"
}
}
| HTTP Status | Code | Meaning |
|---|---|---|
400 |
CHECKOUT_SESSION_CREATE_FAILED / ORDER_EXPIRES_IN_OUT_OF_RANGE |
Request is invalid, cannot create a session, or expiresIn is outside the allowed range. |
401 |
AUTH_FAILED |
API key is missing, invalid, or in the wrong mode. |
403 |
NO_MERCHANT_ACCOUNT |
Merchant account is required. |
409 |
CHAIN_NOT_AVAILABLE / TOKEN_NOT_AVAILABLE / CHECKOUT_SESSION_CREATE_FAILED |
Chain or token is unavailable, or the idempotency key is in progress or conflicting. |
429 |
RATE_LIMIT_EXCEEDED |
Too many requests. Retry after the indicated time. |