> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eversince.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Calling tools

> The request and response of a tool call over REST, every error code, and how to make a retry safe.

## Request

`POST /api/v1/tools/{name}` with the tool's input as the JSON body. A read tool also answers `GET` with its input as query parameters, each converted to the type the schema declares; a read of many ids is a `POST`. Unknown fields and wrong types are rejected before anything runs.

Two headers apply to any tool: `Idempotency-Key`, equivalent to the `idempotency_key` field on a charged call, and `x-workspace-id` for an OAuth token naming another workspace.

## Response

```json theme={"dark"}
{
  "ok": true,
  "data": { … },
  "meta": { "request_id": "req_…", "cost": { … }, "cloud_processing": { … } },
  "media": [ … ]
}
```

`meta.cost` is present when credits were charged and `meta.cloud_processing` when minutes were, each with what was charged and what is left. `media` carries the pictures a tool returned inline (frames, a rendered still), so a REST caller sees what an MCP client sees.

## Response types

What `data` holds depends on the tool's kind, and every tool's description says what it returns.

* **A result**, from any write: what changed and the resulting state, with the ids of what was created. Reading the object again after a write returns what the response already said. A timeline or canvas write carries the new revision, and a write posted to the feed carries `feed_url`.
* **A job**, from any slow operation: its id, place in the queue and estimate. `get_jobs` follows it. See [Jobs](/concepts/jobs).
* **A page**, from any list: rows and `next_cursor`, passed back with the same filters for the next page. A read that stopped early says so in `cut_short`.
* **A batch**, from a tool that takes many refs: one result per input. A failed input is reported beside the rest rather than failing the call.

## Errors

```json theme={"dark"}
{
  "ok": false,
  "error": { "code": "…", "message": "…", "retryable": false, "suggested_action": "…" }
}
```

`suggested_action` is the next call that works, not a restatement of the error. Work that used minutes before failing carries `cloud_processing` on the error.

| Code                   | Status | Retry | Meaning and next step                                                                                                                                             |
| ---------------------- | ------ | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `validation_error`     | 400    | no    | The message names the field. `GET /tools` carries the exact input schema.                                                                                         |
| `not_media`            | 400    | no    | The ref is not audio or video.                                                                                                                                    |
| `unauthorized`         | 401    | no    | The credential is missing or invalid.                                                                                                                             |
| `forbidden`            | 403    | no    | The credential has no access to this resource. Another id will not help.                                                                                          |
| `refused`              | 403    | no    | Declined on purpose. The message says why.                                                                                                                        |
| `not_found`            | 404    | no    | Re-read the object that gave you the id rather than assembling one.                                                                                               |
| `insufficient_credits` | 402    | no    | `get_balance` returns the balance and where more can be added.                                                                                                    |
| `storage_full`         | 507    | no    | The owner's storage has no room for what this makes. `get_checkout_link` with `product: "storage"` returns a link to buy more, or `delete_items` frees room.      |
| `conflict`             | 409    | no    | Something changed underneath. Re-read and reapply.                                                                                                                |
| `revision_conflict`    | 409    | no    | The document moved since the revision given, or a user edited it since the last read. Re-read and reapply.                                                        |
| `needs_cloud`          | 409    | no    | The call, made through the desktop app, set `run_on: "local"` and the work needed the cloud, so it did not run. Call again without it, or with `run_on: "cloud"`. |
| `rate_limited`         | 429    | yes   | Wait for `Retry-After`, then retry the same call with the same key.                                                                                               |
| `payload_too_large`    | 413    | no    | The body is over 9 MB. Send the file by upload or URL instead.                                                                                                    |
| `unavailable`          | 503    | yes   | A provider or the service is briefly unavailable. Wait for `Retry-After`, then retry with the same key.                                                           |
| `internal_error`       | 500    | once  | An error on our side, not in the call. If it repeats, `submit_feedback`.                                                                                          |

## Safe retries

A call that charges takes an `idempotency_key`, generated for that operation. The same key on a retry, in the field or in the `Idempotency-Key` header, returns the job already dispatched instead of charging again. A new attempt takes a new key.

A write to a timeline or canvas takes `if_revision` from the last read. See [Timelines and canvases](/concepts/timelines-and-canvases).

## Timing

A call answers within about 30 seconds or returns a job. The API allows a call up to 300 seconds for the slowest tools. A client that cuts a call earlier loses the answer, not the work.
