# Jobs

> How long-running tool calls run as jobs: polling, cancelling, timeouts and billing.

[`web_crawl`](https://clonvo.com/docs/web-crawl.md), [`web_research`](https://clonvo.com/docs/web-research.md) and [`browser_task`](https://clonvo.com/docs/browser-task.md) can take minutes, so they run as jobs. `POST /v1/tools/{id}` answers with a job instead of the usual response: `202` while the provider is still working, or `200` when the job finished within the request (crawls on Clonvo credits, and on some providers, do). The job’s `id` is the call’s generation id.

| Endpoint | Description |
| --- | --- |
| `GET /v1/tools/jobs/{id}` | The job: its status, and its result or error once it’s final. |
| `DELETE /v1/tools/jobs/{id}` | Cancels a running job. A final job is returned unchanged. |

## Check a job

```bash
curl https://api.clonvo.com/v1/tools/jobs/gen-01M6B4Q8R2T4V6X8Z0B2D4F6H8 \
  -H "Authorization: Bearer $CLONVO_API_KEY"
```

Wait about `poll_after_ms` between checks. Once `status` is `completed`, `result` holds the tool’s result and `usage` what it cost; `failed` and `cancelled` jobs carry `error` instead.

```python
import os
import time

import requests

BASE_URL = "https://api.clonvo.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['CLONVO_API_KEY']}"}

resp = requests.post(
    f"{BASE_URL}/tools/web_research",
    headers=HEADERS,
    json={"arguments": {"query": "Which open source vector databases support hybrid search?"}},
    timeout=60,
)
resp.raise_for_status()
job = resp.json()

while job["status"] == "running":
    time.sleep(job.get("poll_after_ms", 10000) / 1000)
    resp = requests.get(f"{BASE_URL}/tools/jobs/{job['id']}", headers=HEADERS, timeout=60)
    resp.raise_for_status()
    job = resp.json()

if job["status"] == "completed":
    print(job["result"]["answer"])
else:
    print(job["status"], job["error"]["message"])
```

## The job object

| Field | Description |
| --- | --- |
| `id` | The job’s id, which is the call’s generation id. It appears in **Activity** and works with [`GET /v1/generation`](https://clonvo.com/docs/other-endpoints.md#get-v1-generation). |
| `object` | Always `tool.job`. |
| `tool` | The tool you called. |
| `status` | `running`, `completed`, `failed` or `cancelled`. The last three are final. |
| `provider` | `clonvo` for a job on Clonvo credits, or the id of [your own provider](https://clonvo.com/docs/tool-keys.md#provider-ids) for a job on your key. |
| `created_at`, `completed_at` | When the job started, and when it reached a final status (`null` while it’s running). |
| `poll_after_ms` | While the job is running: how long to wait before checking again. |
| `result` | With `status: "completed"`: the tool’s result, described on the tool’s page. |
| `error` | With `status: "failed"` or `"cancelled"`: the [usual error object](https://clonvo.com/docs/errors.md), with `message`, `type`, `code` and `param`. |
| `usage` | Once the job is final: what it cost and what Clonvo charged, as for any tool call. See [Tool billing](https://clonvo.com/docs/tool-billing.md). |

## Cancel a job

```bash
curl -X DELETE https://api.clonvo.com/v1/tools/jobs/gen-01M6B4Q8R2T4V6X8Z0B2D4F6H8 \
  -H "Authorization: Bearer $CLONVO_API_KEY"
```

Clonvo asks the provider to stop the job where it can. Some providers can’t stop a run once it has started, so it may still finish and bill your provider account. On Clonvo credits, a cancelled job is charged what it still costs (see [Research and browser tasks on credits](https://clonvo.com/docs/tool-billing.md#research-and-browser-tasks-on-credits)).

## How jobs run

-   Clonvo checks the provider in the background as well, so a job finishes and is billed even if you never ask for it again.
-   A job is billed once, when it ends, like any tool call: on your own key, its list price counts toward your BYOK allowance and the fee applies above it; on Clonvo credits, it’s charged its cost plus 2%. Clonvo holds credits for the most it can be charged from the start, until the job ends.
-   A job stops after 30 minutes (45 for `web_research`) and fails with `job_timeout`.
-   Jobs are kept for 24 hours after they finish; after that `GET` answers `404` with `tool_job_not_found`.
-   Over MCP, clients that support tasks get one for each job; other clients get the job’s id and the `job_status` tool. See [MCP](https://clonvo.com/docs/mcp.md#long-running-tools).