Errors
A request that fails is answered with a status other than 200, and a message of one line. The status says what kind of failure it is, and whether to try again; the message says what exactly.
The response
HTTP/1.1 400 invalid json in items[0].total: missing currency
Content-Type: text/plain
invalid json in items[0].total: missing currency
The message is the body, in UTF-8, ended by a newline, and over HTTP/1.1 it is also the status line's reason phrase. Read it from the body, as HTTP/2 has no reason phrase. Log it whole: it names the field and the fault, and it is what we ask for when you write to support.
An error is never JSON. Check the status before you parse the body.
Status codes
| Status | Meaning | Retry |
|---|---|---|
400 |
The request is wrong: its JSON, a field's value, or the HTTP itself. The message says what. | No. Fix the request. |
401 |
The API key is missing or wrong, or may not make this request. See Authentication. | No. |
402 |
A charge of a subscriber was declined: its message starts with transient or permanent. See Declines. |
transient: later, with a new key. permanent: no. |
404 |
The URL fits no request, or names an object that does not exist. | No. |
405 |
The URL is right, but not the method, such as a GET to create a link. |
No. |
408 |
The request's body did not arrive within 30 seconds of its headers. | Yes, with the same Idempotency-Key. |
409 |
The request conflicts with the object's state. The message says which, and is one of index mismatch, transaction in use, transaction is locked, transaction has acts, and link is paid. |
After you read the object again with seq, with a new Idempotency-Key. |
410 |
The object can't be used as asked until it changes, such as a deleted subscriber, which can't be charged until it is renewed. | No. |
413 |
The body is over 32 KiB, or the request line and headers over 4 KiB. | No. |
414 |
The URL's path has more than 8 segments. | No. |
500 |
We failed, or a party behind us did, such as the acquirer. The message says what, and the request's page whether anything was done. | After you synchronize, with a new Idempotency-Key. |
502, 503, 504 |
We could not be reached, as while we deploy. If it lasts, our status page says whether we are down. | Yes, with the same Idempotency-Key. |
A request's own page lists the errors that only it gives:
| Request | Its errors |
|---|---|
| Create payment link | Errors |
| Delete payment link | Errors |
| Capture, refund, void | Capture, refund, void |
| Create subscriber | Errors |
| Charge subscriber | Declines and other errors |
| Renew subscriber | Errors |
| Delete subscriber | Errors |
| Seq | Errors |
Invalid JSON
A body that is not a JSON object, or a field that is not as its table says, is answered with:
400 invalid json in {where}: {why}
{where} is the path of the field at fault: keys joined by dots, with
array indexes in brackets, as in items[1].total or
billing.address[2]. It is json root object when the fault is in the
object as a whole, and json data when there is no object at all. {why} is one of these, or another that says
as plainly what is wrong:
{why} |
Meaning |
|---|---|
no json present |
The body is empty. |
unexpected end of object |
The body ends inside the object, as when it is cut off. |
invalid amount |
An amount is not a number and a currency. See Amounts. |
missing currency |
An amount has no currency. |
mismatching currencies DKK and EUR |
The items' totals are in more than one currency. |
missing total in item |
An item has no "total". |
number is not a pure integer |
An integer field has a fraction or an exponent. |
illegal control character \x0A in string |
A string contains a raw control character, here a newline, which JSON requires to be escaped. |
invalid utf in string |
A string is not valid UTF-8. |
A request whose body has more after the object than white space fails
with 400 invalid json: garbage at offset {n}, where {n} is the
byte where the trouble starts.
Retrying
A request that got no answer, because the connection broke or timed
out, or got a 408, 502, 503, or 504, may or may not have run.
Send it again, unchanged and with the same Idempotency-Key, so that
we answer with the first request's result if it ran. See
Idempotency.
A request that got an error from us, 4xx or 500, has run, and its
answer is stored under its key. Sending it again with the same key gets
the same error, for 24 hours. So:
- A
4xx, but408, fails the same way until you change the request or the object changes: fix the request, or for a409, read the object again first. A402 transientis the one to send again unchanged, the next day, with a new key. - A
500from an act or a charge may have done its work before it failed, as when the acquirer acted and our database did not. Synchronize, and if the act or charge is not in seq, send it again with a new key.
Between tries, wait, longer each time: from 1 second, doubling, to a minute. The implementation note on retries works through the cases, such as a capture whose answer never came.