Credits + limits
Predictable cost, one budget per account, reruns never spend.
The unit
A scan costs ceil(span_days x symbols / 5000) units, computed from your validated document BEFORE the engine runs: span from the times.anchor_time bounds, symbols from your identity.symbol clause (the full universe of ~660 when unscoped). A 7-day universe scan is 1 unit; a 30-day universe scan is 4. The estimate and the charge are the same number - you can price a scan by reading your own document.
When you spend
A debit happens on exactly one path: HTTP 200 with X-Research-Cache: miss - the engine actually scanned. Everything else is free: cache hits (X-Research-Cache: hit), 304 revalidations against your ETag, validation failures, SCAN_BUSY, timeouts. Re-running a result never spends - determinism makes that enforceable, not a promise.
Every query response carries the meters: X-Research-Credits-Estimate, X-Research-Credits-Charged, X-Research-Credits-Remaining.
Budgets
| TIER | UNITS / MONTH (UTC) |
|---|---|
| Free | 5 |
| Pro | 100 |
One ledger per ACCOUNT: scans from the /research page and scans over the API draw the same budget. Interpret calls (POST /interpret) meter separately at a flat 1 unit per call because each one spends provider money. Over budget answers 402 INSUFFICIENT_CREDITS with your state in the body.
Concurrency + rate
| LIMIT | VALUE | ON HIT |
|---|---|---|
| In-flight scans per key | 1 | 429 SCAN_BUSY + Retry-After |
| Requests per key | 60 / minute | 429 RATE_LIMITED + Retry-After |
| Scan budget (engine) | 90 s | 504 SCAN_TIMEOUT |
The SCAN_BUSY dance
The engine bounds concurrent scans globally; under contention it queues your request up to 20 seconds, then answers 429 SCAN_BUSY with a Retry-After. Honor it, retry once or twice, and prefer re-running EXACT documents: identical documents share one flight and one cache entry, so a busy engine still serves your repeat for free the moment the first run lands.