Guides
Error Handling
Error envelope format, error codes, and idempotency keys
All API errors follow a consistent envelope format. Use the code field for programmatic handling and message for user-facing display.
Error envelope
{
"error": {
"code": "not_found",
"message": "invoice not found",
"details": []
},
"meta": {
"request_id": "req_abc123"
}
}Always include meta.request_id in support tickets for faster debugging.
Error codes
| HTTP | Code | Description |
|---|---|---|
| 400 | validation_error | Request body or parameters failed validation |
| 400 | invalid_state | Operation not allowed in current resource state |
| 401 | unauthorized | Missing or invalid API key / JWT |
| 403 | forbidden | Valid credentials but insufficient permissions |
| 404 | not_found | Resource does not exist |
| 409 | conflict | Idempotency key reused with different parameters |
| 429 | rate_limited | Too many requests - see Rate Limits |
| 500 | internal_error | Server error - retry with backoff |
| 503 | gate_offline | Blockchain processor temporarily unavailable |
Handling errors
try {
const invoice = await halfin.createInvoice({
currency: 'BTC',
amount: '0.001',
});
} catch (err) {
if (err.status === 429) {
// Back off and retry
await sleep(parseInt(err.headers['retry-after'] || '60', 10) * 1000);
return retry();
}
if (err.body?.error?.code === 'gate_offline') {
// Try a different currency or show a maintenance message
}
console.error(`halfin error: ${err.body?.error?.message} (${err.body?.meta?.request_id})`);
}Retry only 429 and 5xx. Validation errors (400 validation_error) and 409 conflict will not change without modifying the request - retrying them just wastes quota.
Idempotency keys
Prevent duplicate invoices by passing an idempotency_key:
const invoice = await halfin.createInvoice({
currency: 'BTC',
amount: '0.001',
idempotency_key: 'order-1234-attempt-1',
});- If you retry with the same key and same parameters, you get the original response.
- If you retry with the same key but different parameters, you get a
409 conflicterror. - Keys are scoped to your merchant account and environment.