Getting started
API reference
Every endpoint at a glance, plus the base URL, auth, versioning, request tracing, and the rate and quota model.
The Sprouts Data Platform API is a JSON HTTP API over companies, people, and seven document corpora. Pick an endpoint below, or read the essentials further down: the base URL, the one auth header, versioning and request tracing apply to every endpoint, so if you read one reference page before integrating, make it this one.
Endpoints#
POST /v1/search: companies, people or a document corpus, in words, filters, or both.
POST /v1/similar: company look-alikes from one or more anchors.
POST /v1/entities/{category}: full records by id, domain, LinkedIn URL or name. Nine routes: companies, persons and seven document categories.
POST /v1/relationships*: people connecting two companies, who one person can reach, and the institutions two companies share.
POST /v1/relationships/ask: a relationship question as a sentence, routed for you.
POST /v1/org-chart: one company's people by department × seniority, plus sub-departments and locations.
POST /v1/agents/runs: an asynchronous research run for questions no single search answers.
GET /v1/coverage: what the index holds, per corpus. Free.
/v1/lists: save records into named lists and read them back. Free.
GET /v1/search/filters/{name}: the values a filter accepts. Free.
GET /v1/sorts/{category}: the fields a search can be ordered by. Free.
GET /v1/usage/history: your own runs, with a free replayable snapshot of each search.
POST /v1/feedback: report a wrong, missing or stale result. Free.
GET /v1/credits, GET /v1/keys/usage, top-ups and POST /v1/members/resolve: balance, per-key spend and your organisation.
The shape every list-returning endpoint shares, field by field.
Every route, with its scope and metering
| Method & path | What it does | Scope | Metered |
|---|---|---|---|
POST /v1/search | Search one category | dsp.search.read | Yes (dsp.search.fast / .auto / .deep) |
POST /v1/similar | Company look-alikes from anchors | dsp.search.read | Yes (dsp.similar) |
POST /v1/entities/{category} | Records by id — 9 routes (companies, persons, documents) | dsp.entities.read | Yes (dsp.entities) |
POST /v1/relationships | People connecting two companies, across the affiliation graph | dsp.search.read | Yes (dsp.relationships) |
POST /v1/relationships/reach | Who one named person can reach at a company | dsp.search.read | Yes (dsp.relationships) |
POST /v1/relationships/institutions | The employers and schools two companies share | dsp.search.read | Yes (dsp.relationships) |
POST /v1/relationships/ask | A relationship question in words, routed for you | dsp.search.read | Yes (dsp.relationships.ask) |
POST /v1/org-chart | One company's people by department × seniority — plus /departments and /locations | dsp.search.read | Yes (dsp.org_chart) |
POST /v1/agents/runs | Start an agent run (async) | dsp.agents.write | Yes (dsp.agent.run.* — held on create, settled when the finished run is read) |
POST /v1/agents/runs/{run_id}/cancel | Cancel a run | dsp.agents.write | Free (a cancelled run is not charged) |
GET /v1/agents/runs… | List runs, read one, page its results or stream its events | dsp.agents.read or dsp.agents.write | Free (the run pays once, at settle) |
GET /v1/coverage | What the index holds, per corpus | dsp.search.read | Free |
GET /v1/search/filters/{name} | Values a company/person filter accepts — plus /{category}/{name} for documents | dsp.search.read | Free |
GET /v1/sorts/{category} | Fields a search can be ordered by | dsp.search.read | Free |
GET /v1/credits | Tenant credit balance | dsp.usage.read | Free |
GET /v1/keys/usage | Calling key's spend (key-only) | dsp.usage.read | Free |
POST /v1/billing/top-up/intents | Start a credit top-up, paid in the browser — plus GET …/intents/{topup_id} for its status | dsp.usage.read | Free (the top-up itself is a purchase) |
POST /v1/members/resolve | Resolve one email address to a member of your organisation | dsp.search.read or dsp.agents.write | Free |
GET /v1/usage/history | Your own runs, newest first | dsp.usage.read | Free |
GET /v1/usage/history/{run_id} | One run, with its stored snapshot | dsp.usage.read | Free |
GET /v1/usage/metrics | Your run counts and credits per day | dsp.usage.read | Free |
POST /v1/feedback | Report a wrong, missing or stale result — plus GET /v1/feedback and /tags (/tags needs no credential) | dsp.search.read or dsp.usage.read | Free |
PUT /v1/feedback/votes | Vote on a result set, or flag one record — plus GET /v1/feedback/votes | dsp.search.read or dsp.usage.read | Free |
/v1/lists* | Create, rename and delete saved lists; add, remove and read their items | dsp.search.read or dsp.entities.read | Free |
POST /v1/lists/{list_id}/export, POST /v1/search/export | CSV export — not switched on yet (404 export.not_enabled) | dsp.search.read or dsp.entities.read | — |
Base URL#
https://api.sproutsdata.ai
All paths are relative to it. The OpenAPI document lives at /openapi.json (interactive docs at /docs) and is generated from the running service, so it is always current. It lists only the routes an API key can call, declares the optional Idempotency-Key header on every billed route, and names each operation's accepted scopes in x-scopes. Its info.version is the API contract version, currently 1.0.0.
Versioning#
Every endpoint is under /v1. Within v1, changes are additive only:
- New fields may appear in responses; existing fields never change meaning or disappear.
- Fields reserved for future use are present from day one and serialize as explicit
null(e.g.attribution[].url) — the day they carry values is a data change, not an API change. - Enums (
category, errorcode, degradationreason) are closed sets; members are added deliberately and never removed.
If something does have to be removed or changed in a way that isn't additive, it is announced in the changelog at least 90 days before the change, and the old behaviour keeps working until then. Two such removals have already been made, both recorded in the changelog: the prior_company filter and from_my_company.
Authentication#
One header on every request:
X-API-Key: $SPROUTS_API_KEY
A key goes in X-API-Key only: Authorization: Bearer is for OAuth tokens, and a key sent there gets the generic 401 auth.unauthorized. See Authentication for prefixes, scopes, and key management.
Content types#
- Requests:
application/json. Request bodies reject unknown fields with a 422: a parameter the API silently ignored would let you believe you asked for something you didn't. - Success responses:
application/json. - Error responses:
application/problem+json(RFC 9457) — see Errors.
Request tracing#
Every response, success and error, carries a request id: in the body (meta.request_id / request_id) and as the X-Request-Id response header.
You may send your own X-Request-Id (≤128 chars, [A-Za-z0-9_.:-]) and it is echoed back, so your logs and ours share a key.
Rates, quotas, and credits#
Three separate mechanisms, with distinct answers:
| Mechanism | Status | Family | Fixed by |
|---|---|---|---|
| Rate/quota limits | 429 | quota.* | Waiting — honour Retry-After |
| Credits | 402 | credits.insufficient | Buying — never retry |
| Upstream failures | 503/504 | upstream.* | Retrying after Retry-After — nothing was charged |
- Metered endpoints charge only once the response is ready, so an error, including a 503 or 504, is not charged. The one exception is
503 credits.unavailable: the billing service could not confirm the charge, so the request may have been charged. Retry it with the sameIdempotency-Keyand rows already paid for are not charged again. Seecredits.unavailable. - Test keys (
sk_dsp_test_) are metered at zero cost.
Rate limits
There is no per-key rate limit on the REST API today, for live or test keys. Build your client to honour a 429 with Retry-After anyway: back off, then retry after the number of seconds the header gives. Limits may be introduced later, and they will be announced in the changelog first.
The limits that do exist today:
- Agent runs.
POST /v1/agents/runsrefuses a start with429 quota.entity_ceilingonce a credential has been shown 5,000,000 distinct entities in the last 30 days, and with429 quota.concurrency_exceeded(Retry-After: 30) when more than five runs are being started at the same moment on one credential. See Agent runs. - Dashboard sessions. Playground traffic is throttled per signed-in session at 30 requests/minute and 500/day (
429 quota.burst_exceeded), and sign-in attempts are throttled too. - MCP server. 60 tool calls per minute per credential, answered with a
429andRetry-After. See MCP limits.
The response envelope is shared by every list-returning endpoint.