Documentation
OneFind
OneFind turns a description of people, or a list of identifiers, into rows: name, title, company, location, LinkedIn, email, phone. Two endpoints share one row format. vaaya/onefind finds people for a flat 2 cents. vaaya/onefind-deep finds and enriches, or enriches a batch you already have, and charges only for fields that fill.
Endpoints
| Endpoint | What it does | Price | Mode |
|---|---|---|---|
POST /api/run/vaaya/onefind | Find people from a query. No contact data. | 2 cents per call | sync |
POST /api/run/vaaya/onefind-deep | Find and enrich, or enrich a list of identifiers. | per filled field, capped by a budget | async |
Both take a JSON body and a bearer API key. Both return the same row format, described below.
OneFind returns people only. To find companies, use the company vendors on the GTM page.
Find people
Send a plain-English description. Get back up to 25 rows without contact data.
curl -X POST https://vaaya.ai/api/run/vaaya/onefind \
-H "Authorization: Bearer $VAAYA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "heads of growth at B2B SaaS companies in Berlin", "limit": 15}'Request
| Field | Type | Required | Description |
|---|---|---|---|
query | string | yes | Who you want. A description (role, industry, place, company type) or one person by name and company. |
limit | integer | no | 1 to 25. Default 15. |
Response
{
"ok": true,
"data": {
"query": "heads of growth at B2B SaaS companies in Berlin",
"person": false,
"row_count": 15,
"enriched": false,
"rows": [
{
"id": "https://www.linkedin.com/in/example",
"name": "Jane Doe",
"title": "Head of Growth",
"company": "Example GmbH",
"location": "Berlin, Germany",
"linkedin": "https://www.linkedin.com/in/example",
"email": null,
"phone": null,
"domain": null,
"industry": null,
"headcount": null,
"hq": null,
"sources": { "name": "exa", "title": "exa", "company": "exa", "location": "exa", "linkedin": "exa" },
"enriched": false,
"hops": [],
"charged_cents": 0
}
],
"calls": [{ "service": "exa", "action": "search", "ok": true, "latency_ms": 812 }],
"next": "To add emails and phones, call onefind-deep ..."
},
"charged_cents": 2
}If query names one person, for example "Jerry Liu LlamaIndex", the response has person: true and one row. If it describes a group, person is false and rows is a list to choose from.
An email address or LinkedIn URL as query returns a 400 and is not charged. Those identify one person and belong to onefind-deep.
Find and enrich
Send a query to find people and enrich every row, or send rows to enrich identifiers you already have. The call returns a job_id. Poll it until the job finishes.
curl -X POST https://vaaya.ai/api/run/vaaya/onefind-deep \
-H "Authorization: Bearer $VAAYA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "VP Engineering at fintech companies in London", "limit": 10, "budgetCents": 160}'curl -X POST https://vaaya.ai/api/run/vaaya/onefind-deep \
-H "Authorization: Bearer $VAAYA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"rows": ["satya@microsoft.com", "linkedin.com/in/satyanadella", "Jerry Liu LlamaIndex"]}'Request
| Field | Type | Required | Description |
|---|---|---|---|
query | string | one of query / rows | Find people, then enrich each row. A query that names one person enriches only that person. |
rows | string[] | one of query / rows | 1 to 50 identifiers. Each is an email, a LinkedIn URL, or a name with a company. |
limit | integer | no | Rows to find when using query. 1 to 25. Default 15. |
budgetCents | integer | no | Most you will pay, 10 to 500. Default is 16 cents per row. The job holds this amount until it finishes. |
Response
{
"ok": true,
"data": {
"job_id": "7c1d0f6e-...",
"status": "queued",
"async": true
},
"charged_cents": 0
}Poll the job
Call result with the job_id until status is succeeded or failed. Jobs usually finish within a minute or two.
curl -X POST https://vaaya.ai/api/run/vaaya/result \
-H "Authorization: Bearer $VAAYA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id": "7c1d0f6e-..."}'{
"ok": true,
"job_id": "7c1d0f6e-...",
"status": "succeeded",
"result": {
"query": "VP Engineering at fintech companies in London",
"row_count": 10,
"enriched_count": 10,
"skipped_count": 0,
"stats": { "emails": 7, "phones": 2 },
"rows": [ ... ],
"spent_cents": 84,
"budget_cents": 160,
"find": { "service": "exa", "action": "search", "ok": true, "latency_ms": 790 }
},
"charged_cents": 84
}Row format
Every row has the same fields in both endpoints.
| Field | Type | Description |
|---|---|---|
id | string | The LinkedIn URL when known, otherwise the input. |
input | string | The identifier this row came from. Present in rows mode. |
name, title, company, location, linkedin | string or null | Filled by the find. Enrichment can overwrite them. |
email, phone | string or null | Filled by enrichment only. |
domain, industry, headcount, hq | string or null | About the company. Filled by enrichment. |
sources | object | Which vendor supplied each filled field: exa, contactout, tomba, or input. |
enriched | boolean | Whether enrichment ran on this row. |
hops | array | Vendor calls made for this row. Each has provider, action, ok, charged_cents, latency_ms, and skipped when the call was not made. |
charged_cents | integer | What this row cost. |
error | string | Set when the row could not be resolved. "over budget" means the budget ran out before this row started. |
Reading a null
email: nullwithenriched: false. Not looked up. Callonefind-deepto fill it.email: nullwithenriched: true. Looked up. No vendor had it.
Pricing
onefind: 2 cents per call, anylimit.onefind-deep: you pay the price of each vendor call that returned data. ContactOut is 10 cents, Tomba is 4 to 5 cents, the Exa lookup is 1 cent. Calls that return nothing are free.- The job holds
budgetCents(or 16 cents per row) when it starts and releases what it did not spend when it finishes. - Rows the budget could not cover are returned with
error: "over budget". RaisebudgetCentsor lowerlimit. - A job that finds nobody is failed and charged 0.
How rows are enriched
Each row goes through a fixed order of vendors. The order comes from measured hit rates, not list prices.
| Input | First | Then |
|---|---|---|
contactout/person-from-email (10 cents, free on a miss) | tomba/enrich (4 cents). Skipped for webmail addresses. | |
| LinkedIn URL | contactout/linkedin-contacts (10 cents) | tomba/linkedin-finder (5 cents) |
| name and company | exa/search (1 cent) to find the profile | then the LinkedIn URL order above |
Errors
| Status | Error | Meaning |
|---|---|---|
| 400 | bad_request | Invalid body. onefind-deep needs exactly one of query or rows. |
| 400 | onefind_identifier | onefind got an email, LinkedIn URL, or phone number as query. Use onefind-deep. |
| 402 | credits_required | Balance is below the budget the job would hold. Add credit, lower limit, or set a smaller budgetCents. |
| 429 | too_many_inflight | Three onefind-deep jobs are already running on this account. |
| 502 | no_people | The search found nobody. Not charged. |
Related
- SuperSearch answers questions. OneFind returns people.
- GTM & leads lists the individual vendors, including filters OneFind does not expose and company search.