Errors
Every error is JSON with the same fields. Switch on type, show message to a developer, and keep request_id for support.
{
"_tag": "ParseError",
"type": "ParseError",
"message": "Failed to parse QR code: invalid checksum",
"docs_url": "https://apidocs.borderli.io/docs/errors/ParseError",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
Some errors add a field: details on validation and conflict errors, reason on ExecutionError, scheme on UnsupportedScheme, retryAfter on RateLimitError and ServiceUnavailable. _tag always equals type.
Error types
| type | HTTP | What to do |
|---|---|---|
ParseError | 400 | The QR string could not be decoded. Check the scan. Do not retry as is. |
IdempotencyConflict | 400 | The key was used with a different body. Use a new key. |
AuthError | 401 | Fix the x-api-key header. |
IdempotencyInProgress | 409 | The first request is still running. Send the same request again after a moment. |
ConflictError | 409 | The transaction is not in a state that allows this. details.reason says why. See Pay-ins. |
ValidationError | 422 | A field is missing or wrong. details says which. |
NotFound | 404 | No transaction or delivery with this id exists for your account. Check the id. |
UnsupportedScheme | 422 | Borderli does not support this QR scheme yet. |
AmountRequired | 422 | The QR carries no amount. Send amount and retry. |
InstructionExpired | 422 | The instruction is older than 30 minutes. Resolve the QR again. |
FxQuoteExpired | 422 | The FX quote has expired. Resolve the QR again. |
RateLimitError | 429 | Wait retryAfter seconds and retry. |
RoutingError | 502 | No provider could handle this scheme and country right now. Retry with backoff. |
FxError | 502 | No FX quote right now. Retry, or leave out wallet_currency. |
ExecutionError | 502 | The payment rail rejected the request. reason says why. Retry with the same idempotency key. |
ServiceUnavailable | 503 | Borderli or a dependency is down. Retry after retryAfter seconds with the same idempotency key. |
Retrying
- 400, 401, 422: the request is wrong. Fix it before sending it again.
- 409 IdempotencyInProgress: the same request is still running. Send it again after a short wait, same key, same body.
- 429: wait
retryAfterseconds. - 502, 503: retry with exponential backoff. Keep the same
Idempotency-Keyso a retry never pays twice.
Errors that arrive later
An HTTP error means the request was not accepted. A payment that was accepted and then failed on the rail is a different thing: the transaction ends in status: failed with error.reason, and you learn about it by webhook or by polling. See Pay-outs and Webhooks.