> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tilion.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Billing and usage

Plans define monthly browser-hour and premium-egress allowances, plus a concurrent-session limit. Earlier plans also meter actions and CAPTCHA solves.

Developer and Team accounts use card billing. Requests do not debit the wallet, and a zero wallet balance does not block usage. Available wallet credits cover overage before it is invoiced.

Free and credit-funded accounts use per-call charges. Credit amounts in endpoint descriptions apply to those accounts. `GET /v1/credits` returns base credit rates, excluding the premium-egress per-MB rate.

## GET /v1/usage

Month-to-date usage against the plan, the key's throttles, and premium egress by exit type. Read `remaining` here rather than waiting for a 402.

Auth: Bearer API key. No body.

```bash theme={"dark"}
curl https://back.tilion.dev/v1/usage -H "Authorization: Bearer $TILION_API_KEY"
```

```json theme={"dark"}
{
  "owner": "acme",
  "tier": "team",
  "month": "2026-10",
  "usage": {"actions": 4115, "egress_bytes": 12699763818, "browser_seconds": 446141, "sessions": 8273, "captcha_solves": 12},
  "limits": {"actions": null, "egress_bytes": 26843545600, "browser_seconds": 9000000, "sessions": null, "captcha_solves": null},
  "remaining": {"actions": null, "egress_bytes": 14143781782, "browser_seconds": 8553859, "sessions": null, "captcha_solves": null},
  "browser_hours": {"used": 123.928, "included": 2500.0, "remaining": 2376.072},
  "concurrency_limit": 250,
  "rate_limits": {
    "drive_per_minute": 1000,
    "session_creates_per_minute": 60,
    "concurrent_inspects": 3,
    "scope": "api_key",
    "shared_across_workers": true
  },
  "premium_egress": true,
  "self_healing": true,
  "overage_allowed": true,
  "premium_egress_usage": {
    "included_gb": 25.0,
    "used_gb": 3.9238,
    "remaining_gb": 21.0762,
    "by_type": {
      "dc": {"used_gb": 0.0, "overage_gb": 0.0},
      "isp": {"used_gb": 0.0016, "overage_gb": 0.0},
      "res": {"used_gb": 3.9222, "overage_gb": 0.0},
      "mobile": {"used_gb": 0.0, "overage_gb": 0.0}
    },
    "overage_usd": 0.0,
    "prices_usd_per_gb": {
      "res": [{"up_to_gb": 5, "usd_per_gb": 5.5}, {"up_to_gb": 20, "usd_per_gb": 4.5}, {"up_to_gb": 1000, "usd_per_gb": 3.5}, {"up_to_gb": null, "usd_per_gb": 2.0}],
      "mobile": [{"up_to_gb": 4, "usd_per_gb": 7.0}, {"up_to_gb": 14, "usd_per_gb": 6.17}, {"up_to_gb": 714, "usd_per_gb": 4.5}, {"up_to_gb": null, "usd_per_gb": 3.0}],
      "dc": [{"up_to_gb": 50, "usd_per_gb": 0.48}, {"up_to_gb": 181, "usd_per_gb": 0.44}, {"up_to_gb": 1100, "usd_per_gb": 0.36}, {"up_to_gb": null, "usd_per_gb": 0.32}],
      "isp": [{"up_to_gb": 5, "usd_per_gb": 5.5}, {"up_to_gb": 20, "usd_per_gb": 4.5}, {"up_to_gb": 1000, "usd_per_gb": 3.5}, {"up_to_gb": null, "usd_per_gb": 2.0}]
    }
  },
  "enforced": true
}
```

