# Quote a call

`POST /v1/tools/{tool}/quote`

Needs an API key.

Price a call before making it: the provider that would serve it, and what it would cost.

Takes the same body as `POST /v1/tools/{tool}/calls`. A tool, input, `provider` or `require` the call would refuse is refused with the same error. No provider is called, nothing is charged or reserved, and no call is recorded. `cost` is what the call would charge you if the serving provider serves it. `max_cost` is the most the call can be charged if a fallback provider serves it: what your balance reserves while the call runs.

Unlike a call, a quote ignores your balance, `reuse_within` and `label`, and any API key may ask for one, read-only and test keys included.

## Example request

cURL:

```bash
curl https://api.voxoria.ai/v1/tools/google.serp.organic/quote \
  -H "Authorization: Bearer $VOXORIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"query":"crm for small teams","country":"gb"}}'
```

Python:

```python
import os

import httpx

response = httpx.post(
    "https://api.voxoria.ai/v1/tools/google.serp.organic/quote",
    headers={"Authorization": f"Bearer {os.environ['VOXORIA_API_KEY']}"},
    json={"input": {"query": "crm for small teams", "country": "gb"}},
    timeout=60,
)
print(response.json())
```

TypeScript:

```ts
const response = await fetch("https://api.voxoria.ai/v1/tools/google.serp.organic/quote", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.VOXORIA_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"input": {"query": "crm for small teams", "country": "gb"}}),
});
console.log(await response.json());
```

MCP (`tools/call` params):

```json
{
  "name": "quote_tool",
  "arguments": {
    "tool": "google.serp.organic",
    "input": {
      "query": "crm for small teams",
      "country": "gb"
    }
  }
}
```

## Path parameters

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `tool` | string | Yes |  | The tool's ID, such as `google.serp.organic`. |

## Request body

What to call a tool with.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `input` | object | Yes |  | The tool's input, as its input schema describes. |
| `provider` | string | No |  | Serve the call from this provider only. Omit to use the cheapest that can. 1 or more characters. Can be `null`. |
| `require` | array of string | No |  | Outputs the serving provider must return, by name. Only providers that return each optional one are used; a required one is always returned, so naming it changes nothing. Each item: 1 or more characters. Can be `null`. |
| `reuse_within` | integer | No |  | Reuse a result instead of calling again: if your workspace has a succeeded call with the same tool, `input`, `provider` and `require` made within this many seconds (1 to 2592000, 30 days), the newest such call is returned with `reused: true`. No provider is called, nothing is charged and no call is recorded; `id` and `cost` are that earlier call's. Omit to always make a new call. From 1 to 2592000. Can be `null`. |
| `label` | string | No |  | A name of your choosing for the call, 1 to 100 characters, to find it again by. Not unique. Ignored when the answer is a reused or replayed call. 1 to 100 characters. Can be `null`. |
| `wait` | integer | No | `25` | Seconds to wait for the call to finish, 0 to 50. A call that finishes in time is answered with its result. One still running is answered with `status: "pending"`: it goes on running, and reading the call again by its `id` returns its result. 0 answers at once. From 0 to 50. |

## Response

### 200

What the call would cost now.

What a call with this request would cost now. Making a quote is free and changes nothing.

`provider` is the provider that would serve the call, and `cost` what it would charge: for a provider priced per result, the most it can, and per call and result, with the results the request asks for. If it fails, the next provider serves, so `max_cost` is the most the call can be charged whichever serves: what your balance reserves while it runs. A call your available balance cannot cover at `max_cost` is refused. Prices can change between a quote and a call.

| Field | Type | Nullable | Description |
| --- | --- | --- | --- |
| `tool` | string | No | The tool quoted. |
| `provider` | string | No | The provider that would serve the call. |
| `cost` | object | No | What the call would cost you if `provider` serves it. |
| `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 | The price: the sum of the other two. |
| `max_cost` | object | No | The most the call can cost whichever provider serves it: what your balance reserves while it runs. |
| `max_cost.provider_usd` | string | No | The data provider's part of `total_usd`. |
| `max_cost.platform_fee_usd` | string | No | Voxoria's part of `total_usd`. |
| `max_cost.total_usd` | string | No | The price: the sum of the other two. |

### Example 200 response

```json
{
  "tool": "google.serp.organic",
  "provider": "example-provider",
  "cost": {
    "provider_usd": "0.02",
    "platform_fee_usd": "0.0014",
    "total_usd": "0.0214"
  },
  "max_cost": {
    "provider_usd": "0.0300",
    "platform_fee_usd": "0.0021",
    "total_usd": "0.0321"
  }
}
```

## 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`). |
| 403 | [Refused request](/docs/call-response.md#refused-request) | A subscription is required. |
| 404 | [Refused request](/docs/call-response.md#refused-request) | No tool has this ID (`MODEL_NOT_FOUND`). |
| 409 | [Refused request](/docs/call-response.md#refused-request) | The tool cannot be called yet. |
| 422 | [Invalid request](/docs/call-response.md#invalid-request), [Refused request](/docs/call-response.md#refused-request) | The request is not valid (`VALIDATION`, with `errors`), or no provider can serve it (`NO_ELIGIBLE_PROVIDER`). |
| 429 | [Refused request](/docs/call-response.md#refused-request) | Too many requests with this API key (`RATE_LIMITED`). |
| 503 | [Refused request](/docs/call-response.md#refused-request) | The tool is not available right now (`TOOL_UNAVAILABLE`). Retry shortly. |
