THINKHX

Error codes

A failed call uses the same envelope as a successful one: read the HTTP status code, then read response for a message describing what went wrong. Messages are stable English strings, so you can match on them, but prefer the status code for branching.

json
{
  "code": 403,
  "title": "Forbidden",
  "response": "The API key is missing the required scope: team:write"
}

Status codes

CodeTitleWhat it means
200OKThe call succeeded. Reads, updates and deletes all use this.
201CreatedA record was created. Used by the key, team and feedback endpoints.
301Moved PermanentlyYou called http://. Repeat the call on https://.
400Bad RequestThe body was not a JSON object, or a required field was absent.
401UnauthorizedNo usable key was presented, or the key has expired.
402Payment RequiredThe plan does not cover the action, or its allowance is used up.
403ForbiddenThe key is unknown, disabled, or short of the required scope.
404Not FoundNo such path, or no such record in this project.
405Method Not AllowedThe method is not accepted on that path.
413Payload Too LargeThe request body exceeded 200,000 bytes.
422Unprocessable entityThe body parsed but a value was rejected, or the method and path do not combine.
501Not ImplementedThe endpoint is reserved and does not act yet.
503Service UnavailableA backing service was briefly unreachable. Retry.
500Internal Server ErrorAn unexpected fault. Retry, then report it.

Authentication failures

These are raised before any endpoint code runs, so they can answer any path.

CodeMessageCause
401No valid API key provided.The Authorization header is absent, or does not begin with Bearer .
401The API key has expired.The key had an expiry and it has passed. A key with no expiry never raises this.
403The API key doesn't have permissions to perform the request.The key is unknown, or it is disabled, or its consumer or project is no longer active.

Note — An unknown key and a disabled key give the same 403 with the same message, on purpose: the API never confirms whether a key exists.

Scope failures

An endpoint checks its scope before doing any work.

CodeMessageCause
403The API key is missing the required scope: <scope>The key holds neither *, nor <resource>:*, nor the exact scope named.
403Cannot create a key with wider scope than the calling key.You asked for * on a new key while your own key is narrower.

The message names the scope that was wanted, so the fix is either to widen the key or to stop calling that endpoint. See API keys.

Request failures

CodeMessageCause
400Invalid JSON.The body is not parseable JSON, or it is a JSON value that is not an object.
413Request body too large.The body exceeded 200,000 bytes.
422The parameters were valid but the request failed.The method and path do not combine into a supported endpoint, or a value was rejected without a more specific message.

Not found

Two different 404s exist, and they are easy to tell apart.

An unknown path is refused by the gateway, before any endpoint is reached. This one repeats code as a string rather than a number:

json
{
  "code": "404",
  "title": "Not Found",
  "response": "The requested resource was not found."
}

A path that exists but names a record your project cannot see is refused by the endpoint, with a message naming the record type — App not found., Event not found., File not found., API key not found., Team member not found., Feedback not found., Reasoning not found. or Public app not found.

Important — A record that belongs to another project returns the same 404 as one that never existed. This is what makes a key safe to hand to a third party: it cannot be used to discover what other projects hold.

Plan and quota failures

The run and app endpoints check the project's plan before acting.

CodeTitleMessage
402Quota exceededYour reasoning quota is exhausted. Please wait until it resets or upgrade your plan.
402Payment RequiredThe current billing plan does not allow custom app creation for this project.
402Payment RequiredThe current billing plan app limit has been reached for this project.

Call GET /v1/run-usage/summary to read the remaining allowance before you launch a run, and to find when the cycle resets.

Need help? Contact Support.