Checkout Invoice
POST
/api/v1/invoices/{id}/checkoutCorePick the chain and token for an OPEN invoice. Havala creates a DIRECT payment, leases a one-time deposit address from the wallet pool for that chain, and moves the invoice to PAYMENT_PENDING. Send the buyer to paymentAddress and watch that payment; the window is 30 minutes or whatever is left of the invoice expiry, whichever ends sooner.
Authentication
Signature Pattern
HMAC-SHA256(apiSecret, "{t}\nPOST\n/api/v1/invoices/{id}/checkout\n{idempotencyKey}\n{sha256(body)}")| Header | Value | Description |
|---|---|---|
X-API-Key | a3f9c1e84b7d2065f1a4c8e93b6d0271 | Merchant point API key, a hex string issued with its secret when the point is created. Identifies the point whose invoices you can reach. |
X-Signature | t=1787735662,v1=8c1f0b7d4a29e63f5b0c8d17a4e92f6b3d05c7a81e4f9b26d3c07a5e18b4f962 | Request signature, format t={unix_seconds},v1={hex_hmac_sha256}. Timestamp tolerance is 300s. |
Content-Type | application/json | Always application/json. The signature is taken over the raw body bytes, so send exactly what you signed. |
Idempotency-Key | 9f2b1c44-7a0e-4d63-9f18-2c5b7ea31d04 | Required on POST/DELETE. Unique per logical operation; replays return the first response for 24h. |
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter โ invoice CUID. Must be OPEN and unexpired, otherwise INVOICE_NOT_AVAILABLE or INVOICE_EXPIRED. |
blockchain | string | Required | Lower-case chain key: ethereum, polygon, bsc, arbitrum, optimism, base, avalanche, bitcoin, tron, solana, ton. |
cryptoCurrency | string | Required | Token symbol configured on that chain, e.g. ETH, USDT or USDC on ethereum. An unsupported pair is rejected with INVALID_CURRENCY. |
network | string | Optional | Optional testnet selector, written straight to the payment NetworkEnum column: SEPOLIA, GOERLI, HOLESKY, AMOY, MUMBAI, bsc-testnet, FUJI, NILE, TESTNET, DEVNET, testnet-generic. Omit it for mainnet โ the payment then defaults to MAINNET and is flagged live. |
Request Example
JSONRequest Body
{
"blockchain": "ethereum",
"cryptoCurrency": "USDT"
}Response Parameters
| Field | Type | Example |
|---|---|---|
invoice | object | {โฆ} |
invoice.id | string | "clyv3n8x40001qh7m2k9d5b1t" |
invoice.referenceId | string | "INV-260826-041C" |
invoice.orderId | string | "order-8814" |
invoice.description | string | "Pro plan, annual billing" |
invoice.amount | string | "12500" |
invoice.currency | string | "USD" |
invoice.status | string | "PAYMENT_PENDING" |
invoice.customerEmail | string | "buyer@example.com" |
invoice.customerName | string | "Ada Lovelace" |
invoice.customerMetadata | object | {โฆ} |
invoice.customerMetadata.userId | integer | 4471 |
invoice.metadata | object | {โฆ} |
invoice.metadata.internalRef | string | "sub_2026_08_pro" |
invoice.returnUrl | string | "https://merchant.example.com/checkout/suโฆ |
invoice.cancelUrl | string | "https://merchant.example.com/checkout/caโฆ |
invoice.expiresAt | string | "2026-08-26T10:14:22.481Z" |
invoice.viewedAt | null | null |
invoice.paidAt | null | null |
invoice.cancelledAt | null | null |
invoice.createdAt | string | "2026-08-26T09:14:22.481Z" |
payment | object | {โฆ} |
payment.id | string | "clyv4p1c70003qh7m8w2r6z9f" |
payment.referenceId | string | "PAY-260826-118A" |
payment.paymentAddress | string | "0x7Ae2d4C1f83B90e5A6c7D218Ff43b9C0E15d8a72" |
payment.amount | string | "12500" |
payment.blockchain | string | "ethereum" |
payment.cryptoCurrency | string | "USDT" |
payment.status | string | "PENDING" |
payment.expiresAt | string | "2026-08-26T09:44:26.902Z" |
payment.createdAt | string | "2026-08-26T09:14:26.902Z" |
Response Example
JSONResponse
{
"success": true,
"data": {
"invoice": {
"id": "clyv3n8x40001qh7m2k9d5b1t",
"referenceId": "INV-260826-041C",
"orderId": "order-8814",
"description": "Pro plan, annual billing",
"amount": "12500",
"currency": "USD",
"status": "PAYMENT_PENDING",
"customerEmail": "buyer@example.com",
"customerName": "Ada Lovelace",
"customerMetadata": {
"userId": 4471
},
"metadata": {
"internalRef": "sub_2026_08_pro"
},
"returnUrl": "https://merchant.example.com/checkout/success",
"cancelUrl": "https://merchant.example.com/checkout/cancel",
"expiresAt": "2026-08-26T10:14:22.481Z",
"viewedAt": null,
"paidAt": null,
"cancelledAt": null,
"createdAt": "2026-08-26T09:14:22.481Z"
},
"payment": {
"id": "clyv4p1c70003qh7m8w2r6z9f",
"referenceId": "PAY-260826-118A",
"paymentAddress": "0x7Ae2d4C1f83B90e5A6c7D218Ff43b9C0E15d8a72",
"amount": "12500",
"blockchain": "ethereum",
"cryptoCurrency": "USDT",
"status": "PENDING",
"expiresAt": "2026-08-26T09:44:26.902Z",
"createdAt": "2026-08-26T09:14:26.902Z"
}
},
"timestamp": "2026-08-26T13:41:02.477Z",
"requestId": "req_V1StGXR8_Z5j"
}Error shape
JSONError
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Resource not found"
},
"timestamp": "2026-08-26T13:41:02.477Z",
"requestId": "req_V1StGXR8_Z5j"
}Status Codes
200Success
201Created
400Bad Request
401Unauthorized
404Not Found
429Rate Limited
Try itMockapi2.havala.io
POSThttps://api2.havala.io