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.