Checkout API

Base URL: /v1/checkout
Auth:

  • POST /v1/checkout uses the business public key in the request body
  • other server-side checkout endpoints use Authorization: Bearer <secret_key>

Quote checkout amount

GET /v1/checkout/quote

Preview the fiat/crypto conversion before creating a checkout session.

Query:

  • amount required
  • amount_type optional: fiat | crypto
  • asset optional, default solana:usdc
  • public_key optional but recommended when the quote should reflect the business fee rule

Example:

GET /v1/checkout/quote?amount=10&amount_type=crypto&asset=solana:usdc&public_key=pk_live_xxxxx

Response body:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Checkout quote",
  "data": {
    "amount_type": "crypto",
    "asset": "solana:usdc",
    "fiat_amount": 14319.04,
    "base_fiat_amount": 14097.58,
    "fee_amount": 221.46,
    "customer_pays_fee": true,
    "requested_crypto_amount": 10,
    "fiat_currency": "NGN",
    "crypto_amount": 10,
    "crypto_currency": "USDC",
    "network": "solana",
    "rate": 1409.758,
    "expires_at": "2026-05-11 10:30:00",
    "refresh_after_seconds": 60,
    "quote": {
      "rate": 1409.758
    }
  }
}

Notes:

  • quote previews are short-lived
  • refresh the quote again after refresh_after_seconds or once expires_at has passed
  • pass public_key when you want the quote to reflect the business who_pays_fee preference
  • omitting public_key falls back to the base provider pricing only
  • this endpoint depends on Tsara's stablecoin quote provider and returns 503 when quote generation is temporarily unavailable

Checkout assets

GET /v1/checkout/assets

Return the supported checkout amount modes and crypto assets for the UI.

Notes:

  • this response is config-driven from Tsara's supported checkout asset configuration
  • updating the config changes both validation and the checkout/assets response
  • asset flags:
    • enabled: allowed in live checkout flows
    • test_enabled: allowed in test checkout flows
    • hold_supported: allowed when the checkout falls back to hold mode
  • asset UI metadata:
    • sort_order: controls returned display order
    • disabled_reason: optional machine-friendly reason
    • maintenance_message: optional user-facing message

Response body:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Checkout assets",
  "data": {
    "amount_types": ["fiat", "crypto"],
    "assets": [
      {
        "network_asset": "solana:usdc",
        "network": "solana",
        "asset": "usdc",
        "symbol": "USDC",
        "label": "Solana USDC",
        "sort_order": 10,
        "enabled": true,
        "test_enabled": true,
        "hold_supported": true,
        "disabled_reason": null,
        "maintenance_message": null
      },
      {
        "network_asset": "bsc:usdt",
        "network": "bsc",
        "asset": "usdt",
        "symbol": "USDT",
        "label": "BSC USDT",
        "sort_order": 50,
        "enabled": true,
        "test_enabled": true,
        "hold_supported": false,
        "disabled_reason": null,
        "maintenance_message": null
      }
    ]
  }
}

Create checkout session

POST /v1/checkout

Create a checkout transaction and return the hosted checkout URL.

Body:

{
  "public_key": "pk_live_xxxxx",
  "trx_id": "order_001",
  "email": "[email protected]",
  "name": "John Doe",
  "phone": "08000000000",
  "amount": 5000,
  "amount_type": "fiat",
  "currency": "NGN",
  "redirect_url": "https://example.com/checkout/return",
  "payment_method": "bank-transfer",
  "asset": "solana:usdc"
}

