API Reference
The CleraChain API lets you programmatically create invoices, manage payment links, handle withdrawals, and receive real-time webhook notifications for your crypto payment flows.
https://testnet.clerachain.com
API Key in header
JSON request/response
All requests must include a Content-Type: application/json header. Responses always return JSON. Timestamps are in ISO 8601 format. Monetary amounts are in the currency's smallest denomination or as decimal strings.
Authentication
All API requests require authentication via an API key pair. Generate your keys from the Dashboard > API Keys page. Each key pair consists of a publishable key (cpay_xxx) and a secret key (csk_xxx).
Header Format
Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4Example Request
curl https://testnet.clerachain.com/api/invoices \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4" \
-H "Content-Type: application/json"Keep your secret key safe
Never expose your secret key in client-side code, public repositories, or logs. If compromised, rotate your keys immediately from the dashboard.
Invoices
Invoices are the core payment object. Create an invoice with an amount and currency, then redirect your customer to the hosted checkout page to complete payment.
Create Invoice
Creates a new invoice and returns a hosted checkout URL. The customer selects their preferred chain and token on the checkout page.
/api/invoicesHeaders
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | ApiKey cpay_xxx:csk_xxx |
Content-Type | string | Required | application/json |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | number | Required | Invoice amount in the specified currency |
currency | string | Required | Currency code: "USD", "EUR", "GBP", etc. |
callbackUrl | string | Optional | URL to redirect customer after payment |
customerName | string | Optional | Customer display name |
customerEmail | string | Optional | Customer email for receipt |
items | array | Optional | Line items: [{name, quantity, price}] |
taxRate | number | Optional | Tax rate as percentage (e.g., 8.5) |
discount | number | Optional | Discount amount in currency units |
reference | string | Optional | Your internal reference / order ID |
expiresInMinutes | number | Optional | Invoice expiry time in minutes (default: 60) |
Response
{
"invoice": {
"id": "inv_8a3f2b1c9d4e",
"invoiceNumber": "INV-2026-0042",
"amount": 150.00,
"currency": "USD",
"status": "pending",
"checkoutUrl": "https://testnet.clerachain.com/checkout/inv_8a3f2b1c9d4e",
"expiresAt": "2026-03-29T15:30:00.000Z",
"customerName": "Alice Johnson",
"customerEmail": "alice@example.com",
"reference": "order_12345",
"items": [
{ "name": "Pro Plan - Monthly", "quantity": 1, "price": 150.00 }
],
"taxRate": 0,
"discount": 0,
"createdAt": "2026-03-29T14:30:00.000Z"
}
}Code Example
curl -X POST https://testnet.clerachain.com/api/invoices \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4" \
-H "Content-Type: application/json" \
-d '{
"amount": 150.00,
"currency": "USD",
"callbackUrl": "https://yoursite.com/payment/success",
"customerName": "Alice Johnson",
"customerEmail": "alice@example.com",
"items": [
{ "name": "Pro Plan - Monthly", "quantity": 1, "price": 150.00 }
],
"reference": "order_12345",
"expiresInMinutes": 30
}'List Invoices
Returns a list of all invoices for your merchant account, sorted by creation date (newest first). Requires authentication.
/api/invoicesHeaders
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | ApiKey cpay_xxx:csk_xxx |
Response
{
"invoices": [
{
"id": "inv_8a3f2b1c9d4e",
"invoiceNumber": "INV-2026-0042",
"amount": 150.00,
"currency": "USD",
"status": "paid",
"checkoutUrl": "https://testnet.clerachain.com/checkout/inv_8a3f2b1c9d4e",
"customerName": "Alice Johnson",
"reference": "order_12345",
"createdAt": "2026-03-29T14:30:00.000Z",
"paidAt": "2026-03-29T14:35:22.000Z"
},
{
"id": "inv_7b2e1a0d8c3f",
"invoiceNumber": "INV-2026-0041",
"amount": 49.99,
"currency": "USD",
"status": "expired",
"checkoutUrl": "https://testnet.clerachain.com/checkout/inv_7b2e1a0d8c3f",
"customerName": "Bob Smith",
"reference": "order_12344",
"createdAt": "2026-03-28T10:00:00.000Z",
"expiresAt": "2026-03-28T11:00:00.000Z"
}
]
}Code Example
curl https://testnet.clerachain.com/api/invoices \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4"Get Invoice
Retrieves a single invoice by ID. This endpoint is public and does not require authentication, enabling you to fetch invoice details on client-side checkout pages.
/api/invoices/:idPath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Required | The invoice ID (e.g., inv_8a3f2b1c9d4e) |
Response
{
"invoice": {
"id": "inv_8a3f2b1c9d4e",
"invoiceNumber": "INV-2026-0042",
"amount": 150.00,
"currency": "USD",
"status": "pending",
"walletAddress": "0x1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0B",
"merchantName": "Acme Corp",
"enabledChains": ["ethereum", "bsc", "solana", "tron"],
"selectedChain": null,
"selectedToken": null,
"checkoutUrl": "https://testnet.clerachain.com/checkout/inv_8a3f2b1c9d4e",
"callbackUrl": "https://yoursite.com/payment/success",
"customerName": "Alice Johnson",
"customerEmail": "alice@example.com",
"items": [
{ "name": "Pro Plan - Monthly", "quantity": 1, "price": 150.00 }
],
"expiresAt": "2026-03-29T15:30:00.000Z",
"createdAt": "2026-03-29T14:30:00.000Z"
}
}Code Example
curl https://testnet.clerachain.com/api/invoices/inv_8a3f2b1c9d4ePayment Selection
Allows the customer to select which blockchain and token they want to pay with. Returns the invoice updated with a wallet address for the chosen chain.
/api/invoices/:idPath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Required | The invoice ID |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
chain | string | Required | "bsc" | "ethereum" | "solana" | "tron" |
token | string | Required | "USDT" | "USDC" |
Response
{
"invoice": {
"id": "inv_8a3f2b1c9d4e",
"walletAddress": "0x1a2B3c4D5e6F7a8B9c0D1e2F3a4B5c6D7e8F9a0B",
"token": "USDT",
"chain": "bsc",
"amount": 150.00,
"status": "awaiting_payment"
}
}Code Example
curl -X PATCH https://testnet.clerachain.com/api/invoices/inv_8a3f2b1c9d4e \
-H "Content-Type: application/json" \
-d '{
"chain": "bsc",
"token": "USDT"
}'Payment Links
Payment links are reusable, shareable URLs that create invoices on the fly. Ideal for subscriptions, donations, or any scenario where you want a persistent payment page.
Create Payment Link
Creates a shareable payment link. If no amount is specified, the customer can enter any amount on the payment page.
/api/merchant/payment-linksHeaders
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | ApiKey cpay_xxx:csk_xxx |
Content-Type | string | Required | application/json |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | Required | Display title for the payment link page |
description | string | Optional | Description shown on the payment page |
amount | number | Optional | Fixed amount. If omitted, customer chooses amount |
currency | string | Optional | Currency code (default: "USD") |
Response
{
"paymentLink": {
"id": "pl_4f8e2a1b7c3d",
"slug": "pro-plan-monthly",
"title": "Pro Plan - Monthly",
"description": "Monthly subscription to the Pro plan",
"amount": 49.99,
"currency": "USD",
"url": "https://testnet.clerachain.com/pay/pro-plan-monthly",
"active": true,
"createdAt": "2026-03-29T14:30:00.000Z"
}
}Code Example
curl -X POST https://testnet.clerachain.com/api/merchant/payment-links \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4" \
-H "Content-Type: application/json" \
-d '{
"title": "Pro Plan - Monthly",
"description": "Monthly subscription to the Pro plan",
"amount": 49.99,
"currency": "USD"
}'List Payment Links
Returns all payment links for your merchant account.
/api/merchant/payment-linksResponse
{
"paymentLinks": [
{
"id": "pl_4f8e2a1b7c3d",
"slug": "pro-plan-monthly",
"title": "Pro Plan - Monthly",
"amount": 49.99,
"currency": "USD",
"url": "https://testnet.clerachain.com/pay/pro-plan-monthly",
"active": true,
"totalPayments": 23,
"totalRevenue": 1149.77,
"createdAt": "2026-03-29T14:30:00.000Z"
}
]
}Code Example
curl https://testnet.clerachain.com/api/merchant/payment-links \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4"Webhooks
Webhooks send real-time HTTP POST notifications to your server when events occur. Register an endpoint URL and specify which events you want to receive.
Create Webhook Endpoint
Registers a new webhook endpoint. You will receive a signing secret (whsec_xxx) used to verify webhook payloads.
/api/merchant/webhooksHeaders
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | ApiKey cpay_xxx:csk_xxx |
Content-Type | string | Required | application/json |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Required | HTTPS URL to receive webhook POST requests |
events | string[] | Required | Array of event types to subscribe to |
Response
{
"endpoint": {
"id": "we_9c4d3e2f1a0b",
"url": "https://yoursite.com/webhooks/clerachain",
"secret": "whsec_k7m2n8p4q1r6s3t9u5v0w",
"events": [
"payment.confirmed",
"invoice.expired",
"withdrawal.completed"
],
"active": true,
"createdAt": "2026-03-29T14:30:00.000Z"
}
}Code Example
curl -X POST https://testnet.clerachain.com/api/merchant/webhooks \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yoursite.com/webhooks/clerachain",
"events": [
"payment.confirmed",
"invoice.expired",
"withdrawal.completed"
]
}'List Webhook Endpoints
Returns all registered webhook endpoints for your merchant account.
/api/merchant/webhooksResponse
{
"endpoints": [
{
"id": "we_9c4d3e2f1a0b",
"url": "https://yoursite.com/webhooks/clerachain",
"events": ["payment.confirmed", "invoice.expired", "withdrawal.completed"],
"active": true,
"createdAt": "2026-03-29T14:30:00.000Z"
}
]
}curl https://testnet.clerachain.com/api/merchant/webhooks \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4"Webhook Events
Available event types you can subscribe to. Each event sends a JSON payload with event metadata and the relevant resource data.
| Event | Description |
|---|---|
payment.confirmed | A payment has been confirmed on-chain and credited to the invoice |
invoice.expired | An invoice has passed its expiry time without receiving full payment |
withdrawal.completed | A withdrawal has been broadcast and confirmed on-chain |
Event Payload Format
{
"id": "evt_5a8b3c2d1e0f",
"type": "payment.confirmed",
"createdAt": "2026-03-29T14:35:22.000Z",
"data": {
"invoiceId": "inv_8a3f2b1c9d4e",
"amount": 150.00,
"currency": "USD",
"chain": "bsc",
"token": "USDT",
"txHash": "0xabc123def456789...",
"confirmedAt": "2026-03-29T14:35:22.000Z"
}
}Webhook Verification
Every webhook request includes an HMAC-SHA256 signature in the X-CleraChain-Signatureheader. Verify this signature using your webhook endpoint's whsec_ secret to ensure authenticity.
Webhook Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
X-CleraChain-Signature | string | Required | HMAC-SHA256 hex digest of the raw request body |
X-CleraChain-Timestamp | string | Required | Unix timestamp of when the webhook was sent |
X-CleraChain-Event | string | Required | The event type (e.g., payment.confirmed) |
Verification Example
import crypto from 'crypto';
function verifyWebhook(req, secret) {
const signature = req.headers['x-clerachain-signature'];
const timestamp = req.headers['x-clerachain-timestamp'];
const body = JSON.stringify(req.body);
// Prevent replay attacks: reject if timestamp is > 5 min old
const age = Math.abs(Date.now() / 1000 - parseInt(timestamp));
if (age > 300) {
throw new Error('Webhook timestamp too old');
}
// Compute expected signature
const payload = `${timestamp}.${body}`;
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
// Constant-time comparison
const isValid = crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
if (!isValid) {
throw new Error('Invalid webhook signature');
}
return JSON.parse(body);
}
// Usage in your webhook handler:
// const secret = 'whsec_k7m2n8p4q1r6s3t9u5v0w';
// const event = verifyWebhook(req, secret);
// switch (event.type) {
// case 'payment.confirmed': ...
// case 'invoice.expired': ...
// case 'withdrawal.completed': ...
// }Always verify signatures
Never process webhook events without verifying the HMAC signature. Always use constant-time comparison to prevent timing attacks. Reject requests with timestamps older than 5 minutes.
Deposit Addresses
Generate dedicated deposit addresses for each supported blockchain. Incoming funds to these addresses are automatically detected and credited to your merchant balance.
Create Deposit Address
Generates a new deposit address on the specified blockchain. You can optionally assign a label for internal tracking.
/api/merchant/addressesHeaders
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | ApiKey cpay_xxx:csk_xxx |
Content-Type | string | Required | application/json |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
chain | string | Required | "ethereum" | "bsc" | "solana" | "tron" |
label | string | Optional | Human-readable label for the address |
Response
{
"address": {
"id": "addr_6b5c4d3e2f1a",
"chain": "ethereum",
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
"label": "Primary ETH Deposits",
"totalReceived": 0,
"active": true,
"createdAt": "2026-03-29T14:30:00.000Z"
}
}Code Example
curl -X POST https://testnet.clerachain.com/api/merchant/addresses \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4" \
-H "Content-Type: application/json" \
-d '{
"chain": "ethereum",
"label": "Primary ETH Deposits"
}'List Deposit Addresses
Returns all deposit addresses for your merchant account.
/api/merchant/addressesResponse
{
"addresses": [
{
"id": "addr_6b5c4d3e2f1a",
"chain": "ethereum",
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
"label": "Primary ETH Deposits",
"totalReceived": 4250.00,
"active": true,
"createdAt": "2026-03-29T14:30:00.000Z"
},
{
"id": "addr_7c6d5e4f3a2b",
"chain": "solana",
"address": "7nYS2b4RfQPkBxKmZs3q4wR8TYhNVj1GnYKbLDzSuMp",
"label": "Solana Deposits",
"totalReceived": 1830.50,
"active": true,
"createdAt": "2026-03-28T10:00:00.000Z"
}
]
}curl https://testnet.clerachain.com/api/merchant/addresses \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4"Withdrawals
Withdraw funds from your merchant balance to an external wallet address. All withdrawals require a security PIN set up from your dashboard.
Create Withdrawal
Initiates a withdrawal from your merchant balance to an external address. Requires your 6-digit security PIN for authorization.
/api/withdrawalsHeaders
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | ApiKey cpay_xxx:csk_xxx |
Content-Type | string | Required | application/json |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | number | Required | Amount to withdraw |
chain | string | Required | "ethereum" | "bsc" | "solana" | "tron" |
token | string | Required | "USDT" | "USDC" |
toAddress | string | Required | Destination wallet address |
pin | string | Required | 6-digit security PIN |
Response
{
"withdrawal": {
"id": "wd_3e2f1a0b9c8d",
"amount": 500.00,
"chain": "ethereum",
"token": "USDT",
"toAddress": "0x8Ba1f109551bD432803012645Ac136ddd64DBA72",
"txHash": "0x7c5ea36004851c764c44143b1dcb59679b11c9a68e5f41497f6cf3d480715331",
"status": "pending",
"fee": 2.50,
"createdAt": "2026-03-29T14:30:00.000Z"
}
}Code Example
curl -X POST https://testnet.clerachain.com/api/withdrawals \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4" \
-H "Content-Type: application/json" \
-d '{
"amount": 500.00,
"chain": "ethereum",
"token": "USDT",
"toAddress": "0x8Ba1f109551bD432803012645Ac136ddd64DBA72",
"pin": "123456"
}'Withdrawals are irreversible
Double-check the destination address and chain before submitting. Sending tokens to the wrong chain or address will result in permanent loss of funds.
List Withdrawals
Returns all withdrawals for your merchant account with status and transaction details.
/api/withdrawalsResponse
{
"withdrawals": [
{
"id": "wd_3e2f1a0b9c8d",
"amount": 500.00,
"chain": "ethereum",
"token": "USDT",
"toAddress": "0x8Ba1f109551bD432803012645Ac136ddd64DBA72",
"txHash": "0x7c5ea36004851c764c44143b1dcb59679b11c9a68e5f41497f6cf3d480715331",
"status": "completed",
"fee": 2.50,
"createdAt": "2026-03-29T14:30:00.000Z",
"completedAt": "2026-03-29T14:32:15.000Z"
}
]
}curl https://testnet.clerachain.com/api/withdrawals \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4"Payouts
Send batch payments to multiple recipients in a single API call. Useful for payroll, affiliate payouts, or distributing funds to multiple wallets.
Create Batch Payout
Creates a batch payout to multiple recipients on the same chain. All recipients receive the specified token. Requires your security PIN.
/api/payouts/batchHeaders
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | ApiKey cpay_xxx:csk_xxx |
Content-Type | string | Required | application/json |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
chain | string | Required | "ethereum" | "bsc" | "solana" | "tron" |
token | string | Required | "USDT" | "USDC" |
recipients | array | Required | Array of {address, amount, reference?} |
pin | string | Required | 6-digit security PIN |
Response
{
"payout": {
"id": "po_1a2b3c4d5e6f",
"chain": "bsc",
"token": "USDT",
"totalAmount": 1500.00,
"recipientCount": 3,
"status": "processing",
"recipients": [
{
"address": "0xabc...123",
"amount": 500.00,
"reference": "affiliate_001",
"txHash": null,
"status": "pending"
},
{
"address": "0xdef...456",
"amount": 750.00,
"reference": "affiliate_002",
"txHash": null,
"status": "pending"
},
{
"address": "0xghi...789",
"amount": 250.00,
"reference": "affiliate_003",
"txHash": null,
"status": "pending"
}
],
"fee": 3.75,
"createdAt": "2026-03-29T14:30:00.000Z"
}
}Code Example
curl -X POST https://testnet.clerachain.com/api/payouts/batch \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4" \
-H "Content-Type: application/json" \
-d '{
"chain": "bsc",
"token": "USDT",
"recipients": [
{ "address": "0xabc...123", "amount": 500.00, "reference": "affiliate_001" },
{ "address": "0xdef...456", "amount": 750.00, "reference": "affiliate_002" },
{ "address": "0xghi...789", "amount": 250.00, "reference": "affiliate_003" }
],
"pin": "123456"
}'List Payouts
Returns all batch payouts for your merchant account with status and recipient details.
/api/payoutsResponse
{
"payouts": [
{
"id": "po_1a2b3c4d5e6f",
"chain": "bsc",
"token": "USDT",
"totalAmount": 1500.00,
"recipientCount": 3,
"status": "completed",
"fee": 3.75,
"createdAt": "2026-03-29T14:30:00.000Z",
"completedAt": "2026-03-29T14:33:45.000Z"
}
]
}curl https://testnet.clerachain.com/api/payouts \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4"Settings
Manage your merchant configuration including enabled chains, callback URLs, branding, and security settings.
Get Settings
/api/merchant/settingsResponse
{
"settings": {
"merchantName": "Acme Corp",
"merchantEmail": "payments@acme.com",
"enabledChains": ["ethereum", "bsc", "solana", "tron"],
"enabledTokens": ["USDT", "USDC"],
"defaultCurrency": "USD",
"callbackUrl": "https://acme.com/webhooks/payment",
"logoUrl": "https://acme.com/logo.png",
"brandColor": "#3b82f6",
"autoWithdraw": false,
"autoWithdrawThreshold": 1000.00,
"autoWithdrawAddress": null,
"securityPinEnabled": true,
"twoFactorEnabled": true
}
}Update Settings
/api/merchant/settingsRequest Body
Send only the fields you want to update. All fields are optional.
| Parameter | Type | Required | Description |
|---|---|---|---|
merchantName | string | Optional | Your business name shown on checkout |
enabledChains | string[] | Optional | Chains to accept payments on |
enabledTokens | string[] | Optional | Tokens to accept (USDT, USDC) |
callbackUrl | string | Optional | Default callback URL for invoices |
brandColor | string | Optional | Hex color for checkout branding |
curl -X PATCH https://testnet.clerachain.com/api/merchant/settings \
-H "Authorization: ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4" \
-H "Content-Type: application/json" \
-d '{
"enabledChains": ["ethereum", "bsc", "solana"],
"brandColor": "#8b5cf6"
}'Errors
CleraChain uses conventional HTTP status codes to indicate the success or failure of API requests. All error responses follow a consistent JSON format.
Error Format
{
"error": "Invoice not found"
}HTTP Status Codes
| Code | Description | Example |
|---|---|---|
200 | OK | Request succeeded |
201 | Created | Resource successfully created |
400 | Bad Request | Missing required field: amount |
401 | Unauthorized | Invalid or missing API key |
403 | Forbidden | Invalid security PIN |
404 | Not Found | Invoice not found |
409 | Conflict | Invoice already paid |
422 | Unprocessable Entity | Unsupported chain: polygon |
429 | Too Many Requests | Rate limit exceeded. Retry after 60s |
500 | Internal Server Error | An unexpected error occurred |
Rate Limiting
API requests are rate limited to 100 requests per minuteper API key. When you exceed the limit, you'll receive a 429 response with a Retry-After header.
// Rate limit headers included in every response:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1711720260Error Handling Example
async function createInvoice(data) {
const response = await fetch('https://testnet.clerachain.com/api/invoices', {
method: 'POST',
headers: {
'Authorization': 'ApiKey cpay_pk_a1b2c3d4e5f6:csk_sk_z9y8x7w6v5u4',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
const { error } = await response.json();
switch (response.status) {
case 400:
console.error('Validation error:', error);
break;
case 401:
console.error('Authentication failed:', error);
break;
case 429:
const retryAfter = response.headers.get('Retry-After');
console.error(`Rate limited. Retry after ${retryAfter}s`);
break;
default:
console.error(`API error (${response.status}):`, error);
}
throw new Error(error);
}
return response.json();
}