Skip to content

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"}}. Compare code, display message. details only 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.code says why and is a closed, fixed value to decide on; failure.reason is the normalized cause under the code, to explain; failure.message is 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.

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

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

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.