Notes:

  • amount_type is optional and defaults to fiat
  • supported values:
    • fiat: amount is treated as NGN
    • crypto: amount is treated as the requested crypto amount for the selected asset
  • asset is optional and defaults to solana:usdc
  • asset is used for crypto checkout generation, especially the non-hold crypto payment flow
  • payment_method is optional and defaults to bank-transfer
  • data.expires_at is the overall checkout session expiry
  • account.crypto.expires_at is the current crypto deposit instruction expiry
  • for amount_type=crypto, the checkout still settles internally in NGN; the crypto amount is first priced into a fiat base amount
  • when the business preference says the customer pays checkout fees, the payable fiat amount is uplifted before payment instructions are generated
  • when amount_type=crypto, account.crypto.requested_amount and account.crypto.requested_amount_type are returned
  • available_payment_methods reflects the business payment-method preference
  • default_payment_method is resolved from the business preference:
    • bank-transfer if available
    • otherwise crypto
  • provisioning behavior at create time:
    • bank-transfer only: generate fiat only
    • crypto only: generate crypto only
    • both: generate fiat only; crypto is created later when the user switches on the checkout UI
  • the same fee rule now applies consistently to quote, fiat-first checkout, and crypto-first checkout pricing
  • if the crypto payment provider is temporarily unavailable:
    • crypto-only checkout creation fails
    • dual-mode checkout creation still succeeds with fiat account details only
  • crypto_available shows whether crypto payment details were created successfully for that checkout
  • crypto_error is returned when fiat checkout was created but crypto setup failed

Test-mode note:

  • when the provided public key is a test key, the controller uses the same amount_type pricing rules

Crypto-first example:

{
  "public_key": "pk_live_xxxxx",
  "trx_id": "order_002",
  "email": "[email protected]",
  "name": "John Doe",
  "amount": 10,
  "amount_type": "crypto",
  "asset": "solana:usdc",
  "redirect_url": "https://example.com/checkout/return"
}

Response body:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Checkout Created",
  "data": {
    "id": "order_001",
    "status": "pending",
    "checkout_url": "https://checkout.tsara.ng/?trx_id=order_001",
    "expires_at": "2026-05-07 14:00:00",
    "available_payment_methods": ["bank-transfer", "crypto"],
    "default_payment_method": "bank-transfer",
    "crypto_available": true,
    "crypto_error": null,
    "account": {
      "fiat": {
        "bank_code": "090286",
        "bank_name": "Safe Haven MFB",
        "account_name": "TSARA CHECKOUT",
        "account_number": "1234567890"
      },
      "crypto": {
        "is_type": "offramp",
        "reference": "6c01338d-67e5-4d0c-a394-9d3e367f46a5",
        "publicKey": "7fYw4wLbW7F5L6LwY6u3pM7cQ2T8K1m3A9zP6n2sQ4rX",
        "address": "7fYw4wLbW7F5L6LwY6u3pM7cQ2T8K1m3A9zP6n2sQ4rX",
        "network": "solana",
        "asset": "usdc",
        "network_asset": "solana:usdc",
        "deposit_address": "7fYw4wLbW7F5L6LwY6u3pM7cQ2T8K1m3A9zP6n2sQ4rX",
        "deposit_asset": "solana:usdc",
        "fiat_amount": 14097.58,
        "fiat_currency": "NGN",
        "expires_at": "2026-05-07 13:50:00",
        "status": "AWAITING_DEPOSIT",
        "type": "OFFRAMP",
        "rate": {
          "USDC": 1409.758
        },
        "amount": 10
      }
    }
  },
  "url": "https://checkout.tsara.ng/?trx_id=order_001",
  "trx_id": "order_001",
  "available_payment_methods": ["bank-transfer", "crypto"],
  "default_payment_method": "bank-transfer",
  "crypto_available": true,
  "crypto_error": null,
  "account": {
    "fiat": {
      "bank_code": "090286",
      "bank_name": "Safe Haven MFB",
      "account_name": "TSARA CHECKOUT",
      "account_number": "1234567890"
    },
    "crypto": {
      "is_type": "offramp",
      "reference": "6c01338d-67e5-4d0c-a394-9d3e367f46a5",
      "publicKey": "7fYw4wLbW7F5L6LwY6u3pM7cQ2T8K1m3A9zP6n2sQ4rX",
      "address": "7fYw4wLbW7F5L6LwY6u3pM7cQ2T8K1m3A9zP6n2sQ4rX",
      "network": "solana",
      "asset": "usdc",
      "network_asset": "solana:usdc",
      "deposit_address": "7fYw4wLbW7F5L6LwY6u3pM7cQ2T8K1m3A9zP6n2sQ4rX",
      "deposit_asset": "solana:usdc",
      "fiat_amount": 14097.58,
      "fiat_currency": "NGN",
      "expires_at": "2026-05-07 13:50:00",
      "status": "AWAITING_DEPOSIT",
      "type": "OFFRAMP",
      "rate": {
        "USDC": 1409.758
      },
      "amount": 10
    }
  }
}

