Errors
How the ibakepro API reports errors, and how to handle them.
Almost every error uses one envelope. The exceptions are listed below.
Error response format
Error response
{
"error": {
"type": "validation_error",
"code": "invalid_value",
"message": "first_name is required",
"field": "first_name"
}
}
- Name
error.type- Type
- string
- Description
A broad category for the error, such as
validation_errororauthentication_error. Determines the HTTP status.
- Name
error.code- Type
- string
- Description
A specific machine-readable code. Branch on this, not on the message.
- Name
error.message- Type
- string
- Description
A human-readable description. Wording is not stable; do not parse it.
- Name
error.field- Type
- string
- Description
The request field that caused the error. Present on most validation errors, absent when the failure is not attributable to one field.
- Name
error.requiredScope- Type
- string
- Description
The scope your key is missing. Present only on
403 insufficient_scope.
Responses that do not use the envelope
Three responses are flat objects with a string error. Check the HTTP status before reaching for error.type.
429 Too Many Requests
{
"error": "Too many requests",
"message": "Please slow down and try again later",
"retryAfter": 60
}
403 Plan required
{
"error": "plan_required",
"feature": "rest-api",
"label": "Public REST API",
"required": "business",
"current": "starter"
}
403 Account inactive
{
"error": "account_inactive",
"status": "suspended"
}
plan_required means the account is not on the Business plan. account_inactive means the account status is neither active nor grace. Both apply to every /api/v2 endpoint and neither is retryable.
HTTP Status Codes
- Name
200 OK- Description
The request succeeded. Every
GETreturns200.
- Name
201 Created- Description
A new resource was created.
- Name
204 No Content- Description
Returned to a CORS
OPTIONSpreflight on a publishable-key endpoint.
- Name
400 Bad Request- Description
The request was malformed, or a query parameter or body field was invalid.
- Name
401 Unauthorized- Description
The API key is missing, malformed, unknown, revoked, expired, or minted for a different region than the host you called.
- Name
403 Forbidden- Description
The key lacks the required scope, a publishable key was used on a secret-only endpoint, the account is not on the Business plan, the account is inactive, or a plan order limit was reached.
- Name
404 Not Found- Description
The requested resource does not exist under your account.
- Name
409 Conflict- Description
A conflicting resource already exists, or a request with the same
Idempotency-Keyis still in flight.
- Name
410 Gone- Description
The request was sent to
/api/v1, which has been removed. Use/api/v2.
- Name
422 Unprocessable Entity- Description
An
Idempotency-Keywas reused with a different body or on a different route.
- Name
429 Too Many Requests- Description
A rate limit was exceeded. See Rate limiting.
- Name
500 Internal Server Error- Description
Something went wrong on our end.
- Name
503 Service Unavailable- Description
A dependency is temporarily unavailable. Retryable.
Error types
Authentication errors
- Name
authentication_error- Description
401, codeinvalid_api_key. Covers every rejection reason: noAuthorizationheader, a key that does not match the key format, a key for the wrong region, an unknown or revoked key, an expired key, and a key string whose declared type does not match the stored key. The message is deliberately generic and never says which of these it was.
401 Unauthorized
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Invalid API key"
}
}
Permission errors
- Name
permission_error- Description
403, codeinsufficient_scope. Your key does not hold the scope the endpoint requires. The response carriesrequiredScopenaming it.
- Name
invalid_request_error- Description
403, codepublishable_key_not_allowed. A publishable key was used on a secret-only endpoint. See which endpoints accept a publishable key.
403 Forbidden
{
"error": {
"type": "permission_error",
"code": "insufficient_scope",
"message": "This action requires the 'orders:write' scope",
"requiredScope": "orders:write"
}
}
Validation errors
All return 400 with type: "validation_error". The code identifies the
problem.
- Name
invalid_value- Description
The default for a missing or invalid field.
fieldnames it.
- Name
invalid_json- Description
The request body was not parseable JSON.
- Name
invalid_cursor- Description
The
cursorquery parameter did not decode, or decoded to a record that no longer exists. Restart pagination from the first page.
- Name
conflicting_filters- Description
Two query filters cannot be combined. Returned by
GET /expenseswhenupdated_afterororder_by=updated_atis combined withdate_fromordate_to, and when more than one equality filter is supplied.
- Name
unsupported_filter_sort_combination- Description
The requested
sortcannot be served with the requested filter. Returned byGET /orderswhencreated_afterorcreated_beforeis combined with anysortother than the defaultcreatedAt.
- Name
customer_not_found- Description
POST /orderswas given acustomer.idthat does not exist under your account.fieldiscustomer.id.
- Name
invalid_idempotency_key- Description
The
Idempotency-Keyheader was empty, over 255 characters, or contained characters outside letters, digits,_,-,:and..
Domain validation failures on create endpoints pass through their own
code, so treat this list as the codes you can rely on, not as exhaustive.
400 Bad Request
{
"error": {
"type": "validation_error",
"code": "invalid_cursor",
"message": "Invalid cursor",
"field": "cursor"
}
}
Resource errors
- Name
not_found- Description
404, codenot_found. The resource does not exist under your account.
- Name
conflict- Description
409, codeconflict. A conflicting resource already exists, for example a customer with the same email onPOST /customers.
404 Not Found
{
"error": {
"type": "not_found",
"code": "not_found",
"message": "Order 'HR7Pcz4Arg6kvZKseSil' not found"
}
}
Idempotency errors
Returned on a misused Idempotency-Key. The type is idempotency_error;
the code distinguishes the case. See
Idempotency.
- Name
idempotency_key_reused- Description
422. The key was previously used with a different body, or on a different endpoint. Use a fresh key for a different operation.
- Name
request_in_flight- Description
409. A request with the same key is still being processed. Retry shortly. A request that has already failed releases its key immediately, so this only appears while an attempt is genuinely running.
422 Unprocessable Entity
{
"error": {
"type": "idempotency_error",
"code": "idempotency_key_reused",
"message": "This Idempotency-Key was previously used with a different request. Use a new key for a different operation."
}
}
Plan limit
- Name
limit_reached- Description
403, withtype: "rate_limit_error".POST /orderswas rejected because the account has reached its plan order limit. The body carrieslimit,currentandmax. This is not a rate limit and retrying will not clear it until the limit window rolls over or the account is upgraded.
403 Forbidden
{
"error": {
"type": "rate_limit_error",
"code": "limit_reached",
"message": "Order limit reached",
"limit": "orders",
"current": 500,
"max": 500
}
}
Server and availability errors
- Name
api_error- Description
500, codeinternal_error. An unexpected failure on our side. A failed request releases itsIdempotency-Keyimmediately, so the same key can be retried.
- Name
service_unavailable- Description
503, codesearch_not_configured.POST /products/search-tokencould not mint a token because search is not currently available for the account. Retryable.
- Name
deprecated- Description
410, codeapi_version_deprecated. The request went to/api/v1. Move to/api/v2.
500 Internal Server Error
{
"error": {
"type": "api_error",
"code": "internal_error",
"message": "An unexpected error occurred"
}
}
Rate limiting
Exceeding a limit returns 429. This body does not use the error
object envelope: error is a plain string, alongside message and
retryAfter in seconds.
Prefer the Retry-After header over the body field. The X-RateLimit-*
headers on the response tell you which bucket you hit. See
Rate limiting.
429 Too Many Requests
{
"error": "Too many requests",
"message": "Please slow down and try again later",
"retryAfter": 60
}
Handling errors
JavaScript error handling
async function createOrder(orderData) {
const response = await fetch('https://au.api.ibakepro.com/api/v2/orders', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.IBAKEPRO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(orderData),
})
if (response.ok) {
return response.json()
}
const result = await response.json()
// A few responses use a flat shape: { error: string, ... }
if (typeof result.error === 'string') {
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') ?? result.retryAfter
throw new Error(`Rate limited, retry after ${retryAfter}s`)
}
// plan_required or account_inactive
throw new Error(result.error)
}
// Everything else uses { error: { type, code, message, field } }
switch (result.error.code) {
case 'insufficient_scope':
throw new Error(`Key is missing scope ${result.error.requiredScope}`)
case 'request_in_flight':
throw new Error('Retry shortly with the same Idempotency-Key')
case 'idempotency_key_reused':
throw new Error('Use a fresh Idempotency-Key for a different request')
case 'customer_not_found':
throw new Error(result.error.message)
default:
throw new Error(`${result.error.type}: ${result.error.message}`)
}
}