API keys
Every/v1 endpoint takes a bearer token.
Provision a key
--rate-limit is requests per minute for that key, defaulting to 120.
Scopes
Each endpoint requires exactly one scope. A key missing it gets403 insufficient_scope — the call is rejected before any provider is touched, so nothing is billed.
Grant the narrowest set that works. A key that only enriches profiles should hold
data:people:read and nothing else.
GET /v1/health needs a valid key but no scope, which makes it the right way to verify a key works before granting it anything.Rate limits
Limits are per key, not per user. Ten workers sharing one key share one minute-bucket; ten customers with their own keys each get their own. Every response carries the current state:
At the default
120/min a key averages about 2 requests per second, with bursts allowed inside the minute. High-volume integrations should be issued a higher limit — 600/min is roughly 10 QPS.
Concurrent requests are fine. Each one authenticates the key, checks scope, resolves the workspace’s provider key, calls the data source, records usage, and returns. Protection downstream is separate and independent: web search is QPS-limited, and profile enrichment is concurrency-limited.
Over the limit returns 429 rate_limited. Back off until X-RateLimit-Reset.
Request IDs
Every response includesX-Request-Id, mirrored in meta.request_id. Send your own X-Request-Id and it is echoed back instead of generated, which makes correlating your logs with cost events straightforward — the same ID appears on the matching row in GET /v1/usage/costs.
Workspace sessions
The/api endpoints authenticate differently. They expect a signed-in workspace session, sent as a browser cookie, and act on that session’s active workspace. Requests must include credentials:
Everything is workspace-scoped
Everything is workspace-scoped
A record belonging to another workspace returns
404, not 403. Existence and access are deliberately indistinguishable, so you cannot probe for IDs you do not own.Write actions need an operator role
Write actions need an operator role
Running a search, enriching, publishing a campaign, and launching all require operate permission. Read endpoints only require a session.
Frozen accounts are blocked
Frozen accounts are blocked
A frozen account can sign in but every
/api route except /api/me returns 403 with code frozen.GET /api/shares/{token} takes no authentication at all. The token is the credential, so treat share URLs as secrets.