Responses & codes
The response envelope and the API200 to API500 code table, with the API409 reasons.
# Responses & codes
Every reply, success or failure, uses the same envelope, and the HTTP status matches the code. `meta` is last and is always present.
~~~json
{ "status": 1, "code": "API200", "message": "success", "data": { }, "go": null, "meta": { "requestid": "0123456789abcdef", "notices": [] } }
~~~
| Field | Type | Meaning |
| --- | --- | --- |
| `status` | integer | `1` for success, `0` for any error. |
| `code` | string | The `API*` code below. Branch on this, not on `message`. |
| `message` | string | A human-readable message. It can change, so do not parse it. |
| `data` | object or null | The payload on success. On some errors it carries detail, such as `param`, `reason` or `detail`. |
| `go` | null | Reserved. Always `null`. |
| `meta` | object | Always present, after `go`. `meta.requestid` is the id of this request (16 hex characters, the same value as the `X-Request-Id` header). `meta.notices` is an array of advisory notices, `[]` when there are none; each notice is `{ "code", "message", "docs"? }`. |
## Codes
| Code | HTTP | Meaning |
| --- | --- | --- |
| `API200` | 200 | OK. |
| `API400` | 400 | A parameter is missing or malformed (unknown chain, bad hash, address or height). `data.param` names it. |
| `API403` | 403 | Refused by policy: hosted signing without the risk acknowledgement, or a key that does not match the inputs. `data.reason` says which. |
| `API404` | 404 | The block, transaction, address, token or webhook was not found. |
| `API405` | 405 | Method not allowed. |
| `API409` | 409 | Not available yet on this chain, or a precondition is missing. `data.reason` says why: see below. |
| `API422` | 422 | The request is well formed but the node or our checks reject it. `data.reason` gives why, and `node_rejected` also carries `data.detail`. |
| `API429` | 429 | Rate limited. A `Retry-After` header says how long to wait. See [Rate limits](https://docs.rarebl.com/rate-limits). |
| `API502` | 502 | The node is unavailable, still syncing or timed out. Retry later. |
| `API500` | 500 | Internal error. |
Every reply also carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-Request-Id`.
## Request ID
Every reply has a request id, in `meta.requestid` and in the `X-Request-Id` header (the same value). Quote it when you contact support, and log it with every error. The `meta` object is on Open API replies only; replies from the explorer backend (`explorer.rarebl.com/src/*`) have no `meta`, and webhook deliveries and WebSocket messages are unchanged.
## `API409` reasons
| `data.reason` | Meaning |
| --- | --- |
| `history_unavailable` | Address history needs the history index, which is not built for this chain yet. |
| `tx_index_pending` | ETH only: the node is still indexing old transactions. Try again later. |
| `before_history_start` | TRON only: the height is below the first block we hold (`historyFrom`, 2026-09-08). |
| `no_mempool_view` | The node has no pending-transaction view for this chain. |
| `not_watched` | BTC, LTC or BCH: the address is not watched and active yet. Start one with [Watch addresses](https://docs.rarebl.com/api/address/watch). |
## `API422` reasons
The request is valid, but it cannot be carried out.
| `data.reason` | Meaning |
| --- | --- |
| `insufficient_funds` | The inputs (or the balance) cannot cover the amount plus the fee. |
| `dust_output` | An output is below the dust limit. |
| `fee_too_low`, `fee_too_high` | The fee is below what the network relays, or above the safety limit. |
| `inputs_spent`, `inputs_unknown` | An input is already spent, or the node does not know it. |
| `bad_signature` | A signature does not verify against its digest and key. |
| `nonce_too_low` | ETH: the nonce is below the pending nonce. |
| `chain_id_mismatch` | ETH: the chain id is not 1. |
| `tx_expired` | TRON: the transaction has expired. |
| `tx_too_large` | Over the size cap: 100 kB (UTXO), 128 kB (ETH), 64 kB (TRON). |
| `node_rejected` | The node refused the transaction. `data.detail` carries its message, for example `min relay fee not met`. |
## `API403` and `API400` reasons for hosted signing
| Code and reason | Meaning |
| --- | --- |
| `API403` `risk_not_acknowledged` | The header `X-Rarebl-Accept-Risk: hosted-signing` is missing. |
| `API403` `key_mismatch` | A key does not match the address of an input it signs. |
| `API400` `plaintext_key_in_query` | A key-like value was in the query string; the request was dropped unprocessed. |
See [Hosted signing](https://docs.rarebl.com/guides/hosted-signing).
## Example: `API400`
~~~json
{ "status": 0, "code": "API400", "message": "Unknown or missing chain.", "data": { "param": "chain" }, "go": null, "meta": { "requestid": "0123456789abcdef", "notices": [] } }
~~~
## Example: `API422`
~~~json
{ "status": 0, "code": "API422", "message": "The node rejected the transaction.", "data": { "reason": "node_rejected", "detail": "min relay fee not met" }, "go": null, "meta": { "requestid": "0123456789abcdef", "notices": [] } }
~~~
## Handling errors
- Retry `API429` and `API502` with back-off. Honour `Retry-After` on `API429`.
- Do not retry `API400`: fix the request. `data.param` tells you which parameter.
- `API409` is not a failure of your request: that data or precondition is not there yet. Check `features` in [Chains](https://docs.rarebl.com/api/stats/chains), and start a watch on `not_watched`.
- `API422` means change the transaction (fund it, raise the fee, rebuild), not retry it unchanged.
- Match on `code` and `data.reason`, never on `message`.
## Conventions
Amounts are exact decimal strings in whole units, times are ISO 8601 UTC, unknown values are `null`, ETH hashes and addresses carry `0x`, TRON addresses are base58, and BCH addresses are CashAddr without the prefix. See [Chains & units](https://docs.rarebl.com/chains-and-units).