Checkout
The unauthenticated API behind the hosted payment page. Read an invoice as the buyer sees it, pick a chain and currency, and poll the payment that comes back. Possession of the invoice id is the capability โ nothing is signed.
/checkout/api/v1/invoices/{id}RecommendedEverything the payment page renders: the merchant company name in full, the buyer email and name masked, the amount, and the blockchain/currency matrix the buyer picks from. Stamps viewedAt on the first call. Returns 400 with code INVOICE_EXPIRED or INVOICE_CANCELLED โ not 200 โ when the invoice is no longer payable, and 404 INVOICE_NOT_FOUND otherwise.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter โ invoice CUID, as returned by the gateway create-invoice call |
{
"id": "clx7k2p9a0001qz8fh3n2v4m6",
"referenceId": "INV-260826-041B",
"amount": "12500",
"currency": "USD",
"description": "Order #4471 โ annual plan",
"merchant": {
"name": "Northwind Digital LLC"
},
"availableBlockchains": [
"ethereum",
"polygon",
"bsc",
"bitcoin",
"tron",
"solana",
"ton",
"arbitrum",
"optimism",
"base",
"avalanche"
],
"availableCurrencies": {
"ethereum": [
"ETH",
"USDT",
"USDC"
],
"polygon": [
"POL",
"USDT",
"USDC"
],
"bsc": [
"BNB",
"USDT",
"USDC"
],
"bitcoin": [
"BTC"
],
"tron": [
"TRX",
"USDT"
],
"solana": [
"SOL",
"USDC"
],
"ton": [
"TON",
"USDT"
],
"arbitrum": [
"ETH",
"USDT",
"USDC"
],
"optimism": [
"ETH",
"USDT",
"USDC"
],
"base": [
"ETH",
"USDC"
],
"avalanche": [
"AVAX",
"USDT",
"USDC"
]
},
"customerEmail": "a***@example.com",
"customerName": "A*** N***",
"status": "OPEN",
"expiresAt": "2026-08-26T14:30:00.000Z",
"returnUrl": "https://shop.example.com/orders/4471/thanks",
"cancelUrl": "https://shop.example.com/orders/4471"
}/checkout/api/v1/invoices/{id}/statusRecommendedThree-field polling projection for the payment page: the invoice status, the id of the most recently created payment (null before the buyer picks a coin), and paidAt. Unlike the full invoice read this stays 200 for EXPIRED and CANCELLED invoices, so it is the safe thing to poll on a timer.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter โ invoice CUID |
{
"status": "PAYMENT_PENDING",
"paymentId": "clx7k2p9a0007qz8f1d0s9k2r",
"paidAt": null
}/checkout/api/v1/invoices/{id}/checkoutRecommendedLocks the invoice to one blockchain/currency pair and returns the instructions the buyer needs to pay. For method "direct" the payment carries paymentAddress โ a one-time address leased from the wallet pool; for "web3" and "havala_wallet" it carries contractAddress, externalId (the bytes32 form), externalIdUuid, treasuryWallet, tokenAddress (null for the chain native coin) and chainId instead, and "havala_wallet" adds requiresConfirmation: true. The payment window is min(now + 30 minutes, invoice expiry) and checkout always runs on MAINNET.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter โ invoice CUID; must currently be OPEN and unexpired |
blockchain | string | Required | Lowercase chain key from availableBlockchains: ethereum, polygon, bsc, bitcoin, tron, solana, ton, arbitrum, optimism, base, avalanche |
cryptoCurrency | string | Required | Token symbol that the chosen chain supports (see availableCurrencies); rejected with INVALID_CURRENCY otherwise |
method | string | Required | direct | web3 | havala_wallet. web3 and havala_wallet are EVM-only (ethereum, polygon, bsc, arbitrum, optimism, base, avalanche) and fail with BLOCKCHAIN_NOT_SUPPORTED elsewhere |
{
"blockchain": "ethereum",
"cryptoCurrency": "USDT",
"method": "direct"
}{
"payment": {
"id": "clx7k2p9a0007qz8f1d0s9k2r",
"referenceId": "PAY-260826-118A",
"method": "direct",
"paymentAddress": "0xe58b081006f7e3dfc967a64cb14028d512c9791e",
"amount": "12500",
"cryptoCurrency": "USDT",
"blockchain": "ethereum",
"network": "MAINNET",
"decimals": 6,
"expiresAt": "2026-08-26T14:12:00.000Z"
}
}/checkout/api/v1/payments/{id}/statusRecommendedConfirmation progress for one payment: status, confirmations against requiredConfirmations (12 on Ethereum mainnet, 128 on Polygon, 3 on Bitcoin, and so on per chain), the transaction hash, and the address the buyer was told to pay. transactionHash stays null until a transaction is matched; paymentAddress is the leased pool address on a direct payment and the treasury wallet on a smart-contract one.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter โ payment CUID, from the create-payment response or the invoice status poll |
{
"status": "CONFIRMING",
"confirmations": 7,
"requiredConfirmations": 12,
"transactionHash": "0xa4c123b1612dd272d1371c17149d439536b3216fdaeeb975729fae923d5a4fd1",
"blockchain": "ethereum",
"amount": "12500",
"cryptoCurrency": "USDT",
"paymentAddress": "0xe58b081006f7e3dfc967a64cb14028d512c9791e",
"expiresAt": "2026-08-26T14:12:00.000Z"
}/checkout/api/v1/payments/{id}/confirmOptionalAttaches a client-signed transaction hash to a SMART_CONTRACT payment, verifies the receipt on chain, moves the payment to PROCESSING, and starts confirmation tracking. Idempotent: a payment already PROCESSING, CONFIRMING or COMPLETED returns its current state with message "Payment is already being processed" instead of an error. Rejects an unmined hash with TX_NOT_FOUND, so retry after a few seconds rather than treating it as fatal.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter โ payment CUID; must be PENDING and of paymentType SMART_CONTRACT (created with method web3 or havala_wallet) |
txHash | string | Required | Transaction hash of the signed payment, matching ^0x[a-fA-F0-9]{64}$ |
{
"txHash": "0xcc3fc1626e53a13043b026c48bbf33feff9243a8f506b40928b5b7a767c76fb0"
}{
"status": "PROCESSING",
"transactionHash": "0xcc3fc1626e53a13043b026c48bbf33feff9243a8f506b40928b5b7a767c76fb0",
"confirmations": 0,
"requiredConfirmations": 12,
"message": "Payment confirmed, tracking confirmations"
}Category Summary
Total Endpoints
5
Base Domain
api2.havala.io