> 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.

# Idempotency and retries

Every request that moves money carries a reference you choose. Halo records the reference **before** it calls the bank, so a repeated request can never move money twice.

## References

| Endpoint | Field | Format |
| --- | --- | --- |
| Same-bank transfer | `RetrievalReference` | At most 12 characters |
| Interbank transfer | `TransactionReference` | At most 12 characters |
| Debit account | `retrieval_reference` | At most 12 characters |
| Debit customer account | `idempotency_key` | At most 64 characters |

References are at most 12 characters. Make each one unique within your business. Your references belong to your business: Halo sends the bank a reference of its own derived from yours, so another business using the same reference never affects yours.

## Sending the same reference again

If your business sends a reference it already used, Halo returns the outcome it recorded for that reference. Nothing is sent to the bank again, even if the other fields are different.

For debit-customer-account the same applies to `idempotency_key`.

## A 202 means unknown

A `202` means the bank did not prove that the transfer succeeded or failed. The money may already have moved.

- **Do not retry with a new reference.** That can move the money twice.
- Check the outcome with `POST /api/banking/core-transactions/check-transaction-status`, using the same reference. Once the transfer is 3 minutes old, Halo asks the bank again if the outcome is still unknown. Before that it answers `pending`.
- For debit-customer-account, Halo finishes the request itself once the bank confirms the debit: it sends the credit, or reverses the debit if the bank refuses the credit. Repeating the request with the same `idempotency_key` does the same and returns the latest outcome.
- You can also repeat the original request with the same reference. You get the recorded outcome back.

For debit-customer-account, the `202` message names the reference to check: the debit reference or the credit reference.

## After a refusal

A refused transfer (`400` with `data.status` set to `refused`) moved no money. To try again, use a **new** reference. Sending the old reference only returns the refusal again.

## Opening accounts

- **Create account:** a `202` means the bank is still opening the account. Call again with the same details. No second account is opened.
- Each customer can hold one account with your business. Creating an account for a customer who already has one returns that account.