> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.haloinvest.ng/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.haloinvest.ng/_mcp/server.

# Errors and response envelope

## The envelope

Every response, except a `401` from authentication, uses the same envelope:

```json
{
  "status": true,
  "message": "Transfer successful",
  "data": { "reference": "HT0000000001", "status": "success" },
  "status_code": 200
}
```

| Field | Meaning |
| --- | --- |
| `status` | `true` on success, `false` otherwise. A `202` also has `false`, because the outcome is not known yet. |
| `message` | A short message. On a `422` validation failure it is an object of field names to error lists. |
| `data` | The result. Most errors leave it out. Money and account-opening errors include it with the reference and a `status`. |
| `status_code` | The same value as the HTTP status code. |

A validation failure looks like this:

```json
{
  "status": false,
  "message": { "Amount": ["The amount field is required."] },
  "status_code": 422
}
```

The statement, BVN and NIN endpoints are the exception: they answer a validation failure with `400` and the first error as a plain `message`.

## Status codes

| Status | Meaning | What to do |
| --- | --- | --- |
| `200` | Success. | Use `data`. |
| `202` | The bank has not confirmed the outcome yet. Money may already have moved, or an account may already be opening. | Do not retry with a new reference. Check the status, or repeat the same request with the same reference or details. See [Idempotency and retries](/idempotency-and-retries). |
| `400` | The request was refused, usually by the bank or because a record was not found for your business. | Read `message`. For a refused transfer, use a new reference to try again. |
| `401` | The API key is missing or not recognised, or your business is switched off. | Check your key. See [Authentication](/authentication). |
| `403` | The action is not allowed for this account or customer. For example, the account is held by Halo for investments, or the customer also banks with Halo outside your business. | Do not retry. Contact Halo support if you need the change. |
| `404` | The customer, account or reference was not found for your business. | Check the identifier. You can only see records your business created. |
| `422` | Validation failed, or a business rule refused the request, such as a transfer limit or an account that still holds money. | Fix the request before sending it again. |
| `429` | Too many requests. The message is `Too Many Attempts.` | Wait and try again. See [Rate limits](/rate-limits). |
| `500` | Something failed at Halo or a provider. | For money requests, check the status before trying again. |
| `502` | The bank did not answer clearly. | Check the account or the status before trying again. |
| `503` | Halo could not confirm something with the bank, for example an account balance before closing it. | Try again later. |

A database error at Halo answers `500` with the normal envelope and a message such as `Something went wrong. Quote reference 1A2B3C4D to support.` Quote that reference when you contact support.