Get started

Errors

Every error has the same JSON shape, a machine-readable code and a message you can show or log.

Error shape

Failed requests answer with a 4xx or 5xx status and an error object: a stable code to branch on, a human-readable message, and for validation errors the fields that need attention. Some errors add details next to them, like retryAfter or feature.

400 Bad Request
{  "error": {    "code": "validation_error",    "message": "Some fields need your attention",    "fields": {      "email": "Enter a valid email address",      "customAttributes.plan": "Choose one of the options"    }  }}

Status codes and error codes

Successful requests answer 200 OK, or 201 Created when something new was created.

Status Code Meaning
400 validation_error A field is missing or invalid. fields maps each field (dot paths for nested ones) to a message.
400 bad_request The request can’t be processed as sent — a body that isn’t valid JSON, an unknown teammate, a viewer acting on a conversation.
400 unsupported_version The X-Rabbitblaze-Version header names a version that doesn’t exist.
401 unauthenticated No API key, or an unknown or revoked one.
403 forbidden The key lacks the scope the endpoint needs.
403 plan_limit The plan doesn’t include the API, or a limit (such as contacts) is reached. Includes plan and feature or limit.
404 not_found The resource doesn’t exist in this workspace (malformed ids answer 404 too), or the route doesn’t exist.
409 conflict A uniqueness rule — a duplicate email, user id or tag name — or a state conflict, such as converting a ticket twice.
413 payload_too_large The body is over 2 MB.
415 unsupported_media_type A body was sent without Content-Type: application/json.
422 unprocessable Valid input that can’t be applied — for example closing without required attributes, or publishing an article without a body.
422 idempotency_key_reused The Idempotency-Key was already used for a different request.
429 rate_limited Too many requests. Includes retryAfter (seconds) and a Retry-After header.
500 internal Something went wrong on our side. Safe to retry with backoff.

Messages are written for people and may change; branch on code and the status, never on the message.

Handling errors

  • Fix 4xx errors before retrying — sending the same request again gets the same answer.
  • Retry 429 after retryAfter seconds, and 5xx or network errors with exponential backoff. Add an Idempotency-Key to POSTs so a retry never creates a duplicate.
const res = await fetch(url, options)if (!res.ok) {  const { error } = await res.json()  if (res.status === 429) {    // Wait error.retryAfter seconds (also in the Retry-After header), then retry  } else if (error.code === "validation_error") {    console.warn("Fix these fields:", error.fields)  } else {    throw new Error(`${res.status} ${error.code}: ${error.message}`)  }}
res = session.post(url, json=payload)if not res.ok:    error = res.json()["error"]    if res.status_code == 429:        time.sleep(error.get("retryAfter", 1))  # then retry    elif error["code"] == "validation_error":        print("Fix these fields:", error["fields"])    else:        raise RuntimeError(f"{res.status_code} {error['code']}: {error['message']}")