Skip to content

Errors

Errors come back with a non-2xx HTTP status and a JSON body:

{
"error_code": "invalid_argument",
"error_message": "the transaction amount is insufficient as it wont cater for cost: (4.62)",
"status_code": 400
}

Always read error_message — it carries the specific reason, including the provider’s own explanation when a provider refused the payment.

When a request is malformed, invalid_arguments lists every problem at once, so you can fix them together rather than one round trip at a time:

{
"error_code": "invalid_argument",
"error_message": "transaction_channel is required",
"status_code": 400,
"invalid_arguments": [
{
"field": "transaction_channel",
"value": "",
"tag": "required",
"param": "",
"message": "transaction_channel is required"
}
]
}

field is the JSON path of the offending field, for example customer.first_name or payment_config.account_number.

When a provider rejects a payment, its reason is passed through in error_message:

{
"error_code": "invalid_argument",
"error_message": "missing country in recipient",
"status_code": 400
}

These are usually a missing or mismatched field — compare your request against required_fields[provider] from discovery.

Status error_message What to do
400 transaction_channel is required (and other fields) Fix every entry in invalid_arguments
400 provider "…" is not a known provider code Copy the code from available_providers
400 redirect_url is required for a card payment Send payment_config.redirect_url on card payments
400 missing country in recipient Send customer.country
400 full KYC information is required for the transaction Complete the beneficiary’s KYC
400 the transaction amount is insufficient … Raise the amount to cover the cost
401 — Check your API key
404 beneficiary not found The customer_uuid is not on your account
  • A 4xx is a permanent rejection of that request. Fix the input before retrying.
  • A 401 means your API key is missing or wrong.
  • A timeout or 5xx may still have started the payment. Before retrying, look it up with POST /api/global/transaction-status so the payer is never charged twice.
  • A 200 whose body says success: false is not an error when it carries a merchant_reference — the payment started and the result will arrive on your callback.