> ## Documentation Index
> Fetch the complete documentation index at: https://docs.data.avina.io/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAPI specification

> The machine-readable contract for the Avina Data API, in OpenAPI 3.1.

The API reference on this site is generated from this specification. Copy it to generate a client, load it into an API tool, or hand it to a coding agent.

* **Format:** OpenAPI 3.1, YAML
* **Base URL:** `https://api.avina.io/v1`
* **Authentication:** bearer token, a workspace API key

> [!TIP]
>
> Use the copy button on the code block to copy the whole specification.

```yaml openapi.yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
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.' }
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.