Fallback example when crypto setup fails:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Checkout Created",
  "data": {
    "id": "order_001",
    "status": "pending",
    "checkout_url": "https://checkout.tsara.ng/?trx_id=order_001",
    "expires_at": "2026-05-07 14:00:00",
    "available_payment_methods": ["bank-transfer", "crypto"],
    "default_payment_method": "bank-transfer",
    "crypto_available": false,
    "crypto_error": "Crypto payment is currently unavailable for this checkout.",
    "account": {
      "fiat": {
        "bank_code": "090286",
        "bank_name": "Safe Haven MFB",
        "account_name": "TSARA CHECKOUT",
        "account_number": "1234567890"
      }
    }
  }
}

Crypto-only example:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Checkout Created",
  "data": {
    "id": "order_001",
    "status": "pending",
    "checkout_url": "https://checkout.tsara.ng/?trx_id=order_001",
    "expires_at": "2026-05-07 14:00:00",
    "available_payment_methods": ["crypto"],
    "default_payment_method": "crypto",
    "crypto_available": true,
    "crypto_error": null,
    "account": {
      "crypto": {
        "network_asset": "solana:usdc",
        "asset": "usdc"
      }
    }
  }
}

Fetch checkout account

GET /v1/checkout/account

Return the current payment account details for a checkout transaction.

Query:

  • trx_id (required)
  • method (optional): fiat | crypto

Notes:

  • when method=crypto, only the crypto block is returned
  • when method=fiat, only the fiat block is returned
  • when method is omitted, both blocks are returned when available
  • this endpoint also returns available_payment_methods and default_payment_method so the checkout UI can recover the business payment-mode state after refresh

Example:

GET /v1/checkout/account?trx_id=order_001&method=crypto
Authorization: Bearer sk_live_xxxxx

Response body:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Account updated!",
  "data": {
    "available_payment_methods": ["bank-transfer", "crypto"],
    "default_payment_method": "bank-transfer",
    "crypto": {
      "is_type": "offramp",
      "reference": "6c01338d-67e5-4d0c-a394-9d3e367f46a5",
      "publicKey": "0xcd257a5867B42556fa14c35de714154B277f70fD",
      "address": "0xcd257a5867B42556fa14c35de714154B277f70fD",
      "deposit_address": "0xcd257a5867B42556fa14c35de714154B277f70fD",
      "deposit_asset": "solana:usdc",
      "fiat_amount": 14097.58,
      "fiat_currency": "NGN",
      "expires_at": "2026-05-07 13:50:00",
      "status": "AWAITING_DEPOSIT",
      "type": "OFFRAMP",
      "asset": "usdc",
      "network_asset": "solana:usdc",
      "network": "solana",
      "rate": {
        "USDC": 1409.758
      },
      "amount": 10
    }
  }
}

Update checkout crypto asset

POST /v1/checkout/crypto

Rebuild the crypto payment details for an existing checkout transaction using a selected network:asset.

Body:

{
  "trx_id": "order_001",
  "asset": "base:usdc"
}

Notes:

  • requires Authorization: Bearer <secret_key>
  • updates the stored account->crypto payload for the transaction
  • returns the refreshed crypto details for the checkout UI
  • also returns available_payment_methods and default_payment_method
  • hold mode currently supports solana:usdc only
  • if the existing crypto payment instruction for the requested network:asset is still valid, it is reused instead of creating a new one
  • this endpoint depends on Tsara's crypto payment provider for non-hold mode and returns 503 when crypto payment refresh is temporarily unavailable

