# API errors

Every error has this shape, with the HTTP status of its code:

```
{ "error": { "code": "invalid_param", "message": "max_tris must be a whole number.",
  "fix": "Use max_tris=5000", "docs": "https://3dvalley.com/docs/api/errors#invalid_param" } }
```

The message says what went wrong; `fix`, when there is one, says what to send instead. Over MCP the same error is a tool result with `isError: true` and the line `code: message fix`.

## unauthorized

`401`. No key where one is needed, or a key that is not valid or was revoked. Make one at /account/api and send it as `Authorization: Bearer 3dv_live_...`. Over MCP this starts the client's sign-in.

## insufficient_scope

`403`. The key lacks the scope: `tools` for anything that runs a tool. Make a key with it, or approve it when your MCP client asks (`insufficient_scope`).

## not_found

`404`. No such asset, job or upload on this account. An asset that is not mirrored yet answers this from its download, with `source_url`.

## invalid_param

`400`. A parameter or field that is unknown, missing or out of range. The message names it and `fix` lists what is valid. Also: a job that costs more than `max_credits`, or a missing `Idempotency-Key`.

## insufficient_credits

`402`. The balance does not cover the job. Comes with `balance`, `price` and `top_up` (/pricing), and `fix` names a model the balance does cover. Nothing was charged.

## spend_cap_reached

`429`, `limit: "spend_cap"`. This key has spent its daily cap. Raise the cap at /account/api or wait for midnight UTC (`Retry-After` says how long).

## rate_limited

`429`. Too many requests (`limit: "rate"`, `Retry-After` until the window resets) or too many jobs running at once (`limit: "concurrency"`). A free key lifts to the paid tier's limits after one purchase.

## idempotency_conflict

`422` when the `Idempotency-Key` was used with a different body: use a new key for a new job. `409` while the first request with that key is still being processed: wait a moment and send it again. `details.job_id` names the job.

## conflict

`409`. The job is running and cannot be canceled, or the upload already has its file.

## input_rejected

`422`. An input that cannot be used: a URL that does not answer, a picture or mesh that cannot be read, a moderation refusal. Change the input; sending the same one again fails the same way. Nothing was charged.

## provider_failed

`502`. The model's provider failed after we retried. The credits for that stage were given back. Try again later or with another model.

## unavailable

`503`. The model or feature cannot run on this server right now. Nothing was charged.
