# Pattern: estimate cost

> Measure a request's exact token count with a free test call, turn it into a monthly cost, and compare pay as you go with the plans read live from the API.

Dex charges input tokens only, and output is free, so a request's cost is known before it runs: `usage.input_tokens` times the rate. You never estimate output. Measure a representative request once with a free test key, multiply by your volume, and compare the ways to pay.

## Step 1: measure one request

Send one typical request with a test key: it costs nothing, and the same request costs the same number of tokens on a live key.

```bash
curl -s https://api.thinqit.ai/v1/decide \
  -H "authorization: Bearer $DEX_API_KEY" \
  -H "content-type: application/json" \
  --data-binary @request.json | jq .usage
```

`usage.input_tokens` is the billed count: `state_tokens` (your text, billed once however many questions share it) plus `question_tokens` (every question's instructions, criteria and options or levels). The recipes in this cookbook measure like this:

| Recipe | Questions | Input tokens (state + questions) | 1,000 calls pay as you go | 1,000 calls at the Base rate | 1,000 calls at the Hot rate | 1,000 calls at the Fierce rate |
| --- | --- | --- | --- | --- | --- | --- |
| [Support ticket routing and priority](/docs/cookbook/support-routing/) | pick, rate, check | 185 (99 + 86) | EUR 0.185 | EUR 0.0925 | EUR 0.037 | EUR 0.01681818 |
| [Content moderation](/docs/cookbook/moderation/) | pick, rate, check | 232 (86 + 146) | EUR 0.232 | EUR 0.116 | EUR 0.0464 | EUR 0.02109091 |
| [Lead scoring and intent](/docs/cookbook/lead-scoring/) | pick, rate, check | 216 (87 + 129) | EUR 0.216 | EUR 0.108 | EUR 0.0432 | EUR 0.01963636 |
| [AI agent guardrails and tool gating](/docs/cookbook/agent-guardrails/) | pick, check, check | 266 (139 + 127) | EUR 0.266 | EUR 0.133 | EUR 0.0532 | EUR 0.02418182 |
| [Document and email triage](/docs/cookbook/document-triage/) | pick, pick, check, rate | 290 (157 + 133) | EUR 0.29 | EUR 0.145 | EUR 0.058 | EUR 0.02636364 |
| [Product categorisation](/docs/cookbook/categorisation/) | pick, check, pick | 289 (73 + 216) | EUR 0.289 | EUR 0.1445 | EUR 0.0578 | EUR 0.02627273 |
| [Sentiment and stance](/docs/cookbook/sentiment/) | rate, pick, check | 172 (72 + 100) | EUR 0.172 | EUR 0.086 | EUR 0.0344 | EUR 0.01563636 |
| [Compliance and policy checks](/docs/cookbook/compliance/) | check, check, pick, rate | 233 (91 + 142) | EUR 0.233 | EUR 0.1165 | EUR 0.0466 | EUR 0.02118182 |
| [Grading LLM outputs and eval pipelines](/docs/cookbook/llm-grading/) | check, check, check, rate | 164 (73 + 91) | EUR 0.164 | EUR 0.082 | EUR 0.0328 | EUR 0.01490909 |
| [Data quality checks](/docs/cookbook/data-quality/) | check, pick, check | 227 (124 + 103) | EUR 0.227 | EUR 0.1135 | EUR 0.0454 | EUR 0.02063636 |

Prices exclude VAT. A plan's rate applies to tokens inside its weekly allowance; tokens beyond it are paid at the pay-as-you-go rate.

Two things move the count: the length of the state, and the number and length of the questions. Adding a question to an existing request costs only its own question tokens. Long option descriptions on a pick with many options add up; keep them short.

## Step 2: compare the ways to pay

`GET /v1/plans` returns the plans with their current prices, weekly allowances and effective rates, without a key. Read them at run time instead of copying prices into your code.

```python tab="Python"
import httpx

CALLS_PER_MONTH = 400_000
TOKENS_PER_CALL = 185  # usage.input_tokens of your measured request

plans = httpx.get("https://api.thinqit.ai/v1/plans", timeout=30).json()
standard = plans["standard_unit_price_micro_cents"]  # micro-cents per input token, pay as you go
tokens_month = CALLS_PER_MONTH * TOKENS_PER_CALL
tokens_week = tokens_month * 12 / 52

def eur(micro_cents: float) -> float:
    return micro_cents / 100_000_000  # 1 EUR = 100,000,000 micro-cents

print(f"{tokens_month:,} input tokens a month")
print(f"pay as you go: EUR {eur(tokens_month * standard):,.2f} a month")
for p in plans["data"]:
    overage_week = max(0, tokens_week - p["week_allowance_tokens"])
    monthly = p["price_cents"] / 100 + eur(overage_week * 52 / 12 * standard)
    seats = "" if p["available"] else " (no founding-round seat left)"
    print(f"{p['name']}: EUR {monthly:,.2f} a month{seats}")
```

```ts tab="TypeScript"
const CALLS_PER_MONTH = 400_000;
const TOKENS_PER_CALL = 185; // usage.input_tokens of your measured request

type Plan = { name: string; price_cents: number; week_allowance_tokens: number; available: boolean };
const plans = (await (await fetch("https://api.thinqit.ai/v1/plans")).json()) as {
  standard_unit_price_micro_cents: number;
  data: Plan[];
};
const standard = plans.standard_unit_price_micro_cents; // micro-cents per input token, pay as you go
const tokensMonth = CALLS_PER_MONTH * TOKENS_PER_CALL;
const tokensWeek = (tokensMonth * 12) / 52;
const eur = (microCents: number) => microCents / 100_000_000; // 1 EUR = 100,000,000 micro-cents
const fmt = (x: number) => x.toLocaleString("en-GB", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

console.log(`${tokensMonth.toLocaleString("en-GB")} input tokens a month`);
console.log(`pay as you go: EUR ${fmt(eur(tokensMonth * standard))} a month`);
for (const p of plans.data) {
  const overageWeek = Math.max(0, tokensWeek - p.week_allowance_tokens);
  const monthly = p.price_cents / 100 + eur(((overageWeek * 52) / 12) * standard);
  console.log(`${p.name}: EUR ${fmt(monthly)} a month${p.available ? "" : " (no founding-round seat left)"}`);
}
```

Save the TypeScript as `cost.mts` and run `npx tsx cost.mts`. Both print the monthly input tokens, the pay-as-you-go cost and each plan's cost with the overage, from the prices the API returns today. Prices exclude VAT.

## How the plans work

| Plan | Per month, excl. VAT | Input tokens per week | Effective rate per million input tokens | Reset of the week |
| --- | --- | --- | --- | --- |
| Base | EUR 9.99 | 4,611,000 | EUR 0.50 | EUR 2.50 |
| Hot | EUR 24.00 | 27,692,000 | EUR 0.20 | EUR 6.00 |
| Fierce | EUR 39.00 | 99,000,000 | EUR 0.09 | EUR 9.75 |
| Pay as you go | none | none | EUR 1.00 | none |

- The allowance is a number of input tokens per week that resets every 7 days from the day you subscribed. Unused tokens do not roll over, so spread steady traffic over the week.
- Calls beyond the allowance are paid from the prepaid balance at the pay-as-you-go rate. With no allowance and no balance left, a live call gets `402 insufficient_balance` and is not charged; its `hints` say what to do. See [Tokens and billing](/docs/reference/billing/).
- A reset refills the current week's allowance at once, for a quarter of the monthly price.

## Keep an eye on it

- `GET /v1/balance` (scope `balance:read`) shows the plan, `week_used_tokens` of `week_allowance_tokens`, `week_resets_at` and the prepaid balance.
- `GET /v1/usage` (scope `usage:read`) gives day or hour buckets with `input_tokens`, `allowance_tokens`, `paid_tokens` and `charge_micro_cents`. `end` is the first day not included, so `end` = tomorrow includes today.
- The console shows the same numbers, and emails the account owner when the balance runs low or a week's allowance is used up.