Response body:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Crypto payment account updated!",
  "data": {
    "available_payment_methods": ["bank-transfer", "crypto"],
    "default_payment_method": "bank-transfer",
    "crypto": {
      "is_type": "offramp",
      "reference": "6c01338d-67e5-4d0c-a394-9d3e367f46a5",
      "publicKey": "0xcd257a5867B42556fa14c35de714154B277f70fD",
      "address": "0xcd257a5867B42556fa14c35de714154B277f70fD",
      "deposit_address": "0xcd257a5867B42556fa14c35de714154B277f70fD",
      "deposit_asset": "base:usdc",
      "fiat_amount": 14097.58,
      "fiat_currency": "NGN",
      "expires_at": "2026-05-07 13:50:00",
      "status": "AWAITING_DEPOSIT",
      "type": "OFFRAMP",
      "asset": "usdc",
      "network_asset": "base:usdc",
      "network": "base",
      "rate": {
        "USDC": 1409.758
      },
      "amount": 10
    }
  }
}

Checkout status

GET /v1/checkout/status

Query:

  • reference or trx_id

Notes:

  • returns available_payment_methods and default_payment_method for UI state recovery

Example:

GET /v1/checkout/status?trx_id=order_001
Authorization: Bearer sk_live_xxxxx

Response body:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Transaction Status",
  "data": {
    "status": "pending",
    "trx_id": "order_001",
    "available_payment_methods": ["bank-transfer", "crypto"],
    "default_payment_method": "bank-transfer"
  }
}

Checkout index

GET /v1/checkout

Fetch checkout transactions for the authenticated business.

Query:

  • trx_id (optional)
  • reference (optional)
  • status (optional, list mode)
  • customer_email (optional, list mode)
  • date_from (optional, list mode)
  • date_to (optional, list mode)
  • page (optional, list mode, default 1)
  • limit (optional, list mode, default 20, max 100)

Notes:

  • when fetching a single checkout by trx_id or reference, the response also includes available_payment_methods and default_payment_method
  • the account field is returned in the same normalized checkout shape used by create/account/crypto responses
  • when no filter is passed, the endpoint returns a list of checkout transactions ordered by latest first
  • list mode returns pagination metadata in meta
  • date-only filters like 2026-05-16 are expanded to full-day boundaries:
    • date_from => 2026-05-16 00:00:00
    • date_to => 2026-05-16 23:59:59

Single checkout response:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Transactions",
  "data": {
    "id": 1,
    "trx_id": "order_001",
    "reference": "ts-12345678",
    "status": "pending",
    "account": {
      "fiat": {
        "bank_code": "090286",
        "bank_name": "Safe Haven MFB",
        "account_name": "TSARA CHECKOUT",
        "account_number": "1234567890"
      }
    },
    "available_payment_methods": ["bank-transfer", "crypto"],
    "default_payment_method": "bank-transfer"
  }
}

List response:

{
  "success": true,
  "status": "success",
  "status_code": 200,
  "message": "Transactions",
  "data": [
    {
      "id": 2,
      "trx_id": "order_002",
      "reference": "ts-87654321",
      "status": "pending",
      "account": {
        "crypto": {
          "network_asset": "solana:usdc",
          "asset": "usdc"
        }
      },
      "available_payment_methods": ["crypto"],
      "default_payment_method": "crypto"
    },
    {
      "id": 1,
      "trx_id": "order_001",
      "reference": "ts-12345678",
      "status": "pending",
      "account": {
        "fiat": {
          "bank_code": "090286",
          "bank_name": "Safe Haven MFB",
          "account_name": "TSARA CHECKOUT",
          "account_number": "1234567890"
        }
      },
      "available_payment_methods": ["bank-transfer", "crypto"],
      "default_payment_method": "bank-transfer"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 2,
    "total_pages": 1
  }
}