search_id. These endpoints read its results: poll a task with GET /search/status/{task_id}, page through rows with POST /search/query, build a CSV with POST /search/export, download it with GET /search/download, and read your result ceiling with GET /search/limits.
API Reference
See the full request/response schema and parameters in the API Reference.
Get search status
Poll the progress and result of a deep search or an export.task_id is the value returned by Start Deep Search (agentic_search_{search_id}) or by Export (search_export_{search_id}). Lookalike tasks use GET /search/lookalike/{task_id}; this endpoint refuses them.
GET /search/deep-search-status/{task_id} is a deprecated alias of this endpoint, past its May 12, 2026 sunset date. It still returns the same response, with Deprecation and Sunset headers.
Task statuses
running is the only in-progress status. Poll every 10 seconds or slower, and stop on any other status, including values not listed here.
A search that finds nothing does not always end completed:
- A
query_onlydeep search with no matches endscompletedwithtotal_results: 0. - A CSV deep search or an export with no rows to write ends
failed, with a message inerror. This includes searches whose every row was excluded.
failed. See Concurrency and run time.
Status response
Fields without a value are returned as
null.
Retry-After and stops at a deadline, see Deep Search → Example usage.
Query search results
Page through the results of a completed search as JSON.search_id on the first request, then send only {"cursor": "..."} for each next page:
POST /search/query also runs new searches from filters or a natural language query. For those inputs, see Filter Search → Search query.
Replay a saved search
A request withsearch_id runs the saved search’s query again and starts a new set of pages under the same search_id.
A replay carries:
- The saved query and its mode.
- For a lookalike search, its ranking and its seed people, who stay excluded from results.
max_results. It defaults to 1,000 for API keys, whatever the original search used. Send it again.page_size,output_shape, and exclusions. Send them on the first request.
completed. Replaying a search that is still running, or one that failed, returns an error. A replay does not save a new search.
Paginate with cursors
Each page returnshas_more and, while more rows remain, a next_cursor. Send {"cursor": "..."} alone to get the next page. Mode, page size, output shape, and exclusions carry over.
- Stop when
has_moreisfalse. The last page omitsnext_cursorandcursor_expires_in_seconds; they are not returned asnull. - A page can hold fewer rows than
page_size, even zero, whilehas_moreistrue. Keep paging. - Each cursor works once. Sending a cursor again after its page was served fails with
Cursor expired. Start a new search. - Send each cursor only after the previous response arrives. While a request with a cursor is still running, a second request with the same cursor returns
409. - A cursor expires
cursor_expires_in_secondsafter it is issued (30 minutes). It stops working sooner if an exclusion list it applies is deleted, and it can expire early in other cases. When a cursor fails, start again from thesearch_id. - If a cursor request returns
429or503, wait forRetry-Afterand send the same cursor again. If that fails withCursor expired, start again from thesearch_id. - A cursor request accepts only
cursor. Sending a query, paging, or exclusion field with it fails the request.mode,persist_history, and the location-expansion fields are ignored, as are fields sent asnullorfalse. - A cursor works only for the organization that created it.
Query response
Fields without a value are omitted from the response, not returned as
null. Inside results, rows keep their null values.
Fields that change what results mean
Check these fields on every page. When present, the results do not cover everything the query asked for.
Results and fields differ by account, and these fields appear only on some accounts.
GET /search/filter-capabilities lists the fields your account can filter on.
Example: page through a search
Export search results
Generate a CSV from any completed search: deep, filter, or lookalike.
An export runs the saved query again, as a replay does, so its rows can differ from the CSV a deep search wrote.
- Call
POST /search/exportand save thetask_id. - Poll
GET /search/status/{task_id}until it iscompleted, then readresource_handle_id. - Download the CSV with
GET /search/download.
search_id runs at a time. While one runs, another export request for the same search fails; poll search_export_{search_id} instead. An export with parsed_query gets a new ID each time.
CSV columns
A CSV has one row per result, with the same columns asoutput_shape: "workflow" rows.
On accounts where lookalike results carry ranking fields, lookalike CSVs add
similarityScore (0–100), similarityRank, and similaritySignals.
Download search results
Get a signed URL for the CSV of a completed CSV deep search or export.url plus the storage bucket and path of the file.
Fetch the returned
url with your x-api-key header; the signed token does not replace authentication. Disable redirects when sending your API key.Spreadsheet-safe CSV
By default, the file is escaped so that opening it in a spreadsheet never runs a formula:- Every field is quoted.
- A cell that starts with
=,+,-,@, a tab, or a line break (or a full-width=,+,-, or@) gets a leading'. A phone number+14155550123arrives as'+14155550123. Negative numbers such as-12.5are left as they are. - The response carries the header
X-Spreadsheet-Safe: 1.
?spreadsheet_safe=false to the url. The file then arrives exactly as stored, without the header. A file that cannot be escaped, because it is not valid CSV or is too large to escape, is refused by default and downloads with ?spreadsheet_safe=false.
Search limits
Return the maximum number of results your credential can request, retrieve, or export in one search.max_results on POST /search/start-deep-search, POST /search/query, and POST /search/export; a higher value fails the request.
Rate limits
For per-endpoint limits, see Rate Limits. File downloads from the signedurl share one budget with other file downloads; see Limits by endpoint.