# Call response

A call returns one JSON object: the call's ID, status and cost, with the tool's result in `output`. `POST /v1/tools/{tool}/calls` and `GET /v1/calls/{call_id}` return it over REST, and `call_tool` and `get_call` over MCP.

Each tool's page lists the blocks of its `output`: see [all tools](/docs/tools.md).

## Fields

Every field is always present. A field marked nullable can be `null`.

| Field | Type | Nullable | Description |
| --- | --- | --- | --- |
| `id` | string | No | The call's ID. Read the call again with `GET /v1/calls/{call_id}`. |
| `tool` | string | No | The tool called. |
| `status` | string | No | `pending` while providers are tried, `succeeded` once one served the call, `failed` when none did. One of `pending`, `succeeded`, `failed`. |
| `failure_reason` | string | Yes | Why a failed call was not served. `rate_limited`: every provider tried refused it for its rate limit; retry later. `billed_provider_failure`: the provider failed the call and billed it, so no other was tried. `deadline_exceeded` and `abandoned`: the call ran out of time. `all_attempts_failed` and `internal_error`: no provider served it. Null unless the call failed. One of `all_attempts_failed`, `billed_provider_failure`, `rate_limited`, `deadline_exceeded`, `internal_error`, `abandoned`. |
| `provider` | string | Yes | The provider that served the call. Null unless the call succeeded. |
| `requested_provider` | string | Yes | The provider the request named in `provider`. Null when it named none. |
| `input` | object | No | The input as you sent it. |
| `resolved_input` | object | No | The input as the tool read it: case-insensitive values lowercased, defaults filled in, and a page token as its provider issued it. |
| `require` | array of string | No | The optional outputs the request required, by name. |
| `cost` | object | Yes | What the call was charged, in USD. All zeros for a failed call, unless it failed `billed_provider_failure`. Null while the call is pending. |
| `cost.provider_usd` | string | No | The data provider's part of `total_usd`. |
| `cost.platform_fee_usd` | string | No | Voxoria's part of `total_usd`. |
| `cost.total_usd` | string | No | What the call cost you, drawn from your balance: the sum of the other two. |
| `label` | string | Yes | The name you gave the call. Null when it has none. |
| `created_at` | string | No | When the call was made. Format `date-time`. |
| `completed_at` | string | Yes | When the call succeeded or failed. Null while it is pending. Format `date-time`. |
| `output` | object | Yes | What the tool returned, in the blocks its reference lists. Null unless the call succeeded. |
| `reused` | boolean | No | Whether a request with `reuse_within` was answered with this earlier call instead of a new one. A reused call is not charged again. |

## Example

A succeeded call of `google.serp.organic`, each list of its output cut to 3 items. The ID, provider, cost and times are examples.

```json
{
  "id": "tcall_8xQ2vT7mKpR4nW9cYb3LdE",
  "tool": "google.serp.organic",
  "status": "succeeded",
  "failure_reason": null,
  "provider": "example-provider",
  "requested_provider": null,
  "input": {
    "query": "crm for small teams",
    "country": "gb"
  },
  "resolved_input": {
    "query": "crm for small teams",
    "country": "gb",
    "language": "en",
    "device": "desktop",
    "page": 1,
    "autocorrect": true
  },
  "require": [],
  "cost": {
    "provider_usd": "0.02",
    "platform_fee_usd": "0.0014",
    "total_usd": "0.0214"
  },
  "label": "weekly-rankings",
  "created_at": "2026-01-05T09:00:00Z",
  "completed_at": "2026-01-05T09:00:02Z",
  "output": {
    "results": [
      {
        "position": 1,
        "title": "5 best CRMs for small teams (and how to choose the right ...",
        "url": "https://www.insightly.com/blog/top-crms-for-small-teams/",
        "snippet": "Insightly is a modern, affordable CRM that small teams love because it's easy to use, you can customize it to your needs, and it scales with you as you grow. Read more",
        "displayed_url": "https://www.insightly.com › blog › top-crms-for-small-t..."
      },
      {
        "position": 2,
        "title": "Best CRM software for small businesses (2026)",
        "url": "https://www.enterprisenation.com/learn-something/best-crm-software-small-businesses/",
        "snippet": "22 Dec 2025 — Comprehensive set of features: HubSpot CRM lets you manage your contacts and track leads with ease. You can also integrate your email marketing. Read more",
        "displayed_url": "https://www.enterprisenation.com › learn-something › b..."
      },
      {
        "position": 3,
        "title": "10 Shortlist UK's CRM Software for Small Business (2026)",
        "url": "https://www.dynamicssquare.co.uk/blog/best-crm-software-for-small-business/",
        "snippet": "12 Jul 2025 — CRM software provides teams with access to customer information, communication history, preferences, opportunities, and previous interactions. Read more",
        "displayed_url": "https://www.dynamicssquare.co.uk › blog › best-crm-sof..."
      }
    ],
    "related_questions": [],
    "related_searches": [
      {
        "query": "Best crm for small teams"
      },
      {
        "query": "Best CRM for small business free"
      },
      {
        "query": "Best CRM for small business reddit"
      }
    ]
  },
  "reused": false
}
```

