Errors

Every error code the Clakta API can return, what causes it, and how to react.

Every failed request returns a non-2xx status and a JSON body shaped like this:

{
  "error": {
    "code": "not_found",
    "message": "Order \"1042\" not found.",
    "doc_url": "https://www.clakta.com/docs/api-reference/errors#not-found",
    "type": "order_not_found"
  }
}
  • code — a stable, machine-readable identifier. Branch on this, never on message.
  • message — a human-readable explanation, intended for your logs. The wording can change at any time.
  • doc_url — a link to the matching section on this page.
  • type — a stable identifier for the specific failure, present when one applies. It is more precise than code (several type values map to one code) and is what our own UI keys localized messages off.

Error codes

bad_request

400 — The request is malformed and the API could not act on it. Common causes are a missing Bearer prefix on the Authorization header, an unparseable JSON body, or a missing required identifier such as orderId. Fix the request; retrying it unchanged will fail again.

unauthorized

401 — Authentication failed. The Authorization header is missing, or the API key is malformed or revoked. Check that the header reads Bearer <key> and that the key is still active under Settings → API keys.

forbidden

403 — The API key is valid but not allowed to perform this operation, because it lacks the required scope or the acting user lacks the required role. Grant the scope listed on the endpoint's page and retry.

exceeded_limit

403 — The action would exceed a limit on your team's plan, such as the monthly order allowance. The message states which limit was hit. Upgrade the plan or wait for the next billing period.

not_found

404 — The requested resource does not exist, or your API key cannot reach it. The API deliberately answers 404 rather than 403 for resources outside your access, so it never confirms that something exists. Verify the identifier and the project the key is scoped to.

conflict

409 — The request conflicts with the current state of the resource. Creating an order with an orderId that already exists in the project is the usual cause. Treat it as "already recorded" rather than retrying blindly.

invite_pending

409 — An invitation for this email address is already outstanding. Resend or revoke the existing invite instead of creating a second one.

invite_expired

410 — The invitation has expired and can no longer be accepted. Issue a new invite.

unprocessable_entity

422 — The request was well-formed but failed validation. The message names the offending field and what was wrong with it, for example an email that is not RFC 5322, a phone number outside E.164, or a negative price. Correct the payload and retry.

rate_limit_exceeded

429 — You have exceeded your plan's request budget for the current minute. This is the one error worth retrying automatically: wait for the interval in Retry-After, then back off exponentially. X-RateLimit-Reset tells you when the window clears.

internal_server_error

500 — Something failed on our side. The response deliberately does not expose the cause. These are reported to our monitoring automatically; retry with backoff, and contact support@clakta.com if it persists.

meta_api_error

500 — A call to the Meta Marketing API failed while serving your request. Usually transient, or the connected ad account needs to be re-authorized under Ads manager.

500 — A call to the Google Ads API failed while serving your request. Usually transient, or the connected ad account needs to be re-authorized under Ads manager.

tiktok_api_error

500 — A call to the TikTok Marketing API failed while serving your request. Usually transient, or the connected ad account needs to be re-authorized under Ads manager.

Handling errors well

  • Branch on code, not message. Messages are copy and will change.
  • Retry only what is retryable. 429 and 5xx deserve exponential backoff; 4xx codes describe a broken request and will fail identically on retry.
  • Make writes idempotent. Send a stable orderId so a retry after a network timeout surfaces as conflict instead of creating a duplicate order.
  • Log doc_url and type. They pin down which specific failure occurred faster than the message does.