Create Checkout
Create a Checkout to request payment. There are two endpoints available depending on your integration type.
API Endpoints
Server API (Recommended for Kiosk/POS)
Use this endpoint for server-to-server integrations like kiosks, POS systems, or backend services.
POST /v1/checkouts
| Header | Required | Description |
|---|---|---|
x-api-key | Yes | Your Server Key (volr_server_...) |
Content-Type | Yes | application/json |
Server Key Only
This endpoint requires a Server Key (volr_server_...), not an API Key. Using an API Key will result in an INVALID_KEY_TYPE error.
Dashboard API
Use this endpoint when creating checkouts from the Dashboard or authenticated web applications.
POST /dashboard/projects/{projectId}/checkouts
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer JWT token |
Content-Type | Yes | application/json |
Request Body
Token Amount (Direct)
Specify the exact token amount you want to receive.
{
"chainId": 8453,
"tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"merchantAddress": "0xYourMerchantWalletAddress",
"amount": "10000000",
"itemName": "Americano",
"referenceId": "ORDER-12345"
}
Fiat Amount (Fiat Price)
Specify the fiat value and let Volr calculate the token amount.
{
"chainId": 8453,
"tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"merchantAddress": "0xYourMerchantWalletAddress",
"fiatAmount": "4.50",
"fiatCurrency": "EUR",
"itemName": "Americano",
"referenceId": "ORDER-12345"
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
chainId | number | Yes | Chain ID (e.g., 8453=Base) |
tokenAddress | string | Yes | ERC-20 token address (converted to lowercase) |
merchantAddress | string | Yes (Server API) | Merchant wallet address to receive payments. Required for /v1/checkouts. Auto-filled for Dashboard API. |
amount | string | Conditional | Token amount in smallest unit (wei). Required if fiatAmount not used |
fiatAmount | string | Conditional | Fiat amount (e.g., "5000"). Required if amount not used |
fiatCurrency | string | Conditional | Fiat currency code (e.g., USD, EUR, KRW). Required when using fiatAmount. See Public Endpoints for supported currencies |
amountMode | string | No | Amount mode: FIXED (default), MINIMUM, OPEN |
minAmount | string | No | Minimum amount (for MINIMUM mode) |
maxAmount | string | No | Maximum amount |
expiryMinutes | number | No | Expiry time in minutes. Default: 30, Min: 5, Max: 1440. Max 30 for fiat payments |
customerEmail | string | No | Customer email |
customerName | string | No | Customer name |
itemName | string | No | Item name |
itemDescription | string | No | Item description |
itemImageUrl | string | No | Item image URL |
referenceId | string | No | Client order ID (unique per project, used for deduplication) |
metadata | object | No | Custom metadata (JSON) |
successUrl | string | No | Redirect URL on payment success |
cancelUrl | string | No | Redirect URL on payment cancel |
Response
Success (201 Created)
{
"ok": true,
"data": {
"id": "cm5xyz123abc",
"projectId": "project_id",
"chainId": 8453,
"tokenAddress": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"amount": "3703703",
"amountMode": "FIXED",
"depositAddress": "0xabc123def456...",
"salt": "0x...",
"merchantAddress": "0xmerchant...",
"feeBps": 50,
"fixedFeeAmount": "0",
"status": "PENDING",
"expiresAt": "2026-01-30T11:00:00.000Z",
"createdAt": "2026-01-30T10:30:00.000Z",
"updatedAt": "2026-01-30T10:30:00.000Z",
"itemName": "Americano",
"referenceId": "ORDER-12345",
"fiatAmount": "4.50",
"fiatCurrency": "EUR",
"exchangeRateUsed": "0.92",
"exchangeRateAt": "2026-01-30T10:30:00.000Z"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique checkout ID (CUID format) |
depositAddress | string | Address where customer sends payment (CREATE2 generated) |
amount | string | Token amount in smallest unit |
status | string | PENDING, DETECTED, PAID, SETTLED, EXPIRED, LATE_PAID, CANCELLED |
expiresAt | string | ISO 8601 timestamp when checkout expires |
feeBps | number | Fee in basis points (50 = 0.5%) |
exchangeRateUsed | string | Exchange rate used for fiat conversion (null if direct amount) |
Error Responses
Authentication Errors
Missing Server Key
{
"ok": false,
"error": {
"code": "SERVER_KEY_REQUIRED",
"message": "Server API key is required"
}
}
Invalid Key Type
{
"ok": false,
"error": {
"code": "INVALID_KEY_TYPE",
"message": "This endpoint requires a server key (volr_server_...)"
}
}
Project Not Found
{
"ok": false,
"error": {
"code": "PROJECT_NOT_FOUND",
"message": "Project not found"
}
}
Validation Errors
Missing Amount
{
"ok": false,
"error": {
"code": "AMOUNT_OR_FIAT_REQUIRED",
"message": "Either amount or fiatAmount must be provided"
}
}
Missing Fiat Currency
{
"ok": false,
"error": {
"code": "FIAT_CURRENCY_REQUIRED",
"message": "fiatCurrency is required when using fiatAmount"
}
}
Unsupported Token for Fiat
{
"ok": false,
"error": {
"code": "UNSUPPORTED_TOKEN_FOR_FIAT",
"message": "Token ETH is not supported for fiat conversion. Supported: USDC, USDT"
}
}
Exchange Rate Unavailable
{
"ok": false,
"error": {
"code": "EXCHANGE_RATE_UNAVAILABLE",
"message": "Unable to fetch exchange rate. Please try again later."
}
}
Amount Too Small
{
"ok": false,
"error": {
"code": "AMOUNT_TOO_SMALL",
"message": "Amount too small. Minimum amount required to cover fees: 1000000"
}
}
Supported Chains & Tokens
Mainnet
| Chain | Chain ID | Supported Tokens |
|---|---|---|
| Base | 8453 | USDC, USDT |
Token Addresses
| Token | Chain | Address |
|---|---|---|
| USDC | Base | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
Coming Soon
Support for additional networks (Arbitrum, Polygon) is planned for future releases.
Examples
Server API (cURL)
curl -X POST https://api.volr.io/v1/checkouts \
-H "x-api-key: volr_server_xxx" \
-H "Content-Type: application/json" \
-d '{
"chainId": 8453,
"tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"merchantAddress": "0xYourMerchantWallet",
"fiatAmount": "4.50",
"fiatCurrency": "EUR",
"itemName": "Americano",
"referenceId": "ORDER-12345"
}'
Server API (Node.js)
const SERVER_KEY = process.env.VOLR_SERVER_KEY; // volr_server_xxx
const MERCHANT_ADDRESS = process.env.VOLR_MERCHANT_ADDRESS;
const createCheckout = async (priceEUR, itemName) => {
const response = await fetch('https://api.volr.io/v1/checkouts', {
method: 'POST',
headers: {
'x-api-key': SERVER_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
chainId: 8453,
tokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
merchantAddress: MERCHANT_ADDRESS,
fiatAmount: priceEUR.toString(),
fiatCurrency: 'EUR',
itemName,
referenceId: `ORDER-${Date.now()}`,
}),
});
const { ok, data, error } = await response.json();
if (!ok) {
throw new Error(error.message);
}
return data;
};
Server API (Python)
import requests
import os
import time
SERVER_KEY = os.environ['VOLR_SERVER_KEY'] # volr_server_xxx
MERCHANT_ADDRESS = os.environ['VOLR_MERCHANT_ADDRESS']
def create_checkout(price_eur: float, item_name: str):
response = requests.post(
"https://api.volr.io/v1/checkouts",
headers={
"x-api-key": SERVER_KEY,
"Content-Type": "application/json",
},
json={
"chainId": 8453,
"tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"merchantAddress": MERCHANT_ADDRESS,
"fiatAmount": str(price_eur),
"fiatCurrency": "EUR",
"itemName": item_name,
"referenceId": f"ORDER-{int(time.time())}",
},
)
result = response.json()
if not result["ok"]:
raise Exception(result["error"]["message"])
return result["data"]