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 limit re-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.unavailable means the billing system couldn't confirm the charge, so the request may have been charged. Retry with the same Idempotency-Key so 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#

Check affordability before a batch job

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.

Attribute spend across services

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.

Develop without spending

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#

Basic and AI search charge a base price that covers the first 10 results, then a price for each extra result.

CallFirst 10 resultsEach extra result
Basic search — POST /v1/search with mode: "fast"0.5 credits0.08 credits
AI search — POST /v1/search with mode: "auto"0.595 credits0.085 credits

Worked examples:

Results deliveredBasic searchAI search
1 to 100.50.595
110.580.68
251.71.87
503.73.995
1007.78.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

CallPrice
Find similar companies — POST /v1/similar2 credits for the first 10 results, then 1 credit per next 10
Relationships — POST /v1/relationships and POST /v1/relationships/reach2 credits for the first 10 results, then 1 credit per next 10
A relationship question in words — POST /v1/relationships/askThe relationships price above. A question answered by shared institutions is 2 credits flat
Shared institutions — POST /v1/relationships/institutions2 credits flat
Record lookup — every POST /v1/entities/* route1 credit per record found. Ids that come back found: false are free
Org chart — POST /v1/org-chart, /departments and /locations1 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.

An agent run (POST /v1/agents/runs) is priced per run by its effort level, whatever the number of results.

EffortCredits per run
Quick — minimal1.02
Basic — low2.125
Standard — medium8.5
Detailed — high42.5
Maximum — xhigh85
Automatic — autoThe 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/usage
  • GET /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 first GET /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/intents and GET /v1/billing/top-up/intents/{topup_id}
  • The feedback routes: POST /v1/feedback, GET /v1/feedback, GET /v1/feedback/tags, GET and PUT /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_cursor you 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 limit re-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 as unsettled. Poll GET /v1/agents/runs/{run_id} until the run has finished to see its final status and cost.
  • Until a run settles, credits_charged is null, not 0.

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:

StatusCodeMeaning
503upstream.unavailableThe retrieval engine was unreachable. Not charged. Retry after Retry-After
504upstream.timeoutThe 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:

ActionRecorded for
dsp.search.fastPOST /v1/search with mode: "fast"
dsp.search.autoPOST /v1/search with mode: "auto"
dsp.search.deepPOST /v1/search with mode: "deep"
dsp.similarPOST /v1/similar
dsp.entitiesEvery POST /v1/entities/* route
dsp.relationshipsPOST /v1/relationships, /reach and /institutions
dsp.relationships.askPOST /v1/relationships/ask
dsp.org_chartPOST /v1/org-chart, /departments and /locations
dsp.agent.run.minimal … dsp.agent.run.xhighPOST /v1/agents/runs, one action per effort. Automatic is recorded under dsp.agent.run.high

More on credits & usage#