## Errors

A request that fails answers with an HTTP error status and one of three bodies. Branch on `code`, not on `detail`.

### Refused request

A refused request. Nothing was charged. Sent with every error status not listed below, such as 402 when your balance is too low.

| Field | Type | Nullable | Description |
| --- | --- | --- | --- |
| `detail` | string | No | What went wrong, in a sentence. |
| `code` | string | No | The kind of error. Branch on this, not on `detail`. One of `UNKNOWN`, `VALIDATION`, `MODEL_NOT_FOUND`, `NOT_ALLOWED`, `INVALID_AUTH_TOKEN`, `INVALID_CREDENTIALS`, `TOKEN_EXPIRED`, `EMAIL_NOT_VERIFIED`, `DUPLICATE_EMAIL`, `DUPLICATE_SLUG`, `QUOTA_EXCEEDED`, `INSUFFICIENT_BALANCE`, `PAYMENT_PROVIDER_ERROR`, `TOOL_NOT_CALLABLE`, `TOOL_UNAVAILABLE`, `NO_ELIGIBLE_PROVIDER`, `TOOL_CALL_FAILED`, `TOOL_CALL_TIMED_OUT`, `TEST_KEY_NOT_ALLOWED`, `IDEMPOTENCY_KEY_REUSED`, `RATE_LIMITED`, `PROVIDER_RATE_LIMITED`, `CALL_RESULT_DEFERRED`. |

### Invalid request

A request that is not valid, with each of its problems. Nothing was charged. Sent with 422 and `VALIDATION`.

| Field | Type | Nullable | Description |
| --- | --- | --- | --- |
| `detail` | string | No | What went wrong, in a sentence. |
| `errors` | array of object | No | Each problem with the request. |
| `errors.loc` | array of string or integer | No | Where the problem is, as a path into the request. |
| `errors.msg` | string | No | What is wrong there. |
| `code` | string | No | The kind of error. Branch on this, not on `detail`. One of `UNKNOWN`, `VALIDATION`, `MODEL_NOT_FOUND`, `NOT_ALLOWED`, `INVALID_AUTH_TOKEN`, `INVALID_CREDENTIALS`, `TOKEN_EXPIRED`, `EMAIL_NOT_VERIFIED`, `DUPLICATE_EMAIL`, `DUPLICATE_SLUG`, `QUOTA_EXCEEDED`, `INSUFFICIENT_BALANCE`, `PAYMENT_PROVIDER_ERROR`, `TOOL_NOT_CALLABLE`, `TOOL_UNAVAILABLE`, `NO_ELIGIBLE_PROVIDER`, `TOOL_CALL_FAILED`, `TOOL_CALL_TIMED_OUT`, `TEST_KEY_NOT_ALLOWED`, `IDEMPOTENCY_KEY_REUSED`, `RATE_LIMITED`, `PROVIDER_RATE_LIMITED`, `CALL_RESULT_DEFERRED`. |

### Failed call

An error about a recorded call: `call_id` names it, and `GET /v1/calls/{call_id}` reads it.

A call that ran and that no provider served was not charged, unless its provider billed the failure: then `detail` says what it was charged. A call whose result could not be returned (`CALL_RESULT_DEFERRED`) ran as recorded. Sent with 502 and `TOOL_CALL_FAILED`, 504 and `TOOL_CALL_TIMED_OUT`, or 429 and `PROVIDER_RATE_LIMITED`.

| Field | Type | Nullable | Description |
| --- | --- | --- | --- |
| `detail` | string | No | What went wrong, in a sentence. |
| `code` | string | No | The kind of error. Branch on this, not on `detail`. One of `UNKNOWN`, `VALIDATION`, `MODEL_NOT_FOUND`, `NOT_ALLOWED`, `INVALID_AUTH_TOKEN`, `INVALID_CREDENTIALS`, `TOKEN_EXPIRED`, `EMAIL_NOT_VERIFIED`, `DUPLICATE_EMAIL`, `DUPLICATE_SLUG`, `QUOTA_EXCEEDED`, `INSUFFICIENT_BALANCE`, `PAYMENT_PROVIDER_ERROR`, `TOOL_NOT_CALLABLE`, `TOOL_UNAVAILABLE`, `NO_ELIGIBLE_PROVIDER`, `TOOL_CALL_FAILED`, `TOOL_CALL_TIMED_OUT`, `TEST_KEY_NOT_ALLOWED`, `IDEMPOTENCY_KEY_REUSED`, `RATE_LIMITED`, `PROVIDER_RATE_LIMITED`, `CALL_RESULT_DEFERRED`. |
| `call_id` | string | No | The failed call's ID. Read the call with `GET /v1/calls/{call_id}`. |
