API docs

Errors and retries

The error envelope, HTTP status codes, and which requests are safe to retry.

Every error response uses the same envelope. type is a stable, machine-readable identifier you can branch on; message is human-readable and may change between releases. Some error types carry extra fields alongside these two.

{
  "error": {
    "type": "authentication_error",
    "message": "No API key provided. Pass Authorization: Bearer <key>."
  }
}

Status codes

StatusMeaning
200 OKSuccess. The body contains the resource or list you asked for.
201 CreatedA new resource was created. The body contains it, including its ID.
202 AcceptedThe work was accepted and runs asynchronously. The body carries an operation ID; poll Poll an operation or register a webhook rather than holding the connection open.
204 No ContentSuccess with an empty body. Deletes and revocations return this.
401 UnauthorizedMissing, malformed, revoked or unknown key. See below.
403 ForbiddenValid key, wrong scope or wrong project. The error carries required_scope.
429 Too Many RequestsYou hit the per-key rate limit. Back off on the Retry-After header. See Rate limits.
Other 4xxThe request is at fault. Fix it before retrying; the same input will fail the same way.
5xxSomething failed on our side. Retry with backoff, following the rules below.

Authentication and permission errors

A 401 means the key itself is the problem: missing, malformed, revoked or unknown.

{
  "error": {
    "type": "authentication_error",
    "message": "No API key provided. Pass Authorization: Bearer <key>."
  }
}

A 403 means the key is valid but lacks the scope the route requires, or is bound to a different project. The response names the missing scope in required_scope.

{
  "error": {
    "type": "permission_error",
    "required_scope": "train",
    "message": "Key key_2Fd has scopes [read, infer]."
  }
}

When a deployment returns 403 and nobody is sure which key it is actually using, call Verify the current key. It returns the key ID, its scopes and its project binding without side effects.

Retry rules

Every GET and DELETE route is safe to retry. If a read times out or returns a 5xx, retry it with exponential backoff. On 429, wait for the Retry-After value instead of a fixed interval; see Rate limits.

POST routes need more care, because a timeout does not tell you whether the server acted before the connection dropped. That is what idempotency keys are for.

Idempotency

Five POST routes allocate real resource, GPUs, storage or a queue slot, and are therefore not naturally safe to retry:

Retrying one of these after a timeout can create a duplicate: a second file, a second queued job, a second export. If your client retries automatically, send an Idempotency-Key header on these routes. Use a unique value per logical request, generated when you first build the request and reused on every retry of it. A UUID works well. If the original attempt did get through, the retry returns the existing resource instead of allocating another one.

curl https://api.nucleus-ai.io/v1/files \
  -H "Authorization: Bearer $NUCLEUS_API_KEY" \
  -H "Idempotency-Key: 8f14e45f-ceea-4f7a-9a5d-3c4b2f1e0d9b" \
  -F purpose=fine-tune \
  -F [email protected]

Async routes that return 202 Accepted are a separate case: the request itself completed, so there is nothing to retry. Poll Poll an operation with the operation ID from the response until the work finishes.

Errors and retries | Nucleus AI API