Contacts API
The Contact Finder service lets you search a B2B warehouse, reveal contact PII, verify deliverability, enrich records, run bulk discovery, and look up companies. All routes are served under /v1/contacts.
Authentication
Every request must carry a tenant API key as a Bearer token:
Authorization: Bearer ai92_live_<key> # production
Authorization: Bearer ai92_test_<key> # sandboxOAuth 2.0 access tokens (Authorization: Bearer eyJ…) are also accepted. Mutating requests support the Idempotency-Key header.
Credit costs at a glance
| Endpoint | Cost |
|---|---|
GET /v1/contacts/search | Free |
POST /v1/contacts/reveal | 3 cr (email) / 5 cr (email+phone) |
POST /v1/contacts/verify | 1 cr (free if inconclusive) |
POST /v1/contacts/enrich | 5 cr |
POST /v1/contacts/bulk | 300 cr per 100 (rounded up) |
GET /v1/contacts/{company_id} | 2 cr |
GET /v1/contacts/search
Cost: Free
Free warehouse search across the contact database, scoped to a brand.
Auth: Bearer (tenant key or OAuth token)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
brand_id | query | string | No | Restrict results to a brand. Verified against the account. |
tags | query | string | No | Comma-separated tag filter. |
email | query | string | No | Filter by exact email. |
limit | query | integer | No | Page size. Default 50. |
offset | query | integer | No | Page offset. Default 0. |
Request
curl https://api.ai92.ai/v1/contacts/search?brand_id=acme&limit=25 \
-H "Authorization: Bearer ai92_live_51a9c0de…"Response 200 OK
{
"total": 1284,
"limit": 25,
"offset": 0,
"contacts": [
{
"id": "3f2b91c4-7d0e-4a15-9c83-1b6e5a0d2f47",
"person_id": "3f2b91c4-7d0e-4a15-9c83-1b6e5a0d2f47",
"full_name": "Jordan Vega",
"title": "VP Marketing",
"company": "Acme Corp",
"company_id": "8c1d4e77-2a90-4f63-b5aa-90c7e2f18d31",
"tags": ["decision-maker", "saas"]
}
]
}The identifier is id; person_id is an alias search adds for convenience. Both are UUIDs — pass either one to reveal or enrich, and company_id to GET /v1/contacts/{company_id}. Sandbox keys return short mock ids (p_mock_001) instead, which are accepted only in sandbox.
POST /v1/contacts/reveal
Cost: 3 credits (mode=email) · 5 credits (mode=email_phone)
Reveal a contact's PII by person_id. email mode returns the email only; email_phone adds phone. Credits are deducted only after a successful reveal.
Auth: Bearer
| Field | Type | Required | Description |
|---|---|---|---|
person_id | string | Yes | The warehouse person id to reveal. |
mode | string | No | email (default, 3 cr) or email_phone (5 cr). |
include_phone | boolean | No | Legacy alias for mode=email_phone. Default false. |
Request
curl https://api.ai92.ai/v1/contacts/reveal \
-H "Authorization: Bearer ai92_live_51a9c0de…" \
-H "Content-Type: application/json" \
-d '{"person_id": "3f2b91c4-7d0e-4a15-9c83-1b6e5a0d2f47", "mode": "email_phone"}'Response 200 OK
{
"id": "3f2b91c4-7d0e-4a15-9c83-1b6e5a0d2f47",
"full_name": "Jordan Vega",
"title": "VP Marketing",
"company": "Acme Corp",
"email": "[email protected]",
"emails": ["[email protected]"],
"phones": ["+1-415-555-0173"]
}Errors
| Status | Code | When |
|---|---|---|
422 | INVALID_REVEAL_MODE | mode is not email or email_phone. |
422 | INVALID_PERSON_ID | person_id is not a contact UUID from search. |
402 | INSUFFICIENT_CREDITS | Balance below the reveal cost. |
POST /v1/contacts/verify
Cost: 1 credit — free when the verdict is inconclusive (status=unknown)
Email deliverability check via a third-party verification provider. Charged 1 credit only for a definitive verdict.
Auth: Bearer
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | The email address to verify. |
Request
curl https://api.ai92.ai/v1/contacts/verify \
-H "Authorization: Bearer ai92_live_51a9c0de…" \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]"}'Response 200 OK
{
"email": "[email protected]",
"status": "deliverable",
"sub_status": "none",
"credits_consumed": 1
}When the verdict is inconclusive, status is "unknown" and credits_consumed is 0.
Errors
| Status | Code | When |
|---|---|---|
402 | INSUFFICIENT_CREDITS | Balance below 1 credit. |
POST /v1/contacts/enrich
Cost: 5 credits
Returns the full contact record for a person_id: identity, job title, company, and every email and phone address held for that contact. Enrichment is the unlocked view of a record you already located with the free search.
What
enrichreturns today. It returns the same record asPOST /revealwithmode: "email_phone", at the same price (5 credits). Firmographic fields — company size, industry, social profiles — are not part of the response yet; this page will be updated when they ship. If you only need the email address,POST /revealwithmode: "email"costs 3.
Auth: Bearer
| Field | Type | Required | Description |
|---|---|---|---|
person_id | string | Yes | The contact UUID from GET /v1/contacts/search (returned as id, and echoed as person_id). A non-UUID value is rejected upstream. |
fields | string[] | No | Accepted for forward compatibility but not yet honoured — the full record is always returned. |
Request
curl https://api.ai92.ai/v1/contacts/enrich \
-H "Authorization: Bearer ai92_live_51a9c0de…" \
-H "Content-Type: application/json" \
-d '{"person_id": "3f2b91c4-7d0e-4a15-9c83-1b6e5a0d2f47"}'Response 200 OK
{
"id": "3f2b91c4-7d0e-4a15-9c83-1b6e5a0d2f47",
"name": "Jordan Vega",
"full_name": "Jordan Vega",
"first_name": "Jordan",
"last_name": "Vega",
"title": "VP Marketing",
"company": "Acme Corp",
"company_id": "8c1d4e77-2a90-4f63-b5aa-90c7e2f18d31",
"email": "[email protected]",
"emails": ["[email protected]"],
"phones": ["+1-415-555-0173"],
"tags": ["decision-maker", "saas"],
"source": "public-registry",
"created_at": "2026-05-12T09:14:22Z"
}The identifier field is id. Phone numbers are returned in the phones array — there is no scalar phone field.
Sandbox returns a simplified fixture, not this shape. With an
ai92_test_key/enrichanswers withperson_id, a scalarphone,job_titleinstead oftitle, andcompanyas an object. Use the sandbox to exercise auth, errors and wiring — read the production shape from this page, not from the fixture.
Errors
| Status | Code | When |
|---|---|---|
402 | INSUFFICIENT_CREDITS | Balance below 5 credits. |
422 | — | person_id is not a contact UUID from search. |
POST /v1/contacts/bulk
Cost: 300 credits per 100 requested records (rounded up per 100)
Bulk contact discovery. filters must include the discovery keys the backend requires (e.g. vertical, geography). Cost = ceil(limit / 100) * 300.
Auth: Bearer
| Field | Type | Required | Description |
|---|---|---|---|
filters | object | Yes | Discovery filter keys (e.g. vertical, geography). |
limit | integer | No | Records to discover. Default 100. Range 10–10000. |
Request
curl https://api.ai92.ai/v1/contacts/bulk \
-H "Authorization: Bearer ai92_live_51a9c0de…" \
-H "Content-Type: application/json" \
-d '{"filters": {"vertical": "fintech", "geography": "US"}, "limit": 200}'Response 200 OK
{
"discovered": 200,
"contacts": [
{ "person_id": "p_aa01", "full_name": "Lee Park", "title": "CFO", "company": "Northwind" }
],
"credits_charged": 600
}Errors
| Status | Code | When |
|---|---|---|
402 | INSUFFICIENT_CREDITS | Balance below the computed cost. |
GET /v1/contacts/{company_id}
Cost: 2 credits
Look up a company by id from the contact warehouse.
Auth: Bearer
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
company_id | path | string | Yes | Warehouse company id. |
Request
curl https://api.ai92.ai/v1/contacts/co_4521 \
-H "Authorization: Bearer ai92_live_51a9c0de…"Response 200 OK
{
"company_id": "co_4521",
"name": "Acme Corp",
"domain": "acme.com",
"industry": "Software",
"employee_count": 420,
"hq_location": "San Francisco, CA"
}Errors
| Status | Code | When |
|---|---|---|
402 | INSUFFICIENT_CREDITS | Balance below 2 credits. |