| Field | Type | Meaning |
| - | - | - |
| `owner` | string | Your account id. |
| `tier` | string | Your plan: `free`, `developer`, `team`, `pro`, `scale` or `enterprise`. |
| `month` | string | The billing month, `YYYY-MM`. |
| `usage` | object | Month to date: `actions` (billable calls that delivered), `egress_bytes` (page, file and screenshot bytes delivered to you), `browser_seconds` (time sessions were alive), `sessions` (sessions counted this month), `captcha_solves`. |
| `limits` | object | The plan's included amount on each axis; `null` is unlimited. |
| `remaining` | object | `limits` minus `usage`, floored at 0; `null` where the limit is `null`. |
| `browser_hours` | object | `browser_seconds` in hours: `used`, `included`, `remaining`. |
| `concurrency_limit` | integer | Live sessions you may hold at once, the higher of the plan's cap and a cap granted to this key. |
| `rate_limits` | object or null | The throttles that answer 429: `drive_per_minute`, `session_creates_per_minute`, `concurrent_inspects`, `scope` (`api_key`), `shared_across_workers` (true when the count is global). `null` when throttling is off. |
| `premium_egress` | boolean | Whether the plan may use residential, ISP and mobile exits. |
| `self_healing` | boolean | Whether blocked reads escalate through stronger exits. |
| `overage_allowed` | boolean | Whether usage past the allowance is metered (true) or refused (false). |
| `premium_egress_usage` | object | Proxy traffic this month: `included_gb`, `used_gb`, `remaining_gb`; `by_type` for `dc`, `isp`, `res` and `mobile` with `used_gb` and `overage_gb`; `overage_usd` run up so far; `prices_usd_per_gb`, the graduated bands per type (`up_to_gb: null` is the last band). |
| `enforced` | boolean | Whether the plan limits are enforced. |

## GET /v1/credits

The wallet balance and base credit rates. Developer and Team use card billing as described above; these rates do not imply per-call wallet debits on those plans.

```bash theme={"dark"}
curl https://back.tilion.dev/v1/credits -H "Authorization: Bearer $TILION_API_KEY"
```

```json theme={"dark"}
{
  "owner": "acme",
  "balance": 12480.5,
  "enforced": true,
  "browser_hours_remaining": 208.008,
  "cost": {
    "action": 1.0,
    "captcha": 20.0,
    "egress_mb": 1.0,
    "session": 2.0,
    "browser_minute": 1.0,
    "browser_hour": 60.0,
    "plan_call": 2.0,
    "workflow_step": 2.0
  }
}
```

| Field | Type | Meaning |
| - | - | - |
| `owner` | string | Your account id. |
| `balance` | number | Credits in the wallet. On credit-funded accounts, concurrent charges can take it below zero and later calls can be refused until you top up. Developer and Team use wallet credits for overage. |
| `enforced` | boolean | Whether credit enforcement is enabled. Card-billed Developer and Team accounts remain exempt from per-call wallet checks. |
| `browser_hours_remaining` | number or null | `balance` divided by the hourly browser rate; null when browser time is not priced. |
| `cost.action` | number | One billable call (fetch, navigate, extract, search, act, and so on). |
| `cost.captcha` | number | One CAPTCHA or challenge solve, wherever it happens. |
| `cost.egress_mb` | number | One MB of page, file, screenshot or CDP traffic delivered to you through a datacenter exit. |
| `cost.session` | number | Starting a session. |
| `cost.browser_minute`, `cost.browser_hour` | number | Each minute a session is alive, debited once a minute, whether or not you call anything. |
| `cost.plan_call` | number | One `POST /v1/plan`, or the planning step of a prompt-driven `POST /v1/workflow`. |
| `cost.workflow_step` | number | Each step a workflow runs. |

## POST /v1/credits/redeem

Redeem a promo code into the wallet. Single use per account.

Request: `{"code": "..."}` (`promo` is accepted as an alias). Codes are matched case-insensitively.

```bash theme={"dark"}
curl -X POST https://back.tilion.dev/v1/credits/redeem \
  -H "Authorization: Bearer $TILION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"code": "YOUR-CODE"}'
```

A valid code answers 200 with `ok: true`, `granted` (the credits added) and `balance` (the new balance); the new balance applies to the very next call.

Errors:

| Status | `error` | When |
| - | - | - |
| 400 | `unknown_code` | No such code, or it has expired. |
| 409 | `already_redeemed` | This account already used the code; `balance` is included. |
| 429 | `rate_limited` | Too many redeem attempts; the session-create bucket throttles guessing. |

## What each route costs

The table uses the example credit rates above for Free and credit-funded accounts. Read `GET /v1/credits` for current base rates. Session creation, browser time, actions and egress are separate charges; an unsuccessful page read can still incur session or traffic charges.

| Route | Credits |
| - | - |
| `POST /v1/session` | 2 at create, then 1 per minute while the session lives. A failed `start_url` navigation can still incur the create charge. |
| `POST /v1/session/{id}/navigate`, `/act`, `/elements`, `/context` (GET and POST), `/rotate-ip`, `POST /v1/session/{id}/tabs` | 1 |
| `POST /v1/fetch` | 1 for a successful delivery, plus egress at the applicable rate. The action is waived on undelivered or `incomplete` pages; egress can still be charged. Polling `GET /v1/job/{id}` adds no action charge. |
| `POST /v1/extract` | 1, plus 5 when you ask for structured `data` with `schema` or `prompt` (that pass runs a model). |
| `POST /v1/scrape` | 1 plus 1 per MB of page. |
| `POST /v1/crawl` | 1 per page delivered, at least 1. |
| `POST /v1/inspect` | 1 per capture. |
| `POST /v1/search`, `POST /v1/task` | 1 |
| `POST /v1/session/{id}/screenshot`, `POST /v1/session/{id}/files/fetch` | 1 plus 1 per MB of the image or file. |
| `POST /v1/agent`, `POST /v1/template` | 1 per run. |
| `POST /v1/solve`, and automatic solving during a session | 20 per challenge solved; nothing when there was nothing to solve. |
| `POST /v1/plan` | 2 |
| `POST /v1/workflow` | 2 per step, plus 2 for the plan when you send a `prompt`. A recording replay bills steps only. |
| Raw CDP and Playwright connect, and the noVNC window | 1 per MB relayed to you through a datacenter exit; the premium rate on a residential session. |

Traffic through a residential, ISP or mobile exit is billed per MB at the premium rate instead of the datacenter rate, and counted against the plan's included premium egress.

## Premium egress

Traffic through a [custom proxy](https://docs.tilion.dev/sessions/custom-proxy.md) does not count against the Tilion premium proxy allowance. Browser time is billed as usual.

Every byte a session moves through a paid exit (residential, ISP or mobile, chosen with `residential: true`, `proxy_type`, `stealth: "max"` or a `geo` target on create, or spent by self-healing on a blocked page) is metered by exit type and reported in `premium_egress_usage`. The plan's included GB is shared by all types; past it, each GB is invoiced at the graduated prices in `prices_usd_per_gb` on a plan with overage, and refused on a plan without it. Datacenter sessions keep working either way.

Refusals you can get:

| Status | `error` | When |
| - | - | - |
| 402 | `premium_egress_exhausted` | The month's included proxy traffic is used up on a plan without overage. |
| 402 | `insufficient_credits` | The wallet cannot cover the next charge. `balance` and `redeem_url` are included. |
| 402 | `quota_exceeded` | The monthly allowance is used up on a plan without overage. `reason`, `tier`, `upgrade_url` and `checkout` are included. |
| 403 | `account_suspended` | The account was suspended; contact support. |

## `premium_required`

`POST /v1/fetch` and `POST /v1/extract` do not fail when a page can only be reached through a paid exit you cannot use. They answer 200 with the outcome they could reach (`status` `challenged`, `hard_blocked` or similar) and set `premium_required` to a sentence saying what would unlock it: that this month's included premium egress is used up and the plan needs an upgrade, or that the wallet needs more credits for residential unlock and CAPTCHA solving. It is `null` on every other answer.

## Plans

Developer and Team are the self-serve paid plans, billed by card through the dashboard; Free needs no card. Checkout and the billing portal are dashboard actions. Both paid plans allow overage: browser time, premium egress by exit type, and on the earlier plans actions and solves, are metered past the included amounts and invoiced; credits in the wallet are spent on overage first. Pro and Scale remain for customers already subscribed. Enterprise lifts every cap.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.