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 returns a checkoutSessionUrl for hosted checkout, the Stafiel widget, or a merchant-rendered payment page.

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 Chain label used for the checkout session. 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 decimal string. The value may use up to 2 decimal places, and responses do not guarantee trailing zeroes.
expiresIn No Merchant default Payment window in seconds. The value must be inside the effective merchant or plan policy range. If it is outside the range, the error response may include error.expiresInAllowRange.
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.

Use these testnet chainName values when creating testnet checkout sessions:

chainName Chain ID Description
eth-sepolia 11155111 Ethereum Sepolia for testnet payments.
base-sepolia 84532 Base Sepolia for testnet payments.
bsc-testnet 97 BNB Smart Chain Testnet for testnet payments.
polygon-amoy 80002 Polygon Amoy for testnet payments.
solana-devnet 103 Solana Devnet for testnet payments.
tron-nile 3448148188 Tron Nile for testnet 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"
    }
  }'

This example returns directly to a merchant order page. You may instead send the customer through your own return handler before showing the final order page.

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 returned for the session.
expiresAt string ISO 8601 timestamp when the checkout session expires.
amountUsd string Accepted checkout amount as a decimal string. Trailing zeroes are not guaranteed.
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.

For hosted checkout or Widget integrations, pass the complete checkoutSessionUrl exactly as returned. Treat the URL and its payment token as opaque values. Do not alter, rebuild, truncate, length-limit, decode, or log the complete URL.

For a merchant-rendered payment page, your backend may extract the payment token from the final path segment. For example, https://pay.stafiel.com/pay/ps_live_example contains the payment token ps_live_example.

For the server-side payment data request and response fields, see Custom Payment Page.

Idempotency Key

idempotencyKey provides 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.
  • Use the same idempotencyKey when retrying an identical creation request.
  • After creation succeeds, an identical retry with that key returns the original checkout session response with HTTP 201.
  • Reusing the key with a different request payload is rejected.

Note: A replay returns the original creation response. For the order's current status, use the Orders API.

Note: If the creation response is lost or the result is unclear, check the request using the same merchantId and idempotencyKey. See Checkout Recovery.

Note: Replaying a checkout session response does not extend the payment window. Use the order's current expiresAt value when determining whether payment is still available.

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 Complete HTTPS URL used by the hosted checkout Back button, subject to 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:

  • Send the complete URL, including the https:// scheme and hostname. Relative paths such as /orders/10001 are not accepted.
  • The submitted URL must be 512 characters or fewer.
  • Unsafe or blocklisted URLs are rejected.
  • If the URL is safe but does not pass the merchant return URL policy, the checkout session can still be created, but the URL is not used.

Note: metadata.returnToUrl controls only the Hosted Checkout Back button. It is not a payment-success callback and is not triggered automatically by payment status changes. Use signed webhooks or authenticated API reads to determine the order outcome.

For policy configuration, see Return URL Settings.

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.
429 CHECKOUT_SESSION_CREATE_FAILED Checkout creation failed. Common causes include reaching an order creation quota or live-order limit.

For 429 CHECKOUT_SESSION_CREATE_FAILED, check the merchant's quotas and limits in the Merchant Dashboard before retrying. Backoff alone does not resolve an exhausted quota or live-order limit.

For ORDER_EXPIRES_IN_OUT_OF_RANGE, error.expiresInAllowRange contains the inclusive minimum and maximum payment window in seconds:

  • min: Minimum accepted expiresIn.
  • max: Maximum accepted expiresIn.

The values depend on the effective policy for the merchant.

{
  "success": false,
  "error": {
    "code": "ORDER_EXPIRES_IN_OUT_OF_RANGE",
    "message": "Payment window is out of allowed range",
    "expiresInAllowRange": {
      "min": 300,
      "max": 86400
    }
  }
}

The range above is an example. Use the values returned for the request.