# List calls

`GET /v1/calls`

Needs an API key.

List your organization's calls, newest first.

Calls are listed without their `output`; fetch one call to read it. Results are paged: pass the `next_cursor` of one page as `cursor` to read the next, until `has_more` is false. Filter by `tool`, `status` or `label`.

To find the calls of one request, pass its `input` as JSON with `tool`, and its `provider` and `require` if it had them. A paid result is kept with no time limit, so you can read it again instead of calling again.

## Example request

cURL:

```bash
curl "https://api.voxoria.ai/v1/calls?tool=google.serp.organic&limit=10" \
  -H "Authorization: Bearer $VOXORIA_API_KEY"
```

Python:

```python
import os

import httpx

response = httpx.get(
    "https://api.voxoria.ai/v1/calls",
    params={"tool": "google.serp.organic", "limit": 10},
    headers={"Authorization": f"Bearer {os.environ['VOXORIA_API_KEY']}"},
)
print(response.json())
```

TypeScript:

```ts
const response = await fetch("https://api.voxoria.ai/v1/calls?tool=google.serp.organic&limit=10", {
  headers: {
    Authorization: `Bearer ${process.env.VOXORIA_API_KEY}`,
  },
});
console.log(await response.json());
```

MCP (`tools/call` params):

```json
{
  "name": "list_calls",
  "arguments": {
    "tool": "google.serp.organic",
    "limit": 10
  }
}
```

## Query parameters

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `limit` | integer | No | `50` | The most calls to return. From 1 to 100. |
| `cursor` | string | No |  | The `next_cursor` of the previous page. Omit to read the first page. |
| `tool` | string | No |  | Only calls of this tool, by its ID. |
| `status` | string | No |  | Only calls with this status. One of `pending`, `succeeded`, `failed`. |
| `input` | string | No |  | Only calls made with exactly this input: the tool's input as a JSON object, URL-encoded. Needs `tool`. Matched as `reuse_within` matches a call, with `provider` and `require`. |
| `provider` | string | No |  | With `input`: only calls that named this provider. Omit for calls that named none. 1 or more characters. |
| `require` | array of string | No |  | With `input`: only calls that required these optional outputs. Repeat for each. Each item: 1 or more characters. Repeat for each value. |
| `label` | string | No |  | Only calls with this label, matched exactly. 1 to 100 characters. |

## Response

### 200

One page of calls, newest first.

| Field | Type | Nullable | Description |
| --- | --- | --- | --- |
| `items` | array of object | No | This page's items. |
| `items.id` | string | No | The call's ID. Read the call again with `GET /v1/calls/{call_id}`. |
| `items.tool` | string | No | The tool called. |
| `items.status` | string | No | `pending` while providers are tried, `succeeded` once one served the call, `failed` when none did. One of `pending`, `succeeded`, `failed`. |
| `items.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`. |
| `items.provider` | string | Yes | The provider that served the call. Null unless the call succeeded. |
| `items.requested_provider` | string | Yes | The provider the request named in `provider`. Null when it named none. |
| `items.input` | object | No | The input as you sent it. |
| `items.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. |
| `items.require` | array of string | No | The optional outputs the request required, by name. |
| `items.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. |
| `items.cost.provider_usd` | string | No | The data provider's part of `total_usd`. |
| `items.cost.platform_fee_usd` | string | No | Voxoria's part of `total_usd`. |
| `items.cost.total_usd` | string | No | What the call cost you, drawn from your balance: the sum of the other two. |
| `items.label` | string | Yes | The name you gave the call. Null when it has none. |
| `items.created_at` | string | No | When the call was made. Format `date-time`. |
| `items.completed_at` | string | Yes | When the call succeeded or failed. Null while it is pending. Format `date-time`. |
| `next_cursor` | string | Yes | Pass as `cursor` to read the next page. Null on the last page. |
| `has_more` | boolean | No | Whether another page follows. |

### Example 200 response

```json
{
  "items": [
    {
      "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"
    }
  ],
  "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wMS0wNVQwOTowMDowMFoifQ",
  "has_more": true
}
```

## Errors

| Status | Body | Description |
| --- | --- | --- |
| 400 | [Refused request](/docs/call-response.md#refused-request) | The request was refused. |
| 401 | [Refused request](/docs/call-response.md#refused-request) | The API key is missing, wrong or revoked (`INVALID_AUTH_TOKEN`). |
| 422 | [Invalid request](/docs/call-response.md#invalid-request) | The request is not valid (`VALIDATION`), such as `input` without `tool`. |
| 429 | [Refused request](/docs/call-response.md#refused-request) | Too many requests with this API key (`RATE_LIMITED`). |
