Skip to content
unzoi docs
Search and navigation
Start here
REST API
MCP
Limits and plans
Agent clients
SDKs
Guides

Credits and overage

Every call is priced in credits from one published table, before it runs. A plan includes credits a month and credits a minute, and both count the same credits.

PlanPriceCredits a monthCredits a minuteAt the allocation
Free Free 1,000 120 Stops
Build $29/mo 50,000 600 Bills overage
Scale $199/mo 500,000 3,000 Bills overage
Archive $799/mo 2,000,000 12,000 Bills overage

The allocation resets at the start of each calendar month (UTC).

What each call costs

A plain search costs 1 credit. A call that makes the index do more work costs more: a vector ranking, entity resolution, a threshold, a checked geographic filter, a relationship traversal. The price is the same on REST and over MCP, and the same whichever host answers; how many index partitions a call reaches is never billed.

CallCredits
search_news, top_headlines — keyword ranking or a browse 1
search_news — mode=semantic / mode=hybrid 2 / 3
the same with near, bbox, amount_min or amount_max 1–4: 1 per 500 candidates checked (keyword or browse); +1 on a semantic or hybrid search
a cursor page 1–2 to start, 1–3 after, in place of the base
+ each entity_id +1–2, up to 5 ids
+ signal_percentile_min +1 when a threshold resolves
+ offset on /search and /top-headlines +1 per full 1,000 rows
list_stories 1, or 2 semantic and 3 hybrid unless sort=recency; +1 with a geographic, event-class or amount filter; +ids and percentile as above; +1 per full 100 rows of offset, which stops at 1,000
get_story 2
get_article 1
find_related 2
resolve_entity 1–2
aggregate_news 1, whatever the number of buckets; +1 with event_type; +ids as above
related_entities 2 to 4 + 2 per edge that gets evidence, at most 16
connection_path 3–8 with max_hops=1, 3–9 with evidence=0, up to 16
entity_network 2 to 4 + 2 per edge that gets evidence, at most 16; +3 for a comparison window
shared_exposures n + 3 to 2n + 3 for n entity ids; +1 with signal_stats
create_watch, list_watches, get_watch, delete_watch, watch_events 1 each
each run of a watch the credits the watch's /stories query takes
each webhook delivery attempt 1, retries included
account_status, /account, MCP initialize, tools/list and notifications, any estimate=true preview 0

Every priced answer says what it cost: credits_charged in the body, and the x-credits-charged header on REST. Each tool description and each endpoint in /openapi.json ends with its price.

What a call is charged, by outcome

OutcomeCharged
200, including a partial answerWhat the call took, held inside its estimate
404The operation's minimum: the lookup ran
400, 401, 402, a credit refusal, 408, 5xxNothing
The client disconnects mid-callThe operation's minimum

Free calls

/account, account_status, the MCP handshake (initialize, tools/list, notifications) and any preview cost 0 credits. They are not unlimited: each takes a message token from an allowance equal to the plan's credits a minute, and so does a request refused before it ran. Rate limits has the detail.

Know the price first

Add estimate=true to any endpoint, or "estimate": true to any tool call. The call does not run and costs nothing; the answer is its credit range, the breakdown, where the key stands, and whether the call would run now.

curl -s -G "https://api.unzoi.com/search" -H "x-api-key: $UNZOI_KEY" \
  --data-urlencode "q=chip export controls" --data-urlencode "mode=hybrid" \
  --data-urlencode "entity_id=organization:asml" --data-urlencode "estimate=true"
{
  "estimate": true,
  "operation": "search_news",
  "credits": { "min": 4, "max": 5 },
  "breakdown": [
    { "item": "hybrid_pass", "min": 3, "max": 3 },
    { "item": "entity_id", "min": 1, "max": 2 }
  ],
  "max_credits": null,
  "credits_charged": 0,
  "credits_limit": 50000,
  "credits_used": 12483,
  "credits_remaining": 37517,
  "credits_reset_secs": 394200,
  "credits_per_minute": 600,
  "hard_cap": false,
  "would_run": true,
  "would_refuse": null
}

To cap a call instead, pass max_credits. A call whose worst case costs more is refused with 400 credit_budget_exceeded before it runs, and costs nothing. An agent working to a budget can pass it on every call.

Watches and webhooks

A watch runs its /stories query for you, and each run is charged what that query costs to the key that created it: 1 credit for a plain recency poll, more with entity ids, a threshold or a derived filter. Every webhook delivery attempt costs 1 credit, retries included, so one event can cost up to 4. A create preview (estimate=true) adds per_run, runs_per_month and webhook_attempts_per_event_max.

PlanWatchesShortest intervalRuns a month, one watch at that interval
Free 2 60 minutes ~720
Build 25 15 minutes ~2,880
Scale 200 5 minutes ~8,640
Archive 1,000 1 minute ~43,200

On a key that stops at its allocation, a run that the credits left cannot cover does not run: the watch pauses with status: paused_credits and is tried again hourly. A pending delivery is held with delivery.status: held_credits, without counting an attempt, and resumes when credits return; a held event that reaches its seven-day retention fails. On a key that bills overage, runs and deliveries carry on and are billed like any call.

The headers

x-credits-charged: 2
x-credits-limit: 50000
x-credits-used: 12485
x-credits-remaining: 37515
x-credits-reset: 394200

used is the durable counters plus this replica's charged calls, so it includes the call that returned it and matches the invoice. reset is seconds until the next calendar month. On an unlimited account the allocation headers are absent rather than zero — a limit of 0 would read as "blocked". The per-minute headers are on Rate limits.

Hard cap, or overage

What happens at the ceiling depends on one flag, reported by /account:

  • hard_cap: true — a call is refused, before it runs, when its worst case is more than the credits left. Only the free tier defaults to this, because there is no card on file. Checking the worst case means a key never overshoots its allocation, even with calls in flight.
  • hard_cap: false — calls keep working and the credits past the allocation are billed. Paid tiers default here, so a traffic spike degrades your bill rather than your product.

Either behaviour can be set on any paid plan from the console.

Overage

PlanPer 1,000 credits past the allocation
Free Not offered — this tier stops instead
Build $1.00
Scale $0.60
Archive $0.40

Hitting the ceiling

On a hard-capped key without enough credits left for a call:

HTTP/1.1 429 Too Many Requests
retry-after: 394200
x-credits-remaining: 2
x-credits-charged: 0

{
  "error": "insufficient credits",
  "code": "insufficient_credits",
  "detail": "this call can cost up to 5 credits and 2 are left this month; ...",
  "retry_after_secs": 394200,
  "credits": { "min": 4, "max": 5 },
  "credits_limit": 1000,
  "credits_used": 998,
  "credits_remaining": 2
}

This shares a status with the per-minute limit, and the two want different handling: switch on code. insufficient_credits will not clear for retry-after seconds, possibly days — but a cheaper call might still fit, which credits and credits_remaining let you decide.

Over MCP the same refusal is a tool error with the same fields, on an open session, so the agent can report it and carry on the moment the account is topped up. The exact shape is here.

How billing sees it

Credits are metered continuously and reported to Stripe against the account's credits meter. The figures in /account, in the console and on the invoice come from the same durable counters, and the console breaks them down by operation, with calls and credits side by side.