Errors
The API answers with a conventional HTTP status: 2xx worked, 4xx failed for what the request carried (a parameter is missing, the key may not do this), 5xx is our problem and rare. A 4xx or 5xx body is always one error object, so your code handles one shape.
The error object
typeenum- The kind of error: one of the types below.
codestring, optional- A short string to handle in your code, from the list of codes below. Left out when the error has none, such as a fault of ours.
messagestring- What went wrong, in English, for the developer. Do not show it to your customer.
paramstring, optional- The parameter the error is about, when there is one.
doc_urlstring, optional- This page, at the code's entry. Sent with every code.
HTTP status codes
200 | OK | It worked. |
201 | Created | A new object was created (POST /payments); a retry with the same idempotency key answers it again. |
400 | Bad Request | The request is not acceptable, often for a missing parameter. |
401 | Unauthorized | No valid API key. |
402 | Request Failed | The parameters were valid but the request failed. |
403 | Forbidden | The key may not do this, or not from this address. |
404 | Not Found | No such object, or no such endpoint. |
409 | Conflict | It conflicts with another request, often one with the same idempotency key. |
424 | External Dependency Failed | A bank or provider behind us failed. |
429 | Too Many Requests | Slow down and retry with backoff. |
500, 502, 503, 504 | Server errors | Our problem; rare. Safe to retry with the same idempotency key. |
Error types
invalid_request_error- The request is wrong: a parameter, the key, the address it came from.
idempotency_error- An Idempotency-Key was reused with another request: another body, or another endpoint. Answered with status 400 and no code.
rate_limit_error- Too many requests too quickly, in test mode. Answered with status 429 and a Retry-After header: wait that many seconds and send it again.
api_error- Anything else: a problem on our side. Rare.
The shape is Stripe's, so code written for Stripe's errors reads ours. There is no card_error: we take no cards.
Error codes
Built from the API's own list: a code is here as soon as the API can return it. New codes can be added at any time, so handle a code you do not know by its type and status.
| Code | Status | What happened and what to do |
|---|---|---|
account_inactive | 403 | The API key is right, but its account, or the merchant it belongs to, is suspended: it takes no requests until it is active again. Contact your account manager to find out why. |
amount_not_whole | 400 | The amount has a fraction of a unit its payment method does not take: a transfer in Argentina is in whole pesos. Send a multiple of 100 centavos, which the message names. |
amount_too_large | 400 | The amount is above the most a payment of its method may be: the market's maximum, or your account's own, which the message names with the currency. Ask for at most that amount, or split the payment. |
amount_too_small | 400 | The amount is below the least a payment of its method may be: the market's minimum, or your account's own, which the message names with the currency. Ask for at least that amount. For a settlement: the amount, less its fee, comes to no USDT past the fixed fee; request more. |
api_key_expired | 401 | The API key was revoked, or a rotation replaced it and its expiry has passed: it no longer works, and the message shows its prefix ("Expired API key provided: sk_live_in_4fQx9aZ2…"). Use the account's current key, which the merchant portal lists under Settings › Developers › API keys. |
api_key_permission | 403 | The API key is a CLI key (rk_test_…), made by novaro login: it may read events, and create, read and confirm payments, in test mode. Use a secret key (sk_) for this request. |
balance_insufficient | 400 | The amount is more than your available balance, and nothing was created: the message names what is available. Request at most that, or read GET /balance first. |
checkout_unavailable | 503 | Your account has no hosted payment page right now, so a payment with checkout cannot be made, and nothing was created. We are alerted and are putting it right; a payment without checkout, shown by your own server, works meanwhile. |
confirmation_not_supported | 400 | The payment's method takes no confirmation: its confirmation_fields are empty. Do not send one for payments of this method; they are matched without it. |
idempotency_key_in_use | 409 | Another request with the same Idempotency-Key is still running. Retry after a moment: once it has finished, the retry gets its answer. |
invalid_api_version | 400 | The PSP-Version header names no version of the API. Send one of the versions the Changelog lists, exactly as written there, or leave the header out to use your account's default version. |
ip_not_allowed | 403 | The request came from an IP address that is not on the IP allowlist of the account. A live API key of an account with an allowlist works only from the addresses on it, and only through the API's public host. Add the address to the allowlist, or call the API from an address that is on it. |
livemode_only | 409 | Settlements are live mode only: a test key cannot request one. Use your live secret key (sk_live_…). |
market_not_enabled | 403 | The API key is right, but the merchant is not enabled on the account's market for the key's mode: a live key needs the merchant active on the market, a test key in test or active. Contact your account manager to enable the market. |
merchant_reference_already_used | 409 | Your account already has a payment with this merchant_reference. Each payment needs its own reference; to retry a request whose answer you did not get, send it again with the same Idempotency-Key instead. |
method_not_enabled | 400 | The payment method is not available in this currency on the market, or not enabled for your account: param names payment_method_data.type. Contact your account manager to enable it. |
parameter_invalid | 400 | A parameter's value is of the wrong type or format, or the body is not one JSON object: param names the parameter, and message what is wrong. Correct the value. |
parameter_missing | 400 | A parameter the request needs is absent or blank: param names it. Send it. |
parameter_unknown | 400 | The request has a parameter the endpoint does not take, or one your market's payments do not: param names it. Remove it; the API reference lists the parameters of each endpoint, and your account manager which of them your market takes. |
payment_final | 409 | The payment has already succeeded or failed, so a confirmation changes nothing, and none was recorded. Retrieve the payment for its status. |
payout_address_missing | 409 | You have no default payout address to send the settlement to. Add one in the merchant portal (Settings › Payout addresses): it becomes active 24 hours later. |
payout_address_not_active | 400 | The payout address is not active: it is still in its first 24 hours, or it was blocked or deleted. Name an active address (GET /payout_addresses lists them), or leave payout_address out to use your default. |
payout_not_cancelable | 409 | The payout is no longer pending: it is being sent, or it ended, so it cannot be canceled. Read it with GET /payouts/{id}: one being sent ends paid or failed, and a failed one's amount and fee are back in your available balance. |
payout_terms_missing | 409 | Your agreement sets no payout fee on this market yet, so a payout cannot be made, and nothing was created. Contact your account manager to set it up. |
payouts_not_available | 409 | Payouts are not open in live mode yet, and nothing was created. Make test payouts with your test key (sk_test_…) meanwhile; live payouts open with an announcement in the Changelog. |
rate_limit | 429 | Too many requests too quickly in test mode: the message names the limit you went over, by default 25 requests a second per test key or 100 per account over all its test keys. Nothing ran. Send the request again after the seconds the Retry-After header gives, and spread your requests out; live mode has no such limit. |
reference_already_used | 409 | The reference already confirms another payment: a UTR is one transaction, and one transaction pays one payment. param names the field. Check the value with the payer; nothing was recorded. |
resource_missing | 404 | No object with the id in the request is yours to read: it does not exist, it belongs to another account, or it was made with a key of the other mode. Check the id, and that you use a key of the account and the mode the object was made with. |
return_url_not_allowed | 400 | checkout.return_url is not an https URL on one of your account's return hosts. Add its host to the account's return hosts in the merchant portal (Settings › Developers › Checkout › Hosts), or send a URL on a host that is there. |
settlement_request_pending | 409 | A settlement you requested is still pending on the market, and you may have one at a time: the message names it. Wait until our team pays or cancels it (settlement.paid or settlement.canceled), then request again. |
settlement_terms_missing | 409 | Your agreement sets no settlement fee or exchange rate on this market yet, so a settlement cannot be priced, and nothing was created. Contact your account manager to set them up. |
tax_id_invalid | 400 | The customer's tax_id is not a valid one of its type: a CUIT or CUIL is 11 digits whose last is its check digit, a DNI 7 or 8 digits. The message says what is wrong. Ask the customer for the number again; a CUIT or CUIL whose only fault is a person's prefix (20, 23, 24 or 27) is taken as its DNI, not refused. |
temporarily_unavailable | 503 | We cannot take the payment or the settlement right now, and nothing was created. Retry after a moment, with the same Idempotency-Key; if a settlement keeps getting it, contact your account manager. |
traffic_type_disabled | 400 | The payment's traffic_type (ftd when it is not sent) is turned off on your account, so the payment was not made. Contact support to turn it on; payments of the other type, if it is on, go through as usual. |