Errors and retries
Handle API failures and retry create requests without duplicating orders.
A failed request returns status: false, a human error message, and a stable
code. Match on code. The message can change; the code does not.
{
"status": false,
"error": "Quote lapsed or already used. Get a new one.",
"code": "quote_expired"
}Error codes
| HTTP | Code | When |
|---|---|---|
| 400 | bad_request | Malformed JSON, a missing required field, or an invalid field format. |
| 400 | invalid_amount | Quote amount is outside the supported range. |
| 400 | invalid_currency | Neither side is NGN, or both are. |
| 400 | invalid_asset | Unsupported crypto asset. |
| 400 | invalid_network | Unsupported chain for that asset. |
| 400 | quote_not_found | No such quote for your business. |
| 400 | quote_expired | Quote lapsed or already used. Get a new one. |
| 400 | quote_flow_mismatch | Onramp quote used on offramp, or the reverse. |
| 400 | invalid_destination_address | Not a valid address for the chain. |
| 400 | account_verification_failed | Bank could not confirm the account. |
| 401 | unauthorized | Invalid or missing API key. |
| 404 | order_not_found | No such order for your business. |
| 409 | duplicate_reference | That reference already belongs to an order, in either flow. Use a new one. |
| 429 | rate_limited | Too many requests. Wait 60 seconds before retrying. |
| 503 | service_unavailable | An upstream service was unreachable and nothing was written. Retry. |
| 500 | internal | Unexpected failure. Safe to retry with the same reference. |
Retries are safe
An order create can time out after Pulse has persisted the order. Every create carries
your reference, so a repeat can return the original order instead of creating a
second one.
Store the reference first
Generate a reference that maps to the payment in your system. Store it before you call Pulse, so you can reproduce it after a timeout.
Retry the same request
On a timeout, 503 service_unavailable, or 500 internal, send the exact same body
with the same reference. Do not change a field between attempts.
Save the Pulse order id
After a successful create, store the returned order id with your reference. You
can also find the order with GET /v1/orders?reference=....
The reference must be unique for each real order and across onramp and offramp. Reuse it only to retry the same request.
| Result | What to do |
|---|---|
| Timeout, no response | Retry with the same reference. The order may already exist. |
503 service_unavailable | Retry the same request. Nothing was written. |
500 internal | Retry the same request with the same reference. |
409 duplicate_reference | Read the existing order or use a new reference for a genuinely new order. |
Set finite connection and response timeouts in your HTTP client. Do not use a timeout as evidence that an order failed. Resolve the result with the same-reference retry or an order lookup.
Never match on the message
Two errors can share a message today and differ tomorrow. Read code in code, and
show error to people.