Credits & errors
Credits & usage
What each call costs, how a search is charged across its pages, and how to read your balance and per-key spend.
Every metered call spends credits from your workspace's data-platform balance, and this page lists what each one costs. The model is built to hold no surprises:
- Searches are charged for the results they deliver, never for results you did not receive.
- A call is charged only once its response is ready, so an error doesn't cost anything.
- Going back to results you have already loaded is free.
- Checking your balance or spend is always free.
Three exceptions are worth knowing up front:
- A cursor sent again with a new
limitre-delivers some rows under a new range, and those rows are charged again (details). - A deep search (
mode: "deep") is charged its flat price even when it returns no rows, because the agent ran either way. - A
503 credits.unavailablemeans the billing system couldn't confirm the charge, so the request may have been charged. Retry with the sameIdempotency-Keyso rows already paid for aren't charged twice (details).
Credits are measured to three decimal places, so a small search costs less than one credit. Every billed response reports its own cost in meta.credits_charged.
Use cases#
A nightly job must not stop halfway on a 402. Call GET /v1/credits first and compare spendable against the job's expected cost, for a go/no-go decision before any credit is spent.
Issue each service its own key and read GET /v1/keys/usage per key, bucketed by day and action. You get per-service, per-action spend that reconciles against what you bought.
Use a sk_dsp_test_ key: same corpus, same responses, zero cost. Every response says meta.environment: "test", so test results can never be mistaken for live ones.
What each call costs#
Search
Basic and AI search charge a base price that covers the first 10 results, then a price for each extra result.
| Call | First 10 results | Each extra result |
|---|---|---|
Basic search — POST /v1/search with mode: "fast" | 0.5 credits | 0.08 credits |
AI search — POST /v1/search with mode: "auto" | 0.595 credits | 0.085 credits |
Worked examples:
| Results delivered | Basic search | AI search |
|---|---|---|
| 1 to 10 | 0.5 | 0.595 |
| 11 | 0.58 | 0.68 |
| 25 | 1.7 | 1.87 |
| 50 | 3.7 | 3.995 |
| 100 | 7.7 | 8.245 |
The base is charged once per search, whether the first page holds 1 result or 10. A search that finds nothing costs nothing.
Look-alikes, relationships and lookups
| Call | Price |
|---|---|
Find similar companies — POST /v1/similar | 2 credits for the first 10 results, then 1 credit per next 10 |
Relationships — POST /v1/relationships and POST /v1/relationships/reach | 2 credits for the first 10 results, then 1 credit per next 10 |
A relationship question in words — POST /v1/relationships/ask | The relationships price above. A question answered by shared institutions is 2 credits flat |
Shared institutions — POST /v1/relationships/institutions | 2 credits flat |
Record lookup — every POST /v1/entities/* route | 1 credit per record found. Ids that come back found: false are free |
Org chart — POST /v1/org-chart, /departments and /locations | 1 credit flat. A call that returns nothing is free |
A part-filled block of 10 is charged as a full block: 25 look-alikes cost 2 + 1 + 1 = 4 credits. A call priced per result or per block costs nothing when it returns nothing; a flat-priced call is charged whatever it returns, because the work behind it ran either way. Org chart is the exception: it is flat-priced but free when it returns nothing.
Agent runs and deep search
An agent run (POST /v1/agents/runs) is priced per run by its effort level, whatever the number of results.
| Effort | Credits per run |
|---|---|
Quick — minimal | 1.02 |
Basic — low | 2.125 |
Standard — medium | 8.5 |
Detailed — high | 42.5 |
Maximum — xhigh | 85 |
Automatic — auto | The price of the effort it selects, never more than 85 |
A deep search (POST /v1/search with mode: "deep") runs the same engine within one request. It is charged the price of the effort it actually ran, which today is Quick (1.02 credits), and it returns up to limit rows (default 10).
Free calls
Deliberately listed, never inferred:
GET /v1/coverage,GET /v1/credits,GET /v1/keys/usageGET /v1/usage/history,GET /v1/usage/history/{run_id},GET /v1/usage/metrics- The vocabulary lookups:
GET /v1/search/filters/{name},GET /v1/search/filters/{category}/{name},GET /v1/sorts/{category} - The agent-run reads:
GET /v1/agents/runs,GET /v1/agents/runs/{run_id},GET .../results,GET .../events,POST .../cancel. A run is charged once, when the firstGET /v1/agents/runs/{run_id}or cancel after it finishes settles it (details) - Saved lists: every
/v1/lists*route - The top-up link routes:
POST /v1/billing/top-up/intentsandGET /v1/billing/top-up/intents/{topup_id} - The feedback routes:
POST /v1/feedback,GET /v1/feedback,GET /v1/feedback/tags,GETandPUT /v1/feedback/votes
The vocabulary lookups are free on one principle: they are the menu, not the meal. A filter picker or a sort control has to be filled before anyone can run a search, so charging for it would be charging before an order was placed.
How a search is charged across pages#
A search keeps one running count of the results it has delivered, across all of its pages. Each page is charged only for the results it adds:
- Page size does not change the total. One page of 25 Basic results and a page of 10 followed by a page of 15 both cost 1.7 credits.
- Going back is free. Sending a
next_cursoryou have already used again returns those rows at no cost (meta.credits_charged: 0). - A request without a cursor starts a new search and pays the base again. Changing the query or the filters always starts a new search; the old cursor is refused with
422 pagination.cursor_invalid. - The first page has no cursor. Keep it rather than asking for it again, or send the same
Idempotency-Key(see below).
Two edges worth knowing:
- Re-sending an old cursor with a different
limitre-delivers some rows under a new range, and every row in that range is charged again at the extra-result rate, not only the rows you hadn't seen. - Results are counted by position. If the index changes between your pages, a record can move; the count is of rows delivered, not of distinct records.
Retries
Send an Idempotency-Key header on a billed request so a retry is recognised. It is honoured on POST /v1/search, POST /v1/similar, the four POST /v1/relationships* routes, the three POST /v1/org-chart* routes and the nine POST /v1/entities/* routes. The same key on the same request, from the same credential, on the same UTC day, belongs to the same search, so a retry that returns the same rows is not charged again. A different key, or no key, is a deliberate new search. Reusing a key with a different body silently starts a new search too; there is no error.
The key protects you in the one case where a retry could otherwise pay twice: a response lost after the charge was made. A retry that returns a different number of rows (an AI search can vary) is a different range, and it is charged again in full, not just for the difference.
Agent runs work differently: Idempotency-Key is required on POST /v1/agents/runs, a reused key returns the original run whatever the body says, and run keys never expire. See Agent runs.
Agent runs hold, then settle#
A run's cost is not known until it ends, so creating one holds the tier price rather than charging it — comparable to a hold on a payment card. A wallet that cannot cover the hold gets a 402 before the run starts.
- A run that succeeds is charged its tier price when it is settled: the first time the finished run is read with
GET /v1/agents/runs/{run_id}, or by a cancel. The rest of the hold is released. Reading results, listing runs and the events stream don't settle it. - A run that fails or is cancelled releases the hold and charges nothing.
effort: "auto"holds 85 credits, the Maximum price, while it chooses, then is charged the price of the effort it ran. Today Automatic runs at Detailed, so it is charged 42.5. Run details report the effort that ran (effort_ran).- The hold lasts 35 minutes from the start of the run. A run nobody reads before then is never charged: the hold lapses, the run reports
credits_charged: 0, and usage history shows it asunsettled. PollGET /v1/agents/runs/{run_id}until the run has finished to see its final status and cost. - Until a run settles,
credits_chargedisnull, not0.
Charged only when the answer is ready#
The rule in one sentence: a call is charged once its response is ready, for what it delivered.
The order of operations is: validate → resolve cursor → retrieve → build the response → charge. Validation, quota and retrieval errors are all returned before the charge, so they never cost anything — 401, 403, 422, 429, 502, 503 upstream.unavailable and 504 alike, and a request abandoned before its answer. The one exception is 503 credits.unavailable, below.
If your balance cannot cover what a call delivered, the call answers 402 credits.insufficient and the results are not returned. The 402 states what the call needed and what was available, both in credits.
The two retrieval failures you will see most often:
| Status | Code | Meaning |
|---|---|---|
| 503 | upstream.unavailable | The retrieval engine was unreachable. Not charged. Retry after Retry-After |
| 504 | upstream.timeout | The retrieval engine did not answer in time. Not charged. Retry after Retry-After |
Both carry Retry-After: 5. A 503 credits.unavailable is different: the billing system could not be reached, or did not confirm the charge in time, so the charge may or may not have landed. Retry with the same Idempotency-Key — if the first charge did land, the retry is recognised as already paid.
Your usage history lists every charged request as pending for the moment it takes to record, then ok or failed.
Credit expiry#
Free credits expire 90 days after they are granted. That covers the 1,000-credit signup grant, referral credits and promotional credits. Credits you buy never expire. GET /v1/credits shows your balance.
Actions#
Every charge is recorded under a named action, which is what GET /v1/keys/usage and your usage history group by. The set is closed:
| Action | Recorded for |
|---|---|
dsp.search.fast | POST /v1/search with mode: "fast" |
dsp.search.auto | POST /v1/search with mode: "auto" |
dsp.search.deep | POST /v1/search with mode: "deep" |
dsp.similar | POST /v1/similar |
dsp.entities | Every POST /v1/entities/* route |
dsp.relationships | POST /v1/relationships, /reach and /institutions |
dsp.relationships.ask | POST /v1/relationships/ask |
dsp.org_chart | POST /v1/org-chart, /departments and /locations |
dsp.agent.run.minimal … dsp.agent.run.xhigh | POST /v1/agents/runs, one action per effort. Automatic is recorded under dsp.agent.run.high |