Skip to main content

Quick Answer

How do I run an async person search from start to finish? Four calls: POST /search-jobs to submit, GET /search-jobs/{segment_id} to poll until completed, POST /search-jobs/{segment_id}/results once to unlock and bill the segment, then GET /search-jobs/{segment_id}/results to page the rest.Common questions this page answers:
  • When should I use async person search instead of the synchronous endpoint?
  • How do I know when my search is done?
  • How much will unlocking cost, and how do I check before I commit?
  • How do I retrieve more than 100 PIDs?
  • Why did I get a 409?
What you need: A user-associated API key and a natural-language audience description of 500 characters or fewer.What you get back: Every Minerva PID matching the query, paged 100 at a time, billed once for the net-new PIDs.

Overview

Synchronous Person Search returns up to 100 PIDs immediately and stops there. Async Person Search instead materializes the complete result set into a reusable segment, tells you exactly how large it is, and only charges you when you explicitly unlock it. That trade — waiting, in exchange for the full audience and a look at the price before you pay it — is the whole reason the async flow exists.
Use synchronous search to preview or prototype an audience. Switch to async once you want the whole thing.

Before you start

1

Use a user-associated API key

Organization-only API keys cannot create or read async person-search jobs and receive 401 Unauthorized on every endpoint in this flow. If you get a 401 with a key that works elsewhere, this is why.
2

Have credits available

Unlocking bills the segment’s net-new PIDs against the platform_records_under_management metric. Insufficient credits fail the unlock with 402 and return no PIDs.
3

Write the query as an audience description

Describe shared attributes (“Software engineers in Austin who previously worked at a public technology company”), not a specific named person. See Writing good queries for the attribute categories the parser handles well — they are identical for sync and async.

The flow at a glance

Steps 1, 2, 3 and 5 never bill. Step 4 is the only call that charges you.
POST /person-search/v0/search-jobs accepts the query and returns immediately with 202 Accepted. Parsing and materialization continue in the background.
202
Store the segment_id. It is the identifier for the job, the segment, and every subsequent call in this flow. The submit response contains no PIDs — that is the key difference from synchronous search.

Full endpoint reference

Request body, headers, and the complete error table for the submit call.

Step 2 — Poll until the segment is built

GET /person-search/v0/search-jobs/{segment_id} reports progress. Poll every 2–5 seconds until the status is terminal. Polling never unlocks PIDs and never bills.
The job walks forward through these states:
Stop polling on failed and cancelled, not just on completed. A retry loop that only checks for completed will spin forever on a failed job.
If the query could not be fully parsed, the status response carries error_criteria describing which criteria failed and suggested_search with a rephrased query worth trying instead.

Full endpoint reference

Every status field, the criteria tree shape, and completed-job statistics.

Step 3 — Review size and cost before unlocking

This is the step that makes the async flow worth using. Once status is completed, the status response tells you exactly what you are about to buy: estimated_billable_count normally equals total_count. The actual charge can come in lower, because PIDs your organization already unlocked this billing year are deduplicated and not charged twice.
The estimate covers the entire segment, not one page. Unlocking a 50,000-PID segment with limit=10 still considers all 50,000 PIDs for billing. limit controls the response size only — it is not a spending cap.
The stats block also lets you qualify the audience before paying for it — email, phone, and address coverage, plus age, gender, income, and location distributions. If coverage is too thin for your campaign, abandon the segment here and refine the query. Nothing has been charged yet.

Step 4 — Unlock the segment (this bills)

POST /person-search/v0/search-jobs/{segment_id}/results unlocks the full materialization, charges the net-new PIDs once, and returns your first page.
200
billable_count is the exact charge — here 1,207 net-new PIDs out of a 1,284 PID segment, because 77 were already under management. Unlock is idempotent. Repeating the POST does not charge the same materialization again.

Step 5 — Page through the remaining PIDs

After unlock, use GET on the same path for every subsequent page. GET is side-effect-free and never bills.
Each response returns at most 100 PIDs. Start at offset=0 and advance by returned until offset + returned >= total. The 100-PID cap applies to the HTTP response only, not to the segment — total reports the full count and you can page all of it.

Full endpoint reference

POST vs GET semantics, pagination parameters, and the complete error table.

Complete working example

The whole flow, end to end, with a cost check before the unlock:

Troubleshooting


What to do with the PIDs

Async person search returns Minerva PIDs only, with no person attributes attached. Take them somewhere next:

Enrich v2

Fetch full profile data — demographics, work history, contact channels — for the PIDs you unlocked.

Add Members to Segment

Persist the results into a segment you can track and activate.

Person Search Usage

Review daily delivery limits and consumption history.

Contact Append / Prospect

A separate async flow for ABM contacts at target companies.

Endpoint reference