- Format: OpenAPI 3.1, YAML
- Base URL:
https://api.avina.io/v1 - Authentication: bearer token, a workspace API key
Use the copy button on the code block to copy the whole specification.
openapi.yaml
openapi: 3.1.0
info:
title: Avina Data API
version: "1.0"
summary: Search companies and people across B2B data providers, with evidence for every match.
description: |
The Avina Data API finds companies and people that match a natural-language request or
structured filters. Searches run asynchronously: start one, poll its status, and page
through results as they are found. Every result lists the criteria it matched and the
evidence for each.
Conventions: JSON bodies with snake_case fields, UTC ISO 8601 timestamps, bearer
authentication with a workspace API key, and one error shape for every failure.
contact:
name: Avina support
email: support@avina.io
url: https://docs.data.avina.io
servers:
- url: https://api.avina.io/v1
description: Production
security:
- bearerAuth: []
tags:
- name: Companies
description: Find companies that match a request, with evidence for each match.
- name: People
description: Find people by role, seniority and employer.
- name: Parse
description: Turn natural language into structured filters and criteria without searching.
- name: Personas
description: Saved contact-targeting settings used to find people at matching companies.
- name: Account
description: Check an API key and read the workspace's credit balance.
paths:
/companies/search:
post:
tags: [Companies]
operationId: startCompanySearch
summary: Start a company search
description: |
Starts a search for companies that match a natural-language `query`, or structured
`filters` and `criteria`. Returns `202` immediately with the search's `id`; the search
runs in the background.
x-docs:
slug: api-reference/companies/search
sidebarTitle: Start a search
intro: |
Send either `query`, or `filters` and/or `criteria`. Every requirement is checked for each company, and only companies that match all of them are returned.
The search runs in the background. Poll [`GET /companies/search/{search_id}/status`](/api-reference/companies/get-search) and read companies from [`GET /companies/search/{search_id}/results`](/api-reference/companies/list-results) as they are found.
<Warning>
Starting a search spends credits as companies are found. Reading status and results is free. Set `max_credits` to cap what one search can spend. See [Pricing](/concepts/pricing).
</Warning>
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CompanySearchCreate'
examples:
query:
summary: Natural language
value:
query: Privately held dental practices in Texas hiring SDRs
limit: 20
filters:
summary: Structured filters
value:
filters:
all:
- field: company.headquarters.country
operator: in
value: [US]
- field: company.employee_count
operator: between
value: [10, 200]
- related:
relationship: open_jobs
where:
all:
- field: title
operator: in
value: [Sales Development Representative, SDR]
criteria:
- independently owned, not part of a dental support organization
limit: 20
max_credits: 25
personas:
summary: With contacts
value:
query: Series B fintech companies in New York
limit: 10
persona_ids: [c92d77d7-cc85-4a62-bcec-518b1d7d6260]
responses:
'202':
description: The search was accepted and queued.
content:
application/json:
schema:
$ref: '#/components/schemas/Search'
example:
object: company_search
id: 32ba40da-e558-442a-8945-e93fc771afc9
status: queued
stop_reason: null
error: null
query: Privately held dental practices in Texas hiring SDRs
limit: 20
interpretation: null
assumptions: []
progress: { candidates: 0, accepted: 0, rejected: 0, unknown: 0, not_returned: 0, contacts_found: 0 }
credits_charged: 0
cancel_requested: false
created_at: '2026-11-12T17:02:11Z'
completed_at: null
expires_at: null
status_url: https://api.avina.io/v1/companies/search/32ba40da-e558-442a-8945-e93fc771afc9/status
results_url: https://api.avina.io/v1/companies/search/32ba40da-e558-442a-8945-e93fc771afc9/results
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'402': { $ref: '#/components/responses/UsageLimitReached' }
'403': { $ref: '#/components/responses/PermissionDenied' }
'409': { $ref: '#/components/responses/IdempotencyKeyReused' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/companies/search/{search_id}/status:
get:
tags: [Companies]
operationId: getCompanySearch
summary: Get a company search
description: Returns a company search's status, progress and spend. Reading it is free.
x-docs:
slug: api-reference/companies/get-search
sidebarTitle: Get search status
intro: |
Poll this endpoint until `status` is `completed`, `failed` or `cancelled`. Start at 2 seconds between polls and back off to 10. See [Search lifecycle](/concepts/search-lifecycle) for what each status and `stop_reason` means.
parameters:
- $ref: '#/components/parameters/SearchId'
responses:
'200':
description: The search.
content:
application/json:
schema:
$ref: '#/components/schemas/Search'
example:
object: company_search
id: 32ba40da-e558-442a-8945-e93fc771afc9
status: running
stop_reason: null
error: null
query: Privately held dental practices in Texas hiring SDRs
limit: 20
interpretation:
filters:
all:
- { field: company.industry, operator: in, value: [Dentists] }
- { field: company.business_description, operator: matches, value: dental practices }
- { field: company.headquarters.state, operator: in, value: [Texas] }
- { field: company.type, operator: in, value: [Privately Held] }
- related:
relationship: open_jobs
where:
all:
- { field: title, operator: in, value: [Sales Development Representative, SDR] }
criteria: []
unsupported_criteria: []
assumptions: []
progress: { candidates: 40, accepted: 6, rejected: 31, unknown: 3, not_returned: 0, contacts_found: 0 }
credits_charged: 2.94
cancel_requested: false
created_at: '2026-11-12T17:02:11Z'
completed_at: null
expires_at: null
status_url: https://api.avina.io/v1/companies/search/32ba40da-e558-442a-8945-e93fc771afc9/status
results_url: https://api.avina.io/v1/companies/search/32ba40da-e558-442a-8945-e93fc771afc9/results
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/companies/search/{search_id}/results:
get:
tags: [Companies]
operationId: listCompanySearchResults
summary: List company search results
description: Returns the companies a search has found, in the order they were found. Available while the search is still running. Reading results is free.
x-docs:
slug: api-reference/companies/list-results
sidebarTitle: List results
intro: |
Results are only ever added, never changed or removed. Store `next_cursor` and pass it as `after` to read only the companies found since your last call. `next_cursor` is always returned, even on an empty page.
`has_more: false` means there are no more stored results right now. It does not mean the search has finished: check `search_status`.
parameters:
- $ref: '#/components/parameters/SearchId'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/After'
responses:
'200':
description: A page of companies.
content:
application/json:
schema:
$ref: '#/components/schemas/CompanyResultList'
example:
object: list
data:
- object: company_search_result
result_id: res_8Zk2Qm4vT1
domain: lakeviewdental.example
name: Lakeview Dental Group
description: Family dentistry with four locations in the Austin area.
industries: [Dentists]
headquarters: { country: US, state: Texas, city: Austin }
employee_count: { low: 51, high: 200 }
annual_revenue_usd: null
total_funding_usd: null
last_funding: { date: null, round: null }
company_type: Privately Held
founded_year: 1998
linkedin_url: https://www.linkedin.com/company/lakeview-dental-example
matched_criteria:
- criterion: company.industry
verdict: matched
evidence:
summary: 'Industry: Dentists'
sources: []
items: []
- criterion: company.business_description
verdict: matched
evidence:
summary: '"Family dentistry with four locations in the Austin area."'
sources: [https://lakeviewdental.example/about]
items: []
- criterion: company.headquarters.state
verdict: matched
evidence:
summary: 'Headquarters state: Texas'
sources: []
items: []
- criterion: company.type
verdict: matched
evidence:
summary: 'Company type: Privately Held'
sources: []
items: []
- criterion: open_jobs
verdict: matched
evidence:
summary: 1 open job matches.
sources: [https://lakeviewdental.example/careers/sdr]
items:
- type: job
title: Sales Development Representative
posted_at: '2026-10-29'
location: Austin, TX
url: https://lakeviewdental.example/careers/sdr
contacts: []
contact_status: not_requested
found_at: '2026-11-12T17:03:40Z'
has_more: false
next_cursor: '1'
search_status: running
'400': { $ref: '#/components/responses/BadRequestCursor' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/companies/search/{search_id}/cancel:
post:
tags: [Companies]
operationId: cancelCompanySearch
summary: Cancel a company search
description: Stops a company search from starting new work. Results found so far stay readable.
x-docs:
slug: api-reference/companies/cancel-search
sidebarTitle: Cancel a search
intro: |
Cancelling stops the search from starting new work. Provider calls already in progress may finish, add results and be charged. The search reaches `status: cancelled` once that work has finished.
Cancelling a search that has already finished returns it unchanged. Cancelling twice costs nothing.
<Note>
A client timeout or a closed connection does not cancel a search. Call this endpoint to stop spending.
</Note>
parameters:
- $ref: '#/components/parameters/SearchId'
responses:
'202':
description: Cancellation was requested. Work already in progress is finishing.
content:
application/json:
schema:
$ref: '#/components/schemas/Search'
example:
object: company_search
id: 32ba40da-e558-442a-8945-e93fc771afc9
status: running
stop_reason: null
error: null
query: Privately held dental practices in Texas hiring SDRs
limit: 20
interpretation:
filters:
all:
- { field: company.industry, operator: in, value: [Dentists] }
- { field: company.business_description, operator: matches, value: dental practices }
- { field: company.headquarters.state, operator: in, value: [Texas] }
- { field: company.type, operator: in, value: [Privately Held] }
- related:
relationship: open_jobs
where:
all:
- { field: title, operator: in, value: [Sales Development Representative, SDR] }
criteria: []
unsupported_criteria: []
assumptions: []
progress: { candidates: 40, accepted: 6, rejected: 31, unknown: 3, not_returned: 0, contacts_found: 0 }
credits_charged: 2.94
cancel_requested: true
created_at: '2026-11-12T17:02:11Z'
completed_at: null
expires_at: null
status_url: https://api.avina.io/v1/companies/search/32ba40da-e558-442a-8945-e93fc771afc9/status
results_url: https://api.avina.io/v1/companies/search/32ba40da-e558-442a-8945-e93fc771afc9/results
'200':
description: The search had already finished. It is returned unchanged.
content:
application/json:
schema:
$ref: '#/components/schemas/Search'
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/companies/search/parse:
post:
tags: [Parse]
operationId: parseCompanySearch
summary: Parse a company query
description: Turns a natural-language request into the structured `filters` and `criteria` a company search takes, without searching. Free.
x-docs:
slug: api-reference/parse/companies
sidebarTitle: Parse a company query
intro: |
Use Parse to show users how their request was understood, let them edit it, or build a filter UI on top of natural language.
When nothing blocks the search, `search_request` is a ready body for [`POST /companies/search`](/api-reference/companies/search): send it as-is, or edit it first. Otherwise `search_request` is `null`, and `unsupported_criteria` or `errors` say what to change.
Parse runs no search and spends no credits.
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ParseRequest'
examples:
default:
summary: Parse
value:
query: Private dental practices in Texas hiring SDRs
responses:
'200':
description: How the query was read.
content:
application/json:
schema:
$ref: '#/components/schemas/SearchParse'
example:
object: company_search_parse
query: Private dental practices in Texas hiring SDRs
filters:
all:
- { field: company.industry, operator: in, value: [Dentists] }
- { field: company.business_description, operator: matches, value: dental practices }
- { field: company.headquarters.state, operator: in, value: [Texas] }
- { field: company.type, operator: in, value: [Privately Held] }
- related:
relationship: open_jobs
where:
all:
- { field: title, operator: in, value: [Sales Development Representative, SDR] }
criteria: []
unsupported_criteria: []
assumptions: []
errors: []
search_request:
filters:
all:
- { field: company.industry, operator: in, value: [Dentists] }
- { field: company.business_description, operator: matches, value: dental practices }
- { field: company.headquarters.state, operator: in, value: [Texas] }
- { field: company.type, operator: in, value: [Privately Held] }
- related:
relationship: open_jobs
where:
all:
- { field: title, operator: in, value: [Sales Development Representative, SDR] }
criteria: null
'400': { $ref: '#/components/responses/BadRequestQuery' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/IdempotencyKeyReused' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/people/search:
post:
tags: [People]
operationId: startPeopleSearch
summary: Start a people search
description: |
Starts a search for people that match a natural-language `query`, or structured
`filters` and `criteria`. Returns `202` immediately with the search's `id`; the search
runs in the background.
x-docs:
slug: api-reference/people/search
sidebarTitle: Start a search
intro: |
Send either `query`, or `filters` and/or `criteria`. Conditions on `person.*` fields describe the person; conditions on `company.*` fields describe their current employer. Only people who match every requirement are returned.
A search returns names, titles and LinkedIn profiles. Email addresses and phone numbers are looked up only when you set `enrich_emails` or `enrich_phones`, and cost extra.
Poll [`GET /people/search/{search_id}/status`](/api-reference/people/get-search) and read people from [`GET /people/search/{search_id}/results`](/api-reference/people/list-results) as they are found.
<Warning>
Starting a search spends credits as people are found. Reading status and results is free. Set `max_credits` to cap what one search can spend. See [Pricing](/concepts/pricing).
</Warning>
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PeopleSearchCreate'
examples:
query:
summary: Natural language
value:
query: Heads of revenue operations at US fintech companies with 200 to 1,000 employees
limit: 25
enrich_emails: true
filters:
summary: Structured filters
value:
filters:
all:
- field: person.title
operator: in
value: [VP Sales, Head of Sales, Chief Revenue Officer]
- field: person.location.country
operator: in
value: [US]
- field: company.industry
operator: in
value: [Software Development]
- field: company.employee_count
operator: between
value: [50, 500]
limit: 25
enrich_emails: true
max_credits: 20
responses:
'202':
description: The search was accepted and queued.
content:
application/json:
schema:
$ref: '#/components/schemas/Search'
example:
object: people_search
id: 7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13
status: queued
stop_reason: null
error: null
query: Heads of revenue operations at US fintech companies with 200 to 1,000 employees
limit: 25
interpretation: null
assumptions: []
progress: { candidates: 0, accepted: 0, rejected: 0, unknown: 0, not_returned: 0, contacts_found: 0 }
credits_charged: 0
cancel_requested: false
created_at: '2026-11-12T17:10:02Z'
completed_at: null
expires_at: null
status_url: https://api.avina.io/v1/people/search/7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13/status
results_url: https://api.avina.io/v1/people/search/7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13/results
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'402': { $ref: '#/components/responses/UsageLimitReached' }
'409': { $ref: '#/components/responses/IdempotencyKeyReused' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/people/search/{search_id}/status:
get:
tags: [People]
operationId: getPeopleSearch
summary: Get a people search
description: Returns a people search's status, progress and spend. Reading it is free.
x-docs:
slug: api-reference/people/get-search
sidebarTitle: Get search status
intro: |
Poll this endpoint until `status` is `completed`, `failed` or `cancelled`. Start at 2 seconds between polls and back off to 10. See [Search lifecycle](/concepts/search-lifecycle) for what each status and `stop_reason` means.
parameters:
- $ref: '#/components/parameters/SearchId'
responses:
'200':
description: The search.
content:
application/json:
schema:
$ref: '#/components/schemas/Search'
example:
object: people_search
id: 7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13
status: completed
stop_reason: target_reached
error: null
query: Heads of revenue operations at US fintech companies with 200 to 1,000 employees
limit: 25
interpretation:
filters:
all:
- { field: person.title, operator: in, value: [Head of Revenue Operations, VP Revenue Operations, Director of Revenue Operations] }
- { field: company.headquarters.country, operator: in, value: [US] }
- { field: company.industry, operator: in, value: [Financial Services] }
- { field: company.employee_count, operator: between, value: [200, 1000] }
criteria: []
unsupported_criteria: []
assumptions: []
progress: { candidates: 61, accepted: 25, rejected: 33, unknown: 3, not_returned: 0, contacts_found: 25 }
credits_charged: 6.41
cancel_requested: false
created_at: '2026-11-12T17:10:02Z'
completed_at: '2026-11-12T17:12:47Z'
expires_at: null
status_url: https://api.avina.io/v1/people/search/7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13/status
results_url: https://api.avina.io/v1/people/search/7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13/results
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/people/search/{search_id}/results:
get:
tags: [People]
operationId: listPeopleSearchResults
summary: List people search results
description: Returns the people a search has found, in the order they were found. Available while the search is still running. Reading results is free.
x-docs:
slug: api-reference/people/list-results
sidebarTitle: List results
intro: |
Results are only ever added, never changed or removed. Store `next_cursor` and pass it as `after` to read only the people found since your last call. `next_cursor` is always returned, even on an empty page.
`has_more: false` means there are no more stored results right now. It does not mean the search has finished: check `search_status`.
parameters:
- $ref: '#/components/parameters/SearchId'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/After'
responses:
'200':
description: A page of people.
content:
application/json:
schema:
$ref: '#/components/schemas/PersonResultList'
example:
object: list
data:
- object: person_search_result
result_id: res_4Hn7Xc2pL9
name: Jordan Avery
title: Head of Revenue Operations
seniority: head
department: operations
linkedin_url: https://www.linkedin.com/in/jordan-avery-example
location: { country: US, state: New York, city: New York }
email: jordan.avery@northwindpay.example
email_status: valid
phone: null
company:
name: Northwind Pay
domain: northwindpay.example
linkedin_url: https://www.linkedin.com/company/northwind-pay-example
industries: [Financial Services]
employee_count: { low: 201, high: 500 }
headquarters: { country: US, state: New York, city: New York }
matched_criteria:
- criterion: person.title
verdict: matched
evidence:
summary: 'Current title: Head of Revenue Operations'
sources: [https://www.linkedin.com/in/jordan-avery-example]
items: []
- criterion: company.headquarters.country
verdict: matched
evidence:
summary: 'Headquarters country: US'
sources: []
items: []
- criterion: company.industry
verdict: matched
evidence:
summary: 'Industry: Financial Services'
sources: []
items: []
- criterion: company.employee_count
verdict: matched
evidence:
summary: 'Employees: 201–500'
sources: []
items: []
found_at: '2026-11-12T17:11:05Z'
has_more: false
next_cursor: '1'
search_status: completed
'400': { $ref: '#/components/responses/BadRequestCursor' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/people/search/{search_id}/cancel:
post:
tags: [People]
operationId: cancelPeopleSearch
summary: Cancel a people search
description: Stops a people search from starting new work. Results found so far stay readable.
x-docs:
slug: api-reference/people/cancel-search
sidebarTitle: Cancel a search
intro: |
Cancelling stops the search from starting new work. Provider calls already in progress may finish, add results and be charged. The search reaches `status: cancelled` once that work has finished.
Cancelling a search that has already finished returns it unchanged. Cancelling twice costs nothing.
<Note>
A client timeout or a closed connection does not cancel a search. Call this endpoint to stop spending.
</Note>
parameters:
- $ref: '#/components/parameters/SearchId'
responses:
'202':
description: Cancellation was requested. Work already in progress is finishing.
content:
application/json:
schema:
$ref: '#/components/schemas/Search'
example:
object: people_search
id: 7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13
status: running
stop_reason: null
error: null
query: Heads of revenue operations at US fintech companies with 200 to 1,000 employees
limit: 25
interpretation:
filters:
all:
- { field: person.title, operator: in, value: [Head of Revenue Operations, VP Revenue Operations, Director of Revenue Operations] }
- { field: company.headquarters.country, operator: in, value: [US] }
- { field: company.industry, operator: in, value: [Financial Services] }
- { field: company.employee_count, operator: between, value: [200, 1000] }
criteria: []
unsupported_criteria: []
assumptions: []
progress: { candidates: 22, accepted: 9, rejected: 12, unknown: 1, not_returned: 0, contacts_found: 9 }
credits_charged: 2.3
cancel_requested: true
created_at: '2026-11-12T17:10:02Z'
completed_at: null
expires_at: null
status_url: https://api.avina.io/v1/people/search/7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13/status
results_url: https://api.avina.io/v1/people/search/7c1d9a52-3e0b-4f6a-9d21-5b8e4a7c0f13/results
'200':
description: The search had already finished. It is returned unchanged.
content:
application/json:
schema:
$ref: '#/components/schemas/Search'
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/people/search/parse:
post:
tags: [Parse]
operationId: parsePeopleSearch
summary: Parse a people query
description: Turns a natural-language request into the structured `filters` and `criteria` a people search takes, without searching. Free.
x-docs:
slug: api-reference/parse/people
sidebarTitle: Parse a people query
intro: |
Use Parse to show users how their request was understood, let them edit it, or build a filter UI on top of natural language.
When nothing blocks the search, `search_request` is a ready body for [`POST /people/search`](/api-reference/people/search): send it as-is, or edit it first. Otherwise `search_request` is `null`, and `unsupported_criteria` or `errors` say what to change.
Parse runs no search and spends no credits.
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ParseRequest'
examples:
default:
summary: Parse
value:
query: VPs of sales at Series B software companies in the US
responses:
'200':
description: How the query was read.
content:
application/json:
schema:
$ref: '#/components/schemas/SearchParse'
example:
object: people_search_parse
query: VPs of sales at Series B software companies in the US
filters:
all:
- { field: person.title, operator: in, value: [VP Sales, Vice President of Sales] }
- { field: company.industry, operator: in, value: [Software Development] }
- { field: company.last_funding_round, operator: in, value: [series_b] }
- { field: company.headquarters.country, operator: in, value: [US] }
criteria: []
unsupported_criteria: []
assumptions:
- text: in the US
assumed: The company is headquartered in the US
alternatives: [The person is located in the US]
errors: []
search_request:
filters:
all:
- { field: person.title, operator: in, value: [VP Sales, Vice President of Sales] }
- { field: company.industry, operator: in, value: [Software Development] }
- { field: company.last_funding_round, operator: in, value: [series_b] }
- { field: company.headquarters.country, operator: in, value: [US] }
criteria: null
'400': { $ref: '#/components/responses/BadRequestQuery' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/IdempotencyKeyReused' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/personas:
get:
tags: [Personas]
operationId: listPersonas
summary: List personas
description: Returns every persona in the workspace. A workspace has at most 10, so the list is not paginated.
x-docs:
slug: api-reference/personas/list
sidebarTitle: List personas
intro: |
Use a persona's `id` in `persona_ids` on [`POST /companies/search`](/api-reference/companies/search) to find those contacts at each matching company. Personas are the same records as **Settings → Personas** in the Avina dashboard.
responses:
'200':
description: The workspace's personas.
content:
application/json:
schema:
$ref: '#/components/schemas/PersonaList'
example:
object: list
data:
- object: persona
id: c92d77d7-cc85-4a62-bcec-518b1d7d6260
name: Sales leaders
job_titles: [VP Sales, CRO, Head of Sales]
contacts_per_company: 2
enrich_emails: true
enrich_phones: false
contact_countries: [US, CA]
created_at: '2026-10-05T17:02:11Z'
updated_at: '2026-10-05T17:02:11Z'
'401': { $ref: '#/components/responses/Unauthorized' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
post:
tags: [Personas]
operationId: createPersona
summary: Create a persona
description: Creates a persona. Creating a persona does not search for contacts or spend credits. A workspace can have up to 10 personas; creating an eleventh returns `400 invalid_request`.
x-docs:
slug: api-reference/personas/create
sidebarTitle: Create a persona
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PersonaCreate'
examples:
default:
summary: Create
value:
name: Sales leaders
job_titles: [VP Sales, CRO, Head of Sales]
contacts_per_company: 2
enrich_emails: true
enrich_phones: false
contact_countries: [US, CA]
responses:
'201':
description: The persona was created.
content:
application/json:
schema:
$ref: '#/components/schemas/Persona'
example:
object: persona
id: c92d77d7-cc85-4a62-bcec-518b1d7d6260
name: Sales leaders
job_titles: [VP Sales, CRO, Head of Sales]
contacts_per_company: 2
enrich_emails: true
enrich_phones: false
contact_countries: [US, CA]
created_at: '2026-10-05T17:02:11Z'
updated_at: '2026-10-05T17:02:11Z'
'400': { $ref: '#/components/responses/BadRequestPersona' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/IdempotencyKeyReused' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/personas/{persona_id}:
get:
tags: [Personas]
operationId: getPersona
summary: Get a persona
description: Returns one persona.
x-docs:
slug: api-reference/personas/get
sidebarTitle: Get a persona
parameters:
- $ref: '#/components/parameters/PersonaId'
responses:
'200':
description: The persona.
content:
application/json:
schema:
$ref: '#/components/schemas/Persona'
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
patch:
tags: [Personas]
operationId: updatePersona
summary: Update a persona
description: Changes a persona. Fields you omit are unchanged. `job_titles` replaces the whole list.
x-docs:
slug: api-reference/personas/update
sidebarTitle: Update a persona
intro: |
A search uses each persona as it was when the search started. Changing a persona does not affect searches already running.
parameters:
- $ref: '#/components/parameters/PersonaId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PersonaUpdate'
examples:
default:
summary: Update
value:
job_titles: [VP Sales, CRO]
responses:
'200':
description: The updated persona.
content:
application/json:
schema:
$ref: '#/components/schemas/Persona'
example:
object: persona
id: c92d77d7-cc85-4a62-bcec-518b1d7d6260
name: Sales leaders
job_titles: [VP Sales, CRO]
contacts_per_company: 2
enrich_emails: true
enrich_phones: false
contact_countries: [US, CA]
created_at: '2026-10-05T17:02:11Z'
updated_at: '2026-11-12T09:30:00Z'
'400': { $ref: '#/components/responses/BadRequestPersona' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
delete:
tags: [Personas]
operationId: deletePersona
summary: Delete a persona
description: Deletes a persona. Searches already running keep the settings they started with.
x-docs:
slug: api-reference/personas/delete
sidebarTitle: Delete a persona
parameters:
- $ref: '#/components/parameters/PersonaId'
responses:
'204':
description: The persona was deleted. The response has no body.
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/me:
get:
tags: [Account]
operationId: getMe
summary: Get the current API key
description: Returns the API key making the request and the workspace it belongs to. Use it to check that a key works.
x-docs:
slug: api-reference/account/me
sidebarTitle: Get the current key
responses:
'200':
description: The key and its workspace.
content:
application/json:
schema:
$ref: '#/components/schemas/Me'
example:
object: api_key
id: key_3f9a1c
name: Production server
workspace:
id: 0b7c8a2e-4d1f-4e39-9a6b-2f5d7c8e9a01
name: Acme Inc
'401': { $ref: '#/components/responses/Unauthorized' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
/usage:
get:
tags: [Account]
operationId: getUsage
summary: Get credit usage
description: Returns the workspace's credit balance and what it has spent in the current billing period. One credit is one US dollar.
x-docs:
slug: api-reference/account/usage
sidebarTitle: Get credit usage
intro: |
Credits are prepaid and denominated in US dollars: 1 credit = $1.00. Searches draw down the balance as they find results. See [Pricing](/concepts/pricing).
responses:
'200':
description: The workspace's usage.
content:
application/json:
schema:
$ref: '#/components/schemas/Usage'
example:
object: usage
period_start: '2026-11-01T00:00:00Z'
period_end: '2026-12-01T00:00:00Z'
credits_used: 41.87
credits_limit: 200
credits_remaining: 158.13
'401': { $ref: '#/components/responses/Unauthorized' }
'429': { $ref: '#/components/responses/RateLimited' }
'500': { $ref: '#/components/responses/InternalError' }
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: A workspace API key, created in the Avina dashboard under Settings → API Keys.
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: false
description: A unique string for this request, 1 to 255 characters. Retrying with the same key and body returns the original response instead of starting new work. Reusing a key with a different body returns `409 idempotency_key_reused`. Always send one when starting a search.
schema:
type: string
minLength: 1
maxLength: 255
example: 6f0c1b9e-search-texas-dental
SearchId:
name: search_id
in: path
required: true
description: The search's `id`, returned when it was started.
schema:
type: string
format: uuid
PersonaId:
name: persona_id
in: path
required: true
description: The persona's `id`.
schema:
type: string
format: uuid
Limit:
name: limit
in: query
required: false
description: Page size.
schema:
type: integer
minimum: 1
maximum: 100
default: 25
After:
name: after
in: query
required: false
description: The `next_cursor` from the previous page. Omit it on the first call.
schema:
type: string
responses:
BadRequest:
description: The request is invalid. `details` names each problem.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: invalid_request
message: 'filters.all.0: unknown field ''company.size'''
request_id: req_8f2a61c09d4e7b3a5f10c2d8
details:
- field: filters.all.0
message: unknown field 'company.size'; supported fields are listed in the filter reference
Unauthorized:
description: The API key is missing, invalid or revoked.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: invalid_api_key
message: The API key is invalid or revoked.
request_id: req_8f2a61c09d4e7b3a5f10c2d8
UsageLimitReached:
description: The workspace has no credits left. Nothing was started or charged.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: usage_limit_reached
message: The workspace has no credits left. Nothing was started or charged.
request_id: req_8f2a61c09d4e7b3a5f10c2d8
NotFound:
description: No such object in this workspace.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: not_found
message: Search not found.
request_id: req_8f2a61c09d4e7b3a5f10c2d8
IdempotencyKeyReused:
description: The `Idempotency-Key` was already used with a different request, or its first request is still running.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: idempotency_key_reused
message: This Idempotency-Key was already used with a different request.
request_id: req_8f2a61c09d4e7b3a5f10c2d8
PermissionDenied:
description: The workspace is not allowed to do this. `details` gives a reason, such as `contact_search_disabled` when `persona_ids` is sent and contact search is turned off.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: permission_denied
message: Contact search is not enabled for this workspace.
request_id: req_8f2a61c09d4e7b3a5f10c2d8
details:
- reason: contact_search_disabled
message: Contact search is not enabled for this workspace.
InternalError:
description: Something went wrong on our side. Retry with backoff, and with the same `Idempotency-Key` if you sent one.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: internal_error
message: Something went wrong on our side. Retry the request; if it keeps failing, contact support with the request id.
request_id: req_8f2a61c09d4e7b3a5f10c2d8
BadRequestCursor:
description: The request is invalid, for example a malformed `after` cursor or a `limit` out of range.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: invalid_request
message: 'after: not a valid cursor'
request_id: req_8f2a61c09d4e7b3a5f10c2d8
details:
- field: after
message: not a valid cursor
BadRequestPersona:
description: The request is invalid. `details` names each problem.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: invalid_request
message: 'job_titles: must contain at least one title'
request_id: req_8f2a61c09d4e7b3a5f10c2d8
details:
- field: job_titles
message: must contain at least one title
BadRequestQuery:
description: The request is invalid, for example a missing `query` or one longer than 1,000 characters.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: invalid_request
message: 'query: must be at most 1000 characters'
request_id: req_8f2a61c09d4e7b3a5f10c2d8
details:
- field: query
message: must be at most 1000 characters
RateLimited:
description: Too many requests. Retry after `Retry-After` seconds.
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
example:
error:
code: rate_limited
message: Too many requests. Retry after 12 seconds.
request_id: req_8f2a61c09d4e7b3a5f10c2d8
schemas:
CompanySearchCreate:
type: object
additionalProperties: false
properties:
query:
type: string
minLength: 1
maxLength: 1000
description: What to find, in plain language. Required unless you send `filters` or `criteria`. Cannot be combined with them.
examples: [Privately held dental practices in Texas hiring SDRs]
filters:
anyOf:
- $ref: '#/components/schemas/Filters'
- type: 'null'
criteria:
anyOf:
- $ref: '#/components/schemas/Criteria'
- type: 'null'
limit:
type: integer
minimum: 1
maximum: 500
default: 20
description: The most companies to return. The search stops when it has found this many.
persona_ids:
type: array
maxItems: 10
items: { type: string, format: uuid }
description: Personas to find contacts for at each matching company. Omitted or empty means no contact lookup and no contact charges. Personas choose which people to find; they do not filter which companies match.
exclude_domains:
type: array
items: { type: string }
description: Company domains to skip, for example companies you already have.
examples: [[acme.com, globex.com]]
max_credits:
type: number
exclusiveMinimum: 0
description: The most credits this search may spend. 1 credit = $1.00. When the search reaches it, it stops with `stop_reason` `usage_limit_reached` and keeps the results found so far. Defaults to your remaining balance.
PeopleSearchCreate:
type: object
additionalProperties: false
properties:
query:
type: string
minLength: 1
maxLength: 1000
description: Who to find, in plain language. Required unless you send `filters` or `criteria`. Cannot be combined with them.
examples: [Heads of revenue operations at US fintech companies with 200 to 1,000 employees]
filters:
anyOf:
- $ref: '#/components/schemas/Filters'
- type: 'null'
criteria:
anyOf:
- $ref: '#/components/schemas/Criteria'
- type: 'null'
limit:
type: integer
minimum: 1
maximum: 500
default: 20
description: The most people to return. The search stops when it has found this many.
enrich_emails:
type: boolean
default: false
description: Look up a work email address for each person found. Charged per person looked up. An email is not guaranteed.
enrich_phones:
type: boolean
default: false
description: Look up a phone number for each person found. Charged per person looked up, at a higher rate than email. A phone number is not guaranteed.
exclude_linkedin_urls:
type: array
items: { type: string, format: uri }
description: LinkedIn profile URLs to skip, for example people you already have.
max_credits:
type: number
exclusiveMinimum: 0
description: The most credits this search may spend. 1 credit = $1.00. When the search reaches it, it stops with `stop_reason` `usage_limit_reached` and keeps the results found so far. Defaults to your remaining balance.
Filters:
type: object
additionalProperties: false
required: [all]
description: Structured conditions. A record must meet every condition in `all`. `null` is treated the same as leaving `filters` out. See the [filter reference](/guides/structured-filters) for every field and operator.
properties:
all:
type: array
minItems: 1
description: The conditions. A record must meet every one. Each item is a field condition (`field`, `operator`, `value`) or a `related` condition.
items:
$ref: '#/components/schemas/FilterCondition'
FilterCondition:
type: object
additionalProperties: false
description: Either a field condition (`field`, `operator`, `value`) or a `related` condition, not both.
properties:
field:
type: string
description: The field to test, such as `company.industry` or `person.title`.
examples: [company.employee_count]
operator:
type: string
enum: [in, matches, eq, gt, gte, lt, lte, between, within_last_days]
description: How to compare. Which operators a field accepts depends on its type.
value:
description: The value to compare against. A list for `in`, a two-item list for `between`, a `{amount, currency}` object for money fields, a number of days for `within_last_days`.
related:
$ref: '#/components/schemas/RelatedCondition'
RelatedCondition:
type: object
additionalProperties: false
required: [relationship, where]
description: A condition on records related to the company. All conditions in `where` must be true of the same record, for example one job listing.
properties:
relationship:
type: string
enum: [open_jobs, new_hires]
description: '`open_jobs`: the company has at least one open job that matches. `new_hires`: someone with a matching title joined the company within the window.'
where:
type: object
additionalProperties: false
required: [all]
description: Conditions on the related record.
properties:
all:
type: array
minItems: 1
description: Conditions on `title` (`in`), `posted_at` (`within_last_days`, for `open_jobs`) or `started_at` (`within_last_days`, for `new_hires`).
items:
type: object
additionalProperties: false
required: [field, operator, value]
properties:
field:
type: string
enum: [title, posted_at, started_at]
description: The field on the related record.
operator:
type: string
enum: [in, within_last_days]
description: '`in` for `title`; `within_last_days` for `posted_at` and `started_at`.'
value:
description: A list of titles for `in`, or a whole number of days from 1 to 36500 for `within_last_days`.
Criteria:
type: array
maxItems: 10
description: Free-text requirements, each checked against evidence for every candidate. Use them for anything the structured fields cannot express. Each item is a string, or an object with `text` and `kind`.
items:
oneOf:
- type: string
- $ref: '#/components/schemas/Criterion'
examples: [[independently owned, sells to hospitals]]
Criterion:
type: object
additionalProperties: false
required: [text]
description: 'A free-text requirement. A plain string is also accepted and is treated as `kind: event`.'
properties:
text:
type: string
minLength: 1
description: The requirement, written as a statement that is true of a match.
examples: [opened a new location this year]
kind:
type: string
enum: [attribute, event]
default: event
description: '`attribute`: a lasting fact the company''s own description could state, such as "sells to hospitals". `event`: something that happened, such as "opened a location in Texas this year"; checked by web research.'
Search:
type: object
required: [object, id, status, stop_reason, error, query, limit, interpretation, assumptions, progress, credits_charged, cancel_requested, created_at, completed_at, expires_at, status_url, results_url]
properties:
object:
type: string
enum: [company_search, people_search]
description: '`company_search` or `people_search`.'
id:
type: string
format: uuid
description: The search's identifier. Use it to read status and results.
status:
type: string
enum: [queued, running, completed, failed, cancelled]
description: '`queued` and `running` are in progress. `completed`, `failed` and `cancelled` are terminal. `completed` means this run finished, not that every matching record in the world was found.'
stop_reason:
type: [string, 'null']
enum: [target_reached, sources_exhausted, usage_limit_reached, retrieval_limit_reached, query_needs_clarification, provider_failed, cancelled, null]
description: Why a finished search stopped. `null` while it is in progress. Can also be `null` on a `failed` search; read `error`.
error:
type: [string, 'null']
description: A message when `status` is `failed`. Results found before the failure stay readable.
query:
type: [string, 'null']
description: The natural-language request, when the search was started with `query`.
limit:
type: integer
description: The most results this search will return.
interpretation:
type: [object, 'null']
description: How a `query` was read. `null` until the query has been interpreted, and for searches started with `filters` or `criteria`.
properties:
filters:
$ref: '#/components/schemas/Filters'
criteria:
type: array
description: Free-text requirements read from the query.
items: { $ref: '#/components/schemas/Criterion' }
unsupported_criteria:
type: array
items: { type: string }
description: Requirements no public source can confirm, quoted from the query. A search cannot run while there are any.
errors:
type: array
description: Problems validating the filters the query was read as. A search cannot run while there are any.
items:
type: object
required: [message]
properties:
field: { type: string, description: 'The filter path with the problem.' }
message: { type: string, description: 'What is wrong.' }
assumptions:
type: array
description: Ambiguous wording in the query and how it was read.
items: { $ref: '#/components/schemas/Assumption' }
progress:
type: object
description: Counts so far. They only increase.
required: [candidates, accepted, rejected, unknown, not_returned, contacts_found]
properties:
candidates:
type: integer
description: Candidates checked so far.
accepted:
type: integer
description: Candidates that matched every requirement and were added to the results.
rejected:
type: integer
description: Candidates that failed at least one requirement.
unknown:
type: integer
description: Candidates whose evidence could not confirm every requirement. They are not returned.
not_returned:
type: integer
description: Candidates that matched every requirement but were not returned because `limit` or a spend limit had already been reached.
contacts_found:
type: integer
description: Contacts found so far. For company searches with `persona_ids`, and people searches with enrichment.
credits_charged:
type: number
description: Credits charged for this search so far. 1 credit = $1.00.
cancel_requested:
type: boolean
description: '`true` after a cancel request, until the search reaches `cancelled`.'
created_at:
type: string
format: date-time
description: When the search was started.
completed_at:
type: [string, 'null']
format: date-time
description: When the search reached a terminal status.
expires_at:
type: [string, 'null']
format: date-time
description: When the search and its results stop being readable. `null` when no expiry is set.
status_url:
type: string
format: uri
description: The URL of this search's status.
results_url:
type: string
format: uri
description: The URL of this search's results.
Assumption:
type: object
required: [text, assumed, alternatives]
properties:
text:
type: string
description: The exact phrase from the query.
assumed:
type: string
description: The reading that was used.
alternatives:
type: array
items: { type: string }
description: Other readings. Reword the query if one of these is what you meant.
ParseRequest:
type: object
additionalProperties: false
required: [query]
properties:
query:
type: string
minLength: 1
maxLength: 1000
description: The request to parse, from one sentence to a pasted paragraph of requirements.
SearchParse:
type: object
required: [object, query, filters, criteria, unsupported_criteria, assumptions, errors, search_request]
properties:
object:
type: string
enum: [company_search_parse, people_search_parse]
description: '`company_search_parse` or `people_search_parse`.'
query:
type: string
description: The original text.
filters:
description: The structured reading of the query. `null` when nothing in the query maps to a structured field.
anyOf:
- $ref: '#/components/schemas/Filters'
- type: 'null'
criteria:
type: array
description: Requirements that will be checked against evidence for each candidate.
items: { $ref: '#/components/schemas/Criterion' }
unsupported_criteria:
type: array
items: { type: string }
description: Requirements no public source can confirm, quoted from the query, such as visits to your own website or subjective quality. The search cannot run while there are any.
assumptions:
type: array
description: Ambiguous wording and how it was read. Assumptions do not block the search.
items: { $ref: '#/components/schemas/Assumption' }
errors:
type: array
description: Problems validating the filters the query was read as.
items:
type: object
required: [message]
properties:
field: { type: string, description: 'The filter path with the problem.' }
message: { type: string, description: 'What is wrong.' }
search_request:
type: [object, 'null']
description: A ready request body for the matching search endpoint. `null` when `unsupported_criteria` or `errors` is not empty, or the query gave nothing to search on.
properties:
filters:
anyOf:
- $ref: '#/components/schemas/Filters'
- type: 'null'
criteria:
type: [array, 'null']
items: { $ref: '#/components/schemas/Criterion' }
CompanyResultList:
type: object
required: [object, data, has_more, next_cursor, search_status]
properties:
object:
type: string
enum: [list]
description: Always `list`.
data:
type: array
description: Companies, in the order they were found.
items: { $ref: '#/components/schemas/CompanyResult' }
has_more:
type: boolean
description: Whether more stored results are available now. `false` does not mean the search has finished.
next_cursor:
type: string
description: Pass as `after` to read the results after this page. Always returned. Store it and send it back unchanged; do not parse it.
search_status:
type: string
enum: [queued, running, completed, failed, cancelled]
description: The search's status when this page was read.
PersonResultList:
type: object
required: [object, data, has_more, next_cursor, search_status]
properties:
object:
type: string
enum: [list]
description: Always `list`.
data:
type: array
description: People, in the order they were found.
items: { $ref: '#/components/schemas/PersonResult' }
has_more:
type: boolean
description: Whether more stored results are available now. `false` does not mean the search has finished.
next_cursor:
type: string
description: Pass as `after` to read the results after this page. Always returned. Store it and send it back unchanged; do not parse it.
search_status:
type: string
enum: [queued, running, completed, failed, cancelled]
description: The search's status when this page was read.
CompanyResult:
type: object
required: [object, result_id, domain, name, matched_criteria, contacts, contact_status, found_at]
properties:
object:
type: string
enum: [company_search_result]
description: Always `company_search_result`.
result_id:
type: string
description: A stable identifier for this result within the search.
domain:
type: string
description: The company's website domain. Unique within a search.
name:
type: [string, 'null']
description: The company's name.
description:
type: [string, 'null']
description: A short description of the company.
industries:
type: array
items: { type: string }
description: LinkedIn industry names. Empty when unknown.
headquarters:
anyOf:
- $ref: '#/components/schemas/Location'
- type: 'null'
description: Where the company is headquartered.
employee_count:
anyOf:
- $ref: '#/components/schemas/NumberInterval'
- type: 'null'
description: Number of employees, as a range.
annual_revenue_usd:
anyOf:
- $ref: '#/components/schemas/NumberInterval'
- type: 'null'
description: Annual revenue in US dollars, as a range.
total_funding_usd:
anyOf:
- $ref: '#/components/schemas/NumberInterval'
- type: 'null'
description: Total funding raised in US dollars, as a range.
last_funding:
type: [object, 'null']
description: The most recent funding round.
properties:
date:
type: [string, 'null']
format: date
description: The date of the round.
round:
type: [string, 'null']
description: The round, such as `seed` or `series_b`.
company_type:
type: [string, 'null']
description: Ownership type, such as `Privately Held` or `Public Company`.
founded_year:
type: [integer, 'null']
description: The year the company was founded.
linkedin_url:
type: [string, 'null']
format: uri
description: The company's LinkedIn page.
matched_criteria:
type: array
description: One entry per requirement of the search, with its evidence.
items: { $ref: '#/components/schemas/MatchedCriterion' }
contacts:
type: array
description: People found for the search's personas. Empty when no personas were requested or nobody was found.
items: { $ref: '#/components/schemas/Contact' }
contact_status:
type: string
enum: [not_requested, complete, partial, failed]
description: '`not_requested`: no personas were sent. `complete`: every lookup finished, including lookups that found nobody. `partial`: some lookups finished and others failed or were stopped. `failed`: no lookup could finish.'
found_at:
type: string
format: date-time
description: When the company was added to the results.
PersonResult:
type: object
required: [object, result_id, name, title, company, matched_criteria, found_at]
properties:
object:
type: string
enum: [person_search_result]
description: Always `person_search_result`.
result_id:
type: string
description: A stable identifier for this result within the search.
name:
type: string
description: The person's full name.
title:
type: [string, 'null']
description: The person's current job title.
seniority:
type: [string, 'null']
enum: [owner, c_suite, vp, head, director, manager, senior, entry, null]
description: The seniority level of the current role.
department:
type: [string, 'null']
description: The function of the current role, such as `sales`, `marketing`, `engineering` or `operations`.
linkedin_url:
type: [string, 'null']
format: uri
description: The person's LinkedIn profile.
location:
anyOf:
- $ref: '#/components/schemas/Location'
- type: 'null'
description: Where the person is located. This can differ from the company's headquarters.
email:
type: [string, 'null']
description: Work email address. `null` unless `enrich_emails` was set and an address was found.
email_status:
type: [string, 'null']
enum: [valid, catch_all, unknown, null]
description: 'The result of verifying `email`. `valid`: the mailbox accepts mail. `catch_all`: the domain accepts every address, so the mailbox cannot be confirmed. `unknown`: verification was inconclusive.'
phone:
type: [string, 'null']
description: Phone number. `null` unless `enrich_phones` was set and a number was found.
company:
type: object
description: The person's current employer.
required: [name, domain]
properties:
name: { type: [string, 'null'], description: 'The company''s name.' }
domain: { type: string, description: 'The company''s website domain.' }
linkedin_url: { type: [string, 'null'], format: uri, description: 'The company''s LinkedIn page.' }
industries: { type: array, items: { type: string }, description: 'LinkedIn industry names.' }
employee_count:
anyOf:
- $ref: '#/components/schemas/NumberInterval'
- type: 'null'
description: Number of employees, as a range.
headquarters:
anyOf:
- $ref: '#/components/schemas/Location'
- type: 'null'
description: Where the company is headquartered.
matched_criteria:
type: array
description: One entry per requirement of the search, with its evidence.
items: { $ref: '#/components/schemas/MatchedCriterion' }
found_at:
type: string
format: date-time
description: When the person was added to the results.
MatchedCriterion:
type: object
required: [criterion, verdict, evidence]
properties:
criterion:
type: string
description: Which requirement this is. A filter field such as `company.industry`, a relationship such as `open_jobs`, or `criteria.<index>` for a free-text criterion, where the index is its zero-based position in `criteria`.
verdict:
type: string
enum: [matched, not_matched, unknown]
description: The outcome of the check. Results only include records where every requirement is `matched`.
evidence:
$ref: '#/components/schemas/Evidence'
Evidence:
type: object
required: [summary, sources, items]
description: Why the verdict was reached.
properties:
summary:
type: string
description: A one-line explanation, or a quote from the source.
sources:
type: array
items: { type: string, format: uri }
description: URLs that support the verdict. Empty when the evidence is a structured record with no public page.
items:
type: array
description: Supporting records, when the requirement is about jobs, hires or technologies.
items:
type: object
required: [type]
properties:
type:
type: string
enum: [job, hire, technology]
description: The kind of record.
title: { type: string, description: 'The job title, for `job` and `hire`.' }
name: { type: string, description: 'The person''s name, for `hire`.' }
technology: { type: string, description: 'The product or vendor, for `technology`.' }
posted_at: { type: string, format: date, description: 'When the job was posted, for `job`.' }
started_at: { type: string, format: date, description: 'When the person started, for `hire`.' }
detected_at: { type: string, format: date, description: 'When the technology was detected, for `technology`.' }
location: { type: string, description: 'The job''s location, for `job`.' }
url: { type: string, format: uri, description: 'A link to the record.' }
Contact:
type: object
required: [name, persona_ids]
properties:
name: { type: string, description: 'The person''s full name.' }
title: { type: [string, 'null'], description: 'The person''s current job title.' }
linkedin_url: { type: [string, 'null'], format: uri, description: 'The person''s LinkedIn profile.' }
email: { type: [string, 'null'], description: 'Work email address, when the persona has `enrich_emails` and an address was found.' }
email_status:
type: [string, 'null']
enum: [valid, catch_all, unknown, null]
description: The result of verifying `email`.
phone: { type: [string, 'null'], description: 'Phone number, when the persona has `enrich_phones` and a number was found.' }
persona_ids:
type: array
items: { type: string, format: uuid }
description: The personas this person matched.
Location:
type: object
properties:
country: { type: [string, 'null'], description: 'ISO 3166-1 alpha-2 country code.' }
state: { type: [string, 'null'], description: 'State or region.' }
city: { type: [string, 'null'], description: 'City.' }
NumberInterval:
type: object
required: [low, high]
description: The value lies between `low` and `high`, inclusive. An exact value has `low` equal to `high`.
properties:
low: { type: number, description: 'The lower bound.' }
high: { type: [number, 'null'], description: 'The upper bound. `null` when open-ended.' }
Persona:
type: object
required: [object, id, job_titles, contacts_per_company, enrich_emails, enrich_phones, created_at, updated_at]
properties:
object: { type: string, enum: [persona], description: 'Always `persona`.' }
id: { type: string, format: uuid, description: 'The persona''s identifier. Use it in `persona_ids`.' }
name: { type: [string, 'null'], description: 'A label for the persona.' }
job_titles:
type: array
items: { type: string }
description: The job titles to look for at each company.
contacts_per_company:
type: integer
description: How many contacts to find per company for this persona.
enrich_emails: { type: boolean, description: 'Whether to look up email addresses.' }
enrich_phones: { type: boolean, description: 'Whether to look up phone numbers.' }
contact_countries:
type: [array, 'null']
items: { type: string }
description: Where the contacts are located, as ISO 3166-1 alpha-2 codes. This is the person's location, not the company's headquarters. `null` or empty means worldwide.
created_at: { type: string, format: date-time, description: 'When the persona was created.' }
updated_at: { type: string, format: date-time, description: 'When the persona was last changed.' }
PersonaCreate:
type: object
additionalProperties: false
required: [job_titles]
properties:
name: { type: string, maxLength: 191, description: 'A label for the persona.' }
job_titles:
type: array
minItems: 1
items: { type: string, minLength: 1 }
description: The job titles to look for at each company.
examples: [[VP Sales, CRO, Head of Sales]]
contacts_per_company:
type: integer
minimum: 1
maximum: 100
default: 1
description: How many contacts to find per company for this persona.
enrich_emails: { type: boolean, default: true, description: 'Look up an email address for each contact.' }
enrich_phones: { type: boolean, default: false, description: 'Look up a phone number for each contact. Costs more than email.' }
contact_countries:
type: array
items: { type: string, pattern: '^[A-Za-z]{2}$' }
description: Where the contacts are located, as ISO 3166-1 alpha-2 codes. Omit for worldwide.
examples: [[US, CA]]
PersonaUpdate:
type: object
additionalProperties: false
properties:
name: { type: [string, 'null'], maxLength: 191, description: 'A label for the persona.' }
job_titles:
type: array
minItems: 1
items: { type: string, minLength: 1 }
description: Replaces the whole list of job titles.
contacts_per_company: { type: integer, minimum: 1, maximum: 100, description: 'How many contacts to find per company for this persona.' }
enrich_emails: { type: boolean, description: 'Look up an email address for each contact.' }
enrich_phones: { type: boolean, description: 'Look up a phone number for each contact. Costs more than email.' }
contact_countries:
type: [array, 'null']
items: { type: string, pattern: '^[A-Za-z]{2}$' }
description: Where the contacts are located, as ISO 3166-1 alpha-2 codes. `null` or empty means worldwide.
PersonaList:
type: object
required: [object, data]
properties:
object: { type: string, enum: [list], description: 'Always `list`.' }
data:
type: array
description: The workspace's personas.
items: { $ref: '#/components/schemas/Persona' }
Me:
type: object
required: [object, id, workspace]
properties:
object: { type: string, enum: [api_key], description: 'Always `api_key`.' }
id: { type: string, description: 'The API key''s identifier. Not the secret.' }
name: { type: [string, 'null'], description: 'The label given to the key when it was created.' }
workspace:
type: object
description: The workspace the key acts for.
required: [id, name]
properties:
id: { type: string, format: uuid, description: 'The workspace''s identifier.' }
name: { type: string, description: 'The workspace''s name.' }
Usage:
type: object
required: [object, period_start, period_end, credits_used, credits_limit, credits_remaining]
properties:
object: { type: string, enum: [usage], description: 'Always `usage`.' }
period_start: { type: [string, 'null'], format: date-time, description: 'The start of the current billing period.' }
period_end: { type: [string, 'null'], format: date-time, description: 'The end of the current billing period.' }
credits_used: { type: number, description: 'Credits spent in the current period. 1 credit = $1.00.' }
credits_limit: { type: [number, 'null'], description: 'Credits available for the period, including top-ups. `null` when there is no limit.' }
credits_remaining: { type: [number, 'null'], description: 'Your balance. Credits left to spend. `null` when there is no limit.' }
Error:
type: object
required: [error]
properties:
error:
type: object
required: [code, message, request_id]
properties:
code:
type: string
enum: [invalid_request, invalid_api_key, usage_limit_reached, permission_denied, not_found, idempotency_key_reused, rate_limited, workspace_not_ready, internal_error, timeout]
description: A stable, machine-readable code. Branch on this, not on `message`.
message:
type: string
description: A human-readable explanation of the first problem.
request_id:
type: string
description: The request's identifier, also in the `X-Request-Id` response header. Include it when you contact support.
details:
type: array
description: Every problem found, when there is more than a message to give.
items:
type: object
required: [message]
properties:
field: { type: string, description: 'The field or path with the problem, such as `filters.all.0` or `criteria.2`.' }
reason: { type: string, description: 'A machine-readable reason, on `permission_denied` errors. For example `contact_search_disabled`.' }
message: { type: string, description: 'What is wrong.' }

