> ## Documentation Index
> Fetch the complete documentation index at: https://www.bitnob.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Bitnob API requests authenticate with an `X-Auth-Client` API key header against https://api.bitnob.com.
> Always use the sandbox environment for testing. Never put live API keys in sample code.
> Money amounts are integers in the smallest unit of the currency (satoshis for BTC, cents for fiat). Never use floats.
> Every state-changing request takes a client-supplied `reference` and must be treated as idempotent on retry.
> Quotes expire. Re-quote rather than reusing a stale quote id.

# Errors and retries

> Errors shared by every Bitnob Business API endpoint: HTTP statuses, the error body, rate limits, and retrying without moving money twice.

Every Bitnob Business API endpoint shares one error model. The Bitnob Enterprise API uses a different one; see [Making Bitnob Enterprise API requests](https://www.bitnob.dev/docs/platform/making-requests.md#errors). Product sections document their own failure scenarios, [payouts](https://www.bitnob.dev/docs/payouts/error-handling.md), [stablecoins](https://www.bitnob.dev/docs/stablecoins/error-handling-and-failure-scenarios.md), [trading](https://www.bitnob.dev/docs/trading/error-handling-patterns.md), [cards](https://www.bitnob.dev/docs/card-issuing/card-fees.md); this page covers what they all have in common.

## Status codes

| Status | Meaning | Retry? |
| - | - | - |
| `400` | Invalid request: missing fields, malformed values, unsupported pairs. | After fixing the request. |
| `401` | Authentication failed: missing header, bad signature, stale timestamp. | After fixing signing; see [Quickstart](https://www.bitnob.dev/docs/getting-started/quickstart.md). |
| `403` | Authenticated but not permitted: feature not enabled, IP not whitelisted. | No; resolve the permission. |
| `404` | No such resource, or a reference that does not exist on your account. | No; check the identifier. |
| `409` | Conflict, typically a duplicate `reference` on a withdrawal. | No; fetch the original result. |
| `410` | Gone, typically an expired quote. | With a fresh quote. |
| `422` | Precondition failed: insufficient balance, an expired or already-used trading quote. Card calls return `400` for insufficient balance. | After the condition changes, or with a fresh quote. |
| `429` | Rate limited. | Yes, with backoff; wait for `X-Ratelimit-Reset`. |
| `5xx` | Temporary problem on Bitnob's side. | Yes, with backoff. |

## The error body

Error responses follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807).

```json theme={null}
{
  "type": "https://api.bitnob.com/errors/UNAUTHORIZED",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Invalid HMAC signature",
  "code": "UNAUTHORIZED",
  "correlation_id": "req_019d9b7e-9e76-711e-afbe-aba9b9455412",
  "timestamp": "2026-04-17T12:50:59.850532036Z"
}
```

| Field | Use |
| - | - |
| `title` | Short, stable description of the error class. |
| `detail` | What went wrong on this specific request. Safe to log; do not parse it. |
| `code` | Machine-readable identifier. Branch on this, not on `detail`. |
| `correlation_id` | Identifies the exact request in our systems. |

Every error body carries `correlation_id`, and repeats it as `request_id`. Log `correlation_id` on every failure. Quote it along with your `reference` when you contact support, because together they locate the request without a search.

If `5xx` errors or timeouts persist across retries, check [status.bitnob.com](https://status.bitnob.com) for an ongoing incident before contacting support.

## Rate limits

The API allows 500 requests per minute from each IP address. Every response carries `X-Ratelimit-Limit`, `X-Ratelimit-Remaining`, and `X-Ratelimit-Reset`, so you can see how close you are before you're throttled. A request over the limit returns `429`: back off exponentially and retry after the reset. Design batch jobs to pace themselves rather than racing the limiter; see [Send payouts in bulk](https://www.bitnob.dev/docs/payouts/mass-payouts.md) for the pattern.

## The retry discipline

Money movement makes naive retries dangerous, and one habit removes the danger:

**1. One reference per business action**

Generate a unique `reference` per payout, transfer, trade, or card operation, before the first attempt, and persist it with the intent.

**2. Retry with the same reference**

On timeout or `5xx`, re-submit the identical request. For most endpoints, if the original succeeded you get its result back or a `409`, and nothing executes twice. **Crypto-pair trades are the exception:** the reference isn't checked there, so look the order up before you resend. Either way, a timeout is never a reason to mint a new reference.

**3. Treat 409 as an answer, not an error**

A duplicate-reference conflict means the action already exists. Fetch it by reference and continue as success.

**4. Confirm outcomes from webhooks**

The synchronous response says "accepted", the webhook says "done". Reconcile on a schedule against the relevant list endpoint so a missed delivery cannot strand a record. See [Webhooks and event handling](https://www.bitnob.dev/docs/getting-started/api-best-practices/webhook-best-practices.md).

More on reference design in [Idempotency and reference integrity](https://www.bitnob.dev/docs/getting-started/api-best-practices/idempotency-and-reference-integrity.md).

## Backoff that behaves

* Exponential with jitter: 1s, 2s, 4s, 8s, capped.
* Bounded attempts, then a human: pages that alert your ops channel beat infinite loops.
* No retry storms: when everything fails at once, the cause is systemic; hammering makes it worse.
* Never blind-retry a **failed** (as opposed to timed-out) money movement; read the failure reason first, because some causes, like compliance blocks, do not resolve by retrying.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.