search— a query over a population. Filters in, candidates out. “Who exists that matches this?”enrich— a lookup of one known entity. An identifier in, that person’s record out. “I already have this lead, fill in the rest.”
CLI first
Operations
Both endpoints bill 3× the provider spend the request actually incurred, read off the run
rather than set as a per-record list price — which also removes an arbitrage the old prices
had, where the same work email cost 8 credits via search or 20 via enrich.
- An empty result is still billed, including a no-match enrich, because the run happened
and we are invoiced for it. The 404 reports the charge in
credits_used. - A failed run is never billed.
- Non-zero charges have a 0.1-credit minimum, so a run under $0.0017 bills 0.1.
- Every charge records
provider_usd, its basis (actualorprojected) and the multiplier, all returned byGET /v1/usage— so a bill can be recomputed rather than trusted.
search
Billed on what the run cost, so a largerlimit costs more because it is more provider work
— not because a list price was multiplied by rows.
title, company, industry, geo, seniority — at least one is required,
and a request with none is refused before any provider run. Keys outside that set are not
read, so check your spelling: a mistyped filter is a broader, billable search.
There is no name filter — searching by person name is not an expressible query. Use
enrich with a name plus a company instead.
seniority has no native provider input; it is folded into the title terms and re-checked on
the returned rows, and empty records and duplicates are dropped. That narrows what you
receive, not the bill — the provider charged for the rows it returned.
limit caps at 50. Above that, use POST /v1/people/tasks.enrich
One identity in, one record out. A no-match returns 404 carrying the charge incredits_used — establishing that someone is absent from the dataset costs a provider run,
so it is billed like any other; you
are not charged for a miss.
The request contract is deliberately wider than what the current provider resolves, so a
caller’s stored identity does not become invalid when the provider changes. An identity
that cannot be resolved is refused with a hint naming the ones that can — never answered
with an empty result.
Email deliverability is reported, not assumed
Withinclude_contact, the response carries email_verification alongside the record:
mailbox_verified is true only when a mailbox was actually probed and null when it was
not — domain_only is the common case, because a catch-all domain accepts any local part,
so the address existing proves little. A work email that could not be verified is returned
labelled, never dropped and never passed off as verified.
An address is also frequently just absent: the provider finds one or it does not, and an
absent email is absent rather than a placeholder.
If the verification provider fails at the account level — a bad token, a suspended plan
— the call errors. It does not answer unverified, because a lapsed credential would
otherwise degrade every response to plausible-looking unverified data forever.
What this returns — and what it never will
Work details only: employer, title, LinkedIn URL, firmographics, and — withinclude_contact — a work email. It does not return a home address, a personal phone
number, date of birth, or consumer attributes.
Two fields sit on the response schema and are never populated today:
phone— a policy choice, not a provider gap. Person-level phone numbers are personal numbers, which the B2B boundary withholds. Kept on the schema so adding a confirmed work-phone source later is not a breaking change.match_likelihood— the current provider returns a profile or nothing and scores neither. Kept for a provider that does score matches.
Batch
POST /v1/people/tasks accepts up to PRIMITIVE_BATCH_MAX identities (1,000 by default),
queues a job, and returns 202. Poll GET /v1/people/tasks/{id}.
Worst-case credits are held at submit and settled against the records actually matched, so
unmatched rows are refunded. The tally reports unmatched, invalid and failed as three
separate numbers — collapsing them would tell a caller whose provider is rate-limiting
that none of their 1,000 leads exist, which is a confident, actionable, wrong answer.
If more than half the records fail outright at the provider the whole job fails with
the first error attached, rather than returning a mostly-empty result that reads like a
successful run. A worker that dies mid-job loses its lease after 15 minutes and the job is
requeued, up to three attempts.
Retries and double-charging
Send anIdempotency-Key header on search and enrich. It deduplicates the response
and becomes the credit-ledger reference, so a retried call cannot be charged twice.
Without one, a retry after a dropped connection is a second billable lookup.
Acceptable use
Governed by Terms of Service Section 18, which every customer accepts.GET /v1/people/terms returns the same prohibitions as JSON, so an agent can read them
without opening a web page.
This data is not a consumer report under the FCRA or any state analogue. You may not
use it to make or inform decisions about:
- Employment — recruitment, promotion, retention
- Credit eligibility or terms
- Insurance underwriting or pricing
- Housing or tenant screening
Retention and erasure
- Sync
searchandenrichstore nothing. Records are normalized, returned, dropped. - Async batches are the only store, pruned automatically at 90 days.
- The audit log records who ran a lookup, not who was looked up.
Enabling the primitive
people is registered optIn: true, so it is disabled on a fresh workspace and an absent
AccountKit entry denies. Enable it in the AccountKit’s primitives_config (dashboard →
Account Kits, or the kit’s people: { enabled: true }).
A refusal names which gate fired: subprocessor_consent_required means the primitive has
never been enabled, primitive_disabled_by_kit means somebody turned it off. MCP callers
meet the same gate — naive_people_* is refused under exactly the conditions
/v1/people/* is.
Related
- Company Data — the employer, rather than the person
- Social Data — public posts and comments
- Reviews — reviews and local listings (the
businessprimitive, “Reviews & Listings”) - Data primitive status — what is verified live and what is not