Authentication
All public endpoints use a workspace API token:GETroutes requireapi.readPOSTroutes requireapi.write401means the token is missing or invalid403means the token is valid but lacks the required scope
GET /v1/public/token-infoGET /v1/public/tenant-info
Test keys
Keys come in two modes, and the key itself tells you which one you are holding:
A test key is not a sandbox. It runs the same scrapers against the same live
targets and returns the same responses, including the same failures — a stub
that always succeeded would tell you nothing about whether this API works on
your URLs, which is the only question an evaluation is asking.
What differs is what it spends. Instead of draining credits, a test key draws on
a per-organization allowance of 125 notional credits per rolling 24-hour
window. Nothing is billed, and
creditsCharged is 0 on every test job.
The window is trailing, not calendar-aligned. Usage ages out continuously, so the allowance
recovers gradually rather than resetting at a fixed hour — there is no midnight to wait for after
an afternoon of testing.
429 and
error.code = "test_quota_exhausted":
GET /v1/public/balance reports both positions, and names the mode of the key
that asked, so a test key is never handed a balance it is not spending:
Credits
Search and scrape endpoints are metered. Credits are charged when a job is created — by a live key. A test key spends its allowance instead; everything below describes live keys.- A fresh successful job reports
creditsChargedwith the debit amount. - A cached hit reports
creditsCharged: 0andcached: true. - If the workspace does not have enough credits, the API returns
402witherror.code = "insufficient_credits".
Cache controls
All metered search and scrape requests accept the shared cache/job fields:fresh: bypass cache and force a new fetchcacheTtlSec: override the cache TTL written for the new result (capped at 7 days)idempotencyKey: deduplicate repeated submissionswebhookUrl: receive a terminal callback instead of only polling
Sync wait defaults
The API defaults to synchronous behavior:waitdefaults totruewaitTimeoutMscan ask for a shorter timeout- the server still enforces its own maximum sync wait budget
202 Accepted with a poll URL rather than holding the request open longer.
Long-running kinds — research, linkedin/employees, and LinkedIn channel — always return 202 immediately regardless of wait: their minimum runtime is minutes, so a sync wait could never observe completion. Poll the job URL or use webhookUrl.