# Usage and billing

Usage is counted per organization and per calendar month (UTC), and compared with the monthly quotas of the organization's plan. This page lists what each endpoint counts, what is free, how to read the counters, and the limits of each plan.

## What is metered

The meter keeps four counters per organization and month:

| Counter | Measures | Quota |
|---|---|---|
| `pages` | Pages fetched or documents parsed | Pages per month |
| `searches` | Search engine queries | Searches per month |
| `browserSeconds` | Time spent in an interactive browser | Browser seconds per month |
| `crawls` | Crawl and batch scrape jobs started | None (informational) |

What each endpoint adds:

| Endpoint | Counted | When |
|---|---|---|
| [Scrape](https://xdive.dev/docs/scrape.md) | 1 page | When the page is fetched, from the site or from the cache. |
| Scrape with `actions`, `wait_for` or `screenshot` | Browser seconds, not pages | When the browser run ends. |
| [Crawl](https://xdive.dev/docs/crawl.md) | 1 crawl, then 1 page per page in the results | The crawl when it is queued; the pages when the job finishes, including pages that failed. |
| [Batch scrape](https://xdive.dev/docs/batch-scrape.md) | 1 crawl, then 1 page per URL in the batch | The same as crawl. |
| [Search](https://xdive.dev/docs/search.md) | 1 search | When the search engines answer, including when the answer comes from the search cache. |
| Search with `search_depth: "advanced"` | 1 page per result read | After the results are read. |
| Search with `scrape` or `include_answer` | 1 page per result scraped | After the results are scraped. |
| [Research](https://xdive.dev/docs/research.md) | The `searches` and `pages_read` reported in the response's `usage` | When a new run succeeds. |
| [Extract](https://xdive.dev/docs/extract.md) | 1 page per source read | After the sources are read, before the model runs. |
| [llms.txt](https://xdive.dev/docs/llms-txt.md) | 1 page per page scraped | After the pages are scraped. |
| `POST /orgs/{id}/parse` | 1 page per document | When parsing succeeds. |
| Browser session actions | Browser seconds | Per actions call: its duration rounded up to whole seconds, at least 1. |

### What is free

- **Cached research answers.** Asking the same research question with the same options again within 10 minutes returns the stored answer with `"cached": true`, and it is not metered. The cache is kept by each API server, so on a deployment with several servers a repeat can still run (and be metered) again. Pass `"no_cache": true` to force a new, metered run.
- **Map.** [Map](https://xdive.dev/docs/map.md) is not metered, but it is refused with `402` once the page quota is used up.
- **Reads and polling.** Crawl status, cancellation, crawl errors and `GET /whoami` are never metered.
- **Rejected and failed requests.** A request refused before any work starts (validation, scope, rate limit or quota) costs nothing, and so do a scrape whose page could not be fetched, a search the engines did not answer, and a research run that failed or timed out.

> **Note:**
>
> Cache hits on scrape and search are faster and do not touch the target site or the search engine, but they are still counted: a cached scrape counts one page and a cached search counts one search.

## Reading usage

The dashboard shows the current period under **Billing** (**Billing & usage**). The same numbers come from the API:

`GET https://xdive.dev/api/orgs/{id}/usage`

This endpoint takes a [session token](https://xdive.dev/docs/authentication.md#dashboard-sessions) from a member of the organization; API keys cannot read usage. `GET /whoami` with an API key returns the organization's `plan`.

```bash
curl "https://xdive.dev/api/orgs/$ORG_ID/usage" \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

```json
{
  "browserSecondsUsed": 45,
  "crawlsUsed": 4,
  "limits": {
    "name": "free",
    "monthlyPages": 1000,
    "monthlySearches": 100,
    "monthlyBrowserSeconds": 600,
    "maxBrowserSessions": 1,
    "maxSchedules": 3,
    "requestsPerMinute": 60,
    "maxConcurrentRequests": 5,
    "maxConcurrentCrawls": 2
  },
  "pagesUsed": 312,
  "period": "2026-10",
  "plan": "free",
  "proxy": {
    "enabled": false,
    "monthlyPages": 200,
    "pagesUsed": 0
  },
  "schedules": 1,
  "searchesUsed": 27
}
```

| Field | Type | Description |
|---|---|---|
| `period` | string | The current period, the UTC calendar month as `YYYY-MM`. |
| `plan` | string | The organization's plan. |
| `limits` | object | The plan's limits; see [Plans](#plans). `-1` means unlimited. |
| `pagesUsed` | integer | Pages counted this period. |
| `searchesUsed` | integer | Searches counted this period. |
| `browserSecondsUsed` | integer | Browser seconds counted this period. |
| `crawlsUsed` | integer | Crawl and batch scrape jobs started this period. |
| `schedules` | integer | Schedules that exist now (a count, not monthly usage). |
| `proxy` | object | The organization's residential proxy entitlement, used for [government and banking sites](https://xdive.dev/docs/scrape.md#government-and-banking-sites): `enabled` (set by the platform administrator; `false` until then), `monthlyPages` (the monthly allowance of proxied pages; `0` allows none) and `pagesUsed` (pages fetched through the proxy this period). |

Counters are updated within seconds of the work, not instantly.

## Per-key budgets

An API key can have its own monthly page and search budget, on top of the plan quota. Give a key with a budget to an AI agent or a contractor, and it stops at that budget without using up the organization's quota.

```bash
curl -X POST "$XDIVE_URL/api/orgs/$ORG_ID/api-keys" \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "research agent", "scopes": ["scrape", "search"], "monthly_page_limit": 500, "monthly_search_limit": 100}'
```

- `0`, the default, means only the plan quota applies.
- Change a budget with `PATCH /orgs/{id}/api-keys/{keyId}` and `{"monthly_page_limit": 1000}`. An omitted field keeps its value. The change applies at once.
- `GET /orgs/{id}/api-keys` lists each key's `pagesUsed` and `searchesUsed` this month.
- A request over the key's budget gets `402` `QUOTA_EXCEEDED`, and the message names the key's budget. A crawl started with less budget left than its `max_pages` is shortened to what is left. A batch scrape with more URLs than the budget allows is refused.
- Budgets reset with the plan period, at the start of each calendar month (UTC).

## Plans

Every organization is on one plan. New organizations start on `free`.

| Limit | `free` | `pro` | `enterprise` |
|---|---|---|---|
| Pages per month (`monthlyPages`) | 1,000 | 50,000 | Unlimited |
| Searches per month (`monthlySearches`) | 100 | 10,000 | Unlimited |
| Browser seconds per month (`monthlyBrowserSeconds`) | 600 | 36,000 | Unlimited |
| Browser sessions at once (`maxBrowserSessions`) | 1 | 3 | 10 |
| Schedules (`maxSchedules`) | 3 | 50 | Unlimited |
| Requests per minute (`requestsPerMinute`) | 60 | 600 | 6,000 |
| Concurrent synchronous requests (`maxConcurrentRequests`) | 5 | 50 | 500 |
| Concurrent crawls, fair share (`maxConcurrentCrawls`) | 2 | 10 | 50 |

When a monthly quota is used up, the requests that need it return `402` until the next month or an upgrade. See [Errors and limits](https://xdive.dev/docs/errors.md#quotas) for the details and for how the per-minute and concurrency limits behave.

## Changing plans

Only the organization's owner can change its plan, from **Billing** in the dashboard.

- When the server has billing configured, upgrading goes through a hosted checkout (`POST /orgs/{id}/billing/checkout` with `{"plan": "pro"}` returns its `url`), and the new plan applies once the payment is confirmed. Downgrading to `free` is immediate.
- When billing is not configured, as on many self-hosted servers, the owner switches plans directly with `PUT /orgs/{id}/plan` and `{"plan": "pro"}`.

---

Source: https://xdive.dev/docs/usage · All docs for agents: https://xdive.dev/llms.txt
