Errors
Every error answers in the same JSON shape, with an HTTP status that tells you what to do next.
The format
{
"code": "customer_not_found",
"message": "No customer with id cus_123",
"hint": "Check the customer id",
"statusCode": 404,
"requestId": "req_0123456789abcdef"
}
code: stable and machine-readable; branch on this, not onmessage.message: a sentence for a human.hint: what to try, when there is something to suggest.statusCode: the HTTP status, repeated.requestId:req_followed by 16 hex characters. Quote it to QBill support so we find your request.
HTTP codes
| Status | code |
When |
|---|---|---|
| 400 | bad_request |
The body failed validation. When several fields are wrong, the messages are joined by ; . Unknown body fields are dropped. |
| 401 | unauthorized |
No key, or a key that is not valid (see Authentication & keys). |
| 403 | publishable_key_forbidden |
A publishable key used outside the few plan reads it is allowed. |
| 403 | api_key_read_only |
A read_only key tried to write. |
| 403 | merchant_suspended |
The account is suspended. |
| 404 | for example customer_not_found |
The object does not exist. |
| 409 | for example sales_link_busy |
The request conflicts with the current state or with another request. Read code: sales_link_busy may succeed on a retry, coupon_code_taken will not. |
| 429 | too_many_requests, rate_limited |
Rate limit reached, see below. |
Other errors carry their own code, such as invoice_not_refundable or key_mode_mismatch.
Rate limits
- 600 requests per minute per IP address: beyond it the answer is 429
too_many_requests. - 300 requests per minute per API key: beyond it the answer is 429
rate_limited. Responses carryX-RateLimit-LimitandX-RateLimit-Remaining; a 429 also carriesRetry-After, the time to wait.
Wait for Retry-After before retrying.
In the SDK
The Node SDK (coming to npm) throws a QBillError for any non-2xx answer, with status, code, hint and requestId:
try {
await qbill.subscriptions.create({ customer, plan });
} catch (e) {
if (e instanceof QBillError) {
console.error(e.status, e.code, e.hint, e.requestId);
}
throw e;
}
The SDK also retries for you, maxRetries times (2 by default, set it in the constructor options). It honours Retry-After on a 429. Calls that are safe to repeat are also retried after a timeout or a server error. See Webhooks for the events your endpoints receive.