Errors and failures
There are two different things and it pays not to mix them up:
- An API error (
4xx/5xx): the request could not be served. It always arrives in the same envelope:{"error": {"code", "message", "details"}}. Comparecode, displaymessage.detailsonly comes with validation errors, with one item per field. - An operation failure (
status: failed): the request was served, the operation exists, and it did not go through.failure.codesays why and is a closed, fixed value to decide on;failure.reasonis the normalized cause under the code, to explain;failure.messageis a readable text that depends on the cause. They never carry the raw code from the bank or the provider.
The message texts are returned in Spanish; the English below is for
reference. Always branch on code, never on message.
Error codes
Section titled “Error codes”unauthorized: The Authorization header is missing or the API key is not valid.scope_missing: Your key is not allowed to perform this operation.body_invalid: The request body could not be read.field_required: Required fields are missing.field_invalid: Some fields have an invalid value.method_unavailable: The method is not available for that country and currency.bank_unsupported: The given bank does not support this method.amount_out_of_range: The amount is outside the allowed range.currency_unsupported: The currency is not available.country_unsupported: The country is not available.idempotency_key_reused: The idempotency key was already used with another request.idempotency_key_required: The Idempotency-Key header is missing.not_found: There is no operation with that identifier.not_cancellable: The operation can no longer be cancelled.code_not_expected: The operation is not awaiting a code.too_many_codes: Too many codes were requested for this operation.temporarily_unavailable: It could not be processed right now. Try again later.route_not_found: The route does not exist.method_not_allowed: The HTTP method is not allowed on this route.
Failure codes
Section titled “Failure codes”counterparty_rejected: The recipient’s bank rejected the operation.payer_insufficient_funds: The payer does not have enough funds.mandate_required: The payer has not yet authorized the debit with their bank.code_rejected: The code is not valid or has expired. Request a new one.limit_exceeded: The amount exceeds the allowed limit.outside_hours: Outside banking hours.invalid_data: The bank did not accept the operation’s data. Review it and create another.expired: The operation expired.cancelled: The operation was cancelled.temporarily_unavailable: It could not be processed right now. Try again later.rejected: The operation was rejected.
Reasons each code allows (failure.reason): counterparty_rejected → invalid_account, account_closed, account_blocked, beneficiary_mismatch, invalid_phone, invalid_bank, invalid_document, other; payer_insufficient_funds → payer_insufficient_funds; mandate_required → no_mandate, mandate_revoked; code_rejected → code_invalid, code_expired; limit_exceeded → amount_over_limit, daily_limit; outside_hours → outside_hours; invalid_data → invalid_data; temporarily_unavailable → other, bank_offline, timeout; expired → expired; cancelled → cancelled; rejected → other.
Failure reasons
Section titled “Failure reasons”Each code allows a fixed set of reasons (failure.reason). other means
“no further detail”: the message is the code’s.
The normalized reason of a failure, with the code it belongs to:
invalid_account(counterparty_rejected): The recipient’s account or phone does not exist at their bank.account_closed(counterparty_rejected): The recipient’s account is closed.account_blocked(counterparty_rejected): The recipient’s account is blocked.beneficiary_mismatch(counterparty_rejected): The recipient’s details do not match that account.invalid_phone(counterparty_rejected): The recipient’s phone is not valid for mobile payments.invalid_bank(counterparty_rejected): The recipient’s bank does not exist or does not receive this kind of operation.invalid_document(counterparty_rejected): The recipient’s document is not valid.other(counterparty_rejected, temporarily_unavailable, rejected): No further detail: the code’s message applies.payer_insufficient_funds(payer_insufficient_funds): The payer does not have enough funds.code_invalid(code_rejected): The code is not valid.code_expired(code_rejected): The code expired.no_mandate(mandate_required): The payer has not yet authorized the debit with their bank.mandate_revoked(mandate_required): The payer suspended or revoked the debit authorization.amount_over_limit(limit_exceeded): The amount exceeds the limit allowed for this operation.daily_limit(limit_exceeded): The daily limit was exceeded.outside_hours(outside_hours): Outside banking hours.invalid_data(invalid_data): The bank did not accept the operation’s data.bank_offline(temporarily_unavailable): The bank is not available right now.timeout(temporarily_unavailable): The bank did not answer in time.expired(expired): The operation expired.cancelled(cancelled): The operation was cancelled.
Validation details
Section titled “Validation details”| Field | Type | Required | Description |
|---|---|---|---|
code |
CodigoDeDetalle |
yes | |
field |
string |
yes | The field path, dot-separated: payer.document.number, Idempotency-Key. |
A detail’s code: required, invalid, unknown.
The envelope
Section titled “The envelope”| Field | Type | Required | Description |
|---|---|---|---|
code |
CodigoDeError |
yes | |
details |
array<Detalle> |
no | Only for validation errors: one item per field. |
message |
string |
yes | To display, not to compare. |
