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

# Person Discovery (Beta)

> Person Discovery API endpoint: find people using natural language queries across 188M+ professional profiles.

## How It Works

Describe who you're looking for in plain English. The API translates your description into a SQL query and returns matching profiles.

The generated SQL query is returned in the `generated_query` field of the response body so you can see exactly how your description was interpreted.

## Example Queries

```text theme={null}
software engineers in Austin who worked at Meta
marketing directors at Fortune 500 companies in New York
nurses in California with 10+ years of experience
VP of Sales at SaaS companies with over 1000 employees
data scientists with Python skills in the Bay Area
```

<Note>
  For precise control over filtering, use [Person Search](/docs/api-reference/person-search) with SQL syntax instead.
</Note>

## Pagination

To page through results beyond the first 100, set `offset` to the number of rows to skip. Maximum `offset` is 10,000. Ordering is deterministic within a build, so paged requests don't overlap or skip rows; builds run on a periodic cadence, so paginate within a single client session, not across days.

```json theme={null}
{
  "query": "software engineers in Austin who worked at Meta",
  "limit": 100,
  "offset": 100
}
```


## OpenAPI

````yaml POST /person/discover
openapi: 3.1.0
info:
  title: Data Legion API
  description: API for enriching, searching, and discovering person and company data
  version: 1.0.0
servers:
  - url: https://api.datalegion.ai
security:
  - APIKeyHeader: []
paths:
  /person/discover:
    post:
      tags:
        - person
        - discover
      summary: Discover persons using natural language
      description: >-
        Describe who you're looking for in plain English. AI translates your
        description into precise database queries. The generated SQL is returned
        in the response body as `generated_query`.
      operationId: discover_persons_person_discover_post
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DiscoverRequest'
      responses:
        '200':
          description: Success - persons found matching natural language query.
          headers:
            Total-Count-Status:
              $ref: '#/components/headers/TotalCountStatus'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonDiscoverResponse'
              example:
                matches:
                  - person:
                      legion_id: a7e91c34-2b8f-4d6e-9c1a-3f5b7d8e2a10
                      full_name: michael chen
                      first_name: michael
                      last_name: chen
                      city: new york
                      state: new york
                      state_code: US-NY
                      country: united states
                      country_code: US
                      job_title: vp of engineering
                      company_name: fintech startup
                      company_domain: fintechstartup.com
                      company_industry: financial services
                      company_size: 201-500
                      seniority_level: vp
                      job_function: engineering
                      is_decision_maker: true
                      is_platform_worker: false
                      work_email: michael.chen@fintechstartup.com
                      linkedin_url: https://www.linkedin.com/in/michaelchen
                      linkedin_id: '987654321'
                      years_of_experience: 18
                      last_seen: '2026-01-18'
                total: 1247
                generated_query: >-
                  SELECT * FROM people WHERE job_title ILIKE '%vp%engineer%' AND
                  state_code = 'US-NY'
        '400':
          description: Bad request - invalid or unclear query
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Payment required - insufficient credits or expired contract
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden - API key not authorized for this endpoint
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '408':
          description: Request timeout - the query exceeded the execution time limit
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          description: Payload too large - request body exceeds size limit
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation error - invalid field format or value
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Too many requests - rate limit exceeded (50 requests per minute)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '501':
          description: Natural language search is not configured on this server
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Query generation service temporarily unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    DiscoverRequest:
      properties:
        query:
          type: string
          minLength: 3
          maxLength: 1000
          title: Query
          description: Natural language description of who you're looking for
        limit:
          type: integer
          minimum: 1
          maximum: 100
          title: Limit
          description: Maximum number of results to return
        offset:
          type: integer
          maximum: 10000
          minimum: 0
          title: Offset
          description: >-
            Number of results to skip for pagination (0-10000). Stable within a
            build; ordering may change across builds.
          default: 0
        titlecase:
          type: boolean
          title: Titlecase
          description: >-
            If true, format text fields in title case (names, company names,
            locations). Raw fields, IDs, URLs, codes, and confidence fields are
            excluded.
          default: false
        include_fields:
          anyOf:
            - type: string
            - type: 'null'
          title: Include Fields
          description: >-
            Comma-separated list of fields to include in response. If omitted,
            all fields are returned.
        exclude_fields:
          anyOf:
            - type: string
            - type: 'null'
          title: Exclude Fields
          description: >-
            Comma-separated list of fields to exclude from response. Applied
            after include_fields filter.
        pretty_print:
          type: boolean
          title: Pretty Print
          description: If true, pretty-print JSON response with indentation.
          default: false
      type: object
      required:
        - query
        - limit
      title: DiscoverRequest
      description: Request model for natural language person discovery.
      example:
        query: VP of Engineering at fintech companies in New York
        limit: 10
    PersonDiscoverResponse:
      allOf:
        - $ref: '#/components/schemas/PersonMatchesResponse'
        - type: object
          required:
            - generated_query
          properties:
            generated_query:
              type: string
              title: Generated Query
              description: SQL query generated from the natural language input
      title: PersonDiscoverResponse
      description: Person discover response with generated query.
    ErrorResponse:
      properties:
        error:
          type: string
          title: Error
          description: Error type/code
        message:
          type: string
          title: Message
          description: Human-readable error message
        details:
          anyOf:
            - additionalProperties: true
              type: object
            - items: {}
              type: array
            - type: 'null'
          title: Details
          description: Additional error details (for validation errors)
      type: object
      required:
        - error
        - message
      title: ErrorResponse
      description: Error response model for customer-facing API.
    PersonMatchesResponse:
      properties:
        matches:
          items:
            $ref: '#/components/schemas/PersonMatchResponse'
          type: array
          title: Matches
          description: >-
            List of matches sorted by confidence (descending). Capped at the
            request's `limit`.
        total:
          type: integer
          title: Total
          description: >-
            For /person/search and /person/discover, the total number of rows
            matching the query's WHERE clause across the database (not just this
            page). For /person/enrich, the number of matches found for the input
            identifier. On search/discover, if the exact count exceeds its time
            budget (broad, low-selectivity queries) it falls back to the query
            planner's row estimate, and if that is unavailable, to the size of
            the returned page; the response header `Total-Count-Status` reports
            which (`exact`, `estimate`, or `page`).
      type: object
      required:
        - matches
        - total
      title: PersonMatchesResponse
      description: Multiple person matches response.
    PersonMatchResponse:
      properties:
        person:
          $ref: '#/components/schemas/PersonResponse'
        match_metadata:
          anyOf:
            - $ref: '#/components/schemas/MatchMetadata'
            - type: 'null'
      type: object
      required:
        - person
      title: PersonMatchResponse
      description: Person response with optional match metadata.
    PersonResponse:
      properties:
        legion_id:
          type: string
          title: Legion Id
        full_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Full Name
        first_name:
          anyOf:
            - type: string
            - type: 'null'
          title: First Name
        middle_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Middle Name
        middle_initial:
          anyOf:
            - type: string
            - type: 'null'
          title: Middle Initial
        last_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Name
        last_initial:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Initial
        suffix:
          anyOf:
            - type: string
            - type: 'null'
          title: Suffix
        prefix:
          anyOf:
            - type: string
            - type: 'null'
          title: Prefix
        sex:
          anyOf:
            - type: string
            - type: 'null'
          title: Sex
        birth_date:
          anyOf:
            - type: string
            - type: 'null'
          title: Birth Date
        birth_year:
          anyOf:
            - type: integer
            - type: 'null'
          title: Birth Year
        birth_month:
          anyOf:
            - type: integer
            - type: 'null'
          title: Birth Month
        birth_day:
          anyOf:
            - type: integer
            - type: 'null'
          title: Birth Day
        age:
          anyOf:
            - type: integer
            - type: 'null'
          title: Age
        work_email:
          anyOf:
            - type: string
            - type: 'null'
          title: Work Email
        mobile_phone:
          anyOf:
            - type: string
            - type: 'null'
          title: Mobile Phone
        linkedin_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Linkedin Url
        linkedin_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Linkedin Id
        city:
          anyOf:
            - type: string
            - type: 'null'
          title: City
        state:
          anyOf:
            - type: string
            - type: 'null'
          title: State
        state_code:
          anyOf:
            - type: string
            - type: 'null'
          title: State Code
        country:
          anyOf:
            - type: string
            - type: 'null'
          title: Country
        country_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Country Code
        job_title:
          anyOf:
            - type: string
            - type: 'null'
          title: Job Title
        company_name:
          anyOf:
            - type: string
            - type: 'null'
          title: Company Name
        company_domain:
          anyOf:
            - type: string
            - type: 'null'
          title: Company Domain
        company_industry:
          anyOf:
            - type: string
            - type: 'null'
          title: Company Industry
        company_size:
          anyOf:
            - type: string
            - type: 'null'
          title: Company Size
        company_legion_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Company Legion Id
        company_linkedin_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Company Linkedin Url
        company_linkedin_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Company Linkedin Id
        seniority_level:
          anyOf:
            - type: string
            - type: 'null'
          title: Seniority Level
        job_function:
          anyOf:
            - type: string
            - type: 'null'
          title: Job Function
        expense_category:
          anyOf:
            - type: string
            - type: 'null'
          title: Expense Category
        is_decision_maker:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Decision Maker
        is_platform_worker:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Platform Worker
        years_of_experience:
          anyOf:
            - type: integer
            - type: 'null'
          title: Years Of Experience
        avg_tenure_months:
          anyOf:
            - type: number
            - type: 'null'
          title: Avg Tenure Months
        highest_degree_level:
          anyOf:
            - type: string
            - type: 'null'
          title: Highest Degree Level
        current_jobs_last_confirmed:
          anyOf:
            - type: string
            - type: 'null'
          title: Current Jobs Last Confirmed
        current_jobs_last_updated:
          anyOf:
            - type: string
            - type: 'null'
          title: Current Jobs Last Updated
        current_location_last_confirmed:
          anyOf:
            - type: string
            - type: 'null'
          title: Current Location Last Confirmed
        current_location_last_updated:
          anyOf:
            - type: string
            - type: 'null'
          title: Current Location Last Updated
        linkedin_followers:
          anyOf:
            - type: integer
            - type: 'null'
          title: Linkedin Followers
        linkedin_connections:
          anyOf:
            - type: integer
            - type: 'null'
          title: Linkedin Connections
        headline:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        summary:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        num_sources:
          anyOf:
            - type: integer
            - type: 'null'
          title: Num Sources
        last_seen:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Seen
        build_version:
          anyOf:
            - type: string
            - type: 'null'
          title: Build Version
        phones:
          items:
            $ref: '#/components/schemas/PhoneResponse'
          type: array
          title: Phones
          default: []
        emails:
          items:
            $ref: '#/components/schemas/EmailResponse'
          type: array
          title: Emails
          default: []
        locations:
          items:
            $ref: '#/components/schemas/LocationResponse'
          type: array
          title: Locations
          default: []
        experience:
          items:
            $ref: '#/components/schemas/ExperienceResponse'
          type: array
          title: Experience
          default: []
        education:
          items:
            $ref: '#/components/schemas/EducationResponse'
          type: array
          title: Education
          default: []
        certifications:
          items:
            $ref: '#/components/schemas/CertificationResponse'
          type: array
          title: Certifications
          default: []
        socials:
          items:
            $ref: '#/components/schemas/SocialResponse'
          type: array
          title: Socials
          default: []
        skills:
          items:
            $ref: '#/components/schemas/SkillResponse'
          type: array
          title: Skills
          default: []
        languages:
          items:
            $ref: '#/components/schemas/LanguageResponse'
          type: array
          title: Languages
          default: []
      type: object
      required:
        - legion_id
      title: PersonResponse
      description: Complete person enrichment response.
    MatchMetadata:
      properties:
        matched_on:
          items:
            type: string
          type: array
          title: Matched On
          description: Fields that matched between request and person
        match_type:
          type: string
          title: Match Type
          description: 'Type of match: exact, fuzzy, or partial'
        match_confidence:
          type: string
          title: Match Confidence
          description: 'Match confidence level: high, moderate, or low'
      type: object
      required:
        - match_type
        - match_confidence
      title: MatchMetadata
      description: Metadata about the match.
    CleanedRawResponse:
      properties:
        cleaned:
          anyOf:
            - type: string
            - type: 'null'
          title: Cleaned
        raw:
          items:
            type: string
          type: array
          title: Raw
          default: []
      type: object
      title: CleanedRawResponse
      description: >-
        Generic {cleaned, raw[]} structure used for titles, degrees, headlines,
        summaries, skills, languages, and certification names/institutions.
    PhoneResponse:
      properties:
        type:
          anyOf:
            - type: string
            - type: 'null'
          title: Type
        number:
          anyOf:
            - type: string
            - type: 'null'
          title: Number
        current:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Current
        confidence:
          anyOf:
            - type: string
            - type: 'null'
          title: Confidence
        last_seen:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Seen
        num_sources:
          anyOf:
            - type: integer
            - type: 'null'
          title: Num Sources
      type: object
      title: PhoneResponse
      description: Phone number response.
    EmailResponse:
      properties:
        address:
          anyOf:
            - type: string
            - type: 'null'
          title: Address
        type:
          anyOf:
            - type: string
            - type: 'null'
          title: Type
        current:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Current
        validated:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Validated
        confidence:
          anyOf:
            - type: string
            - type: 'null'
          title: Confidence
        last_seen:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Seen
        num_sources:
          anyOf:
            - type: integer
            - type: 'null'
          title: Num Sources
        validation_status:
          anyOf:
            - type: string
            - type: 'null'
          title: Validation Status
        hash_sha256:
          anyOf:
            - type: string
            - type: 'null'
          title: Hash Sha256
        hash_sha1:
          anyOf:
            - type: string
            - type: 'null'
          title: Hash Sha1
        hash_md5:
          anyOf:
            - type: string
            - type: 'null'
          title: Hash Md5
      type: object
      title: EmailResponse
      description: Email response.
    LocationResponse:
      properties:
        street_address:
          anyOf:
            - type: string
            - type: 'null'
          title: Street Address
        address_line_2:
          anyOf:
            - type: string
            - type: 'null'
          title: Address Line 2
        city:
          anyOf:
            - type: string
            - type: 'null'
          title: City
        state:
          anyOf:
            - type: string
            - type: 'null'
          title: State
        state_code:
          anyOf:
            - type: string
            - type: 'null'
          title: State Code
        country:
          anyOf:
            - type: string
            - type: 'null'
          title: Country
        country_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Country Code
        continent:
          anyOf:
            - type: string
            - type: 'null'
          title: Continent
        continent_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Continent Code
        postal_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Postal Code
        postal_code_4:
          anyOf:
            - type: string
            - type: 'null'
          title: Postal Code 4
        geo:
          anyOf:
            - type: string
            - type: 'null'
          title: Geo
        raw:
          items:
            type: string
          type: array
          title: Raw
          default: []
        current:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Current
        num_sources:
          anyOf:
            - type: integer
            - type: 'null'
          title: Num Sources
        confidence:
          anyOf:
            - type: string
            - type: 'null'
          title: Confidence
        last_seen:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Seen
      type: object
      title: LocationResponse
      description: Location response.
    ExperienceResponse:
      properties:
        title:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        seniority_level:
          anyOf:
            - type: string
            - type: 'null'
          title: Seniority Level
        job_function:
          anyOf:
            - type: string
            - type: 'null'
          title: Job Function
        expense_category:
          anyOf:
            - type: string
            - type: 'null'
          title: Expense Category
        is_decision_maker:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Decision Maker
        is_platform_worker:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Platform Worker
        organization:
          anyOf:
            - $ref: '#/components/schemas/ExperienceOrganizationResponse'
            - type: 'null'
        start_date:
          anyOf:
            - type: string
            - type: 'null'
          title: Start Date
        end_date:
          anyOf:
            - type: string
            - type: 'null'
          title: End Date
        current:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Current
        tenure_months:
          anyOf:
            - type: integer
            - type: 'null'
          title: Tenure Months
        description:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
      type: object
      title: ExperienceResponse
      description: Experience entry response.
    EducationResponse:
      properties:
        organization:
          anyOf:
            - $ref: '#/components/schemas/EducationOrganizationResponse'
            - type: 'null'
        degree:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        degree_level:
          anyOf:
            - type: string
            - type: 'null'
          title: Degree Level
        field_of_study:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        start_date:
          anyOf:
            - type: string
            - type: 'null'
          title: Start Date
        end_date:
          anyOf:
            - type: string
            - type: 'null'
          title: End Date
        current:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Current
      type: object
      title: EducationResponse
      description: Education entry response.
    CertificationResponse:
      properties:
        name:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        institution:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        credential_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Credential Id
        issue_date:
          anyOf:
            - type: string
            - type: 'null'
          title: Issue Date
        expiration_date:
          anyOf:
            - type: string
            - type: 'null'
          title: Expiration Date
      type: object
      title: CertificationResponse
      description: Certification entry response.
    SocialResponse:
      properties:
        network:
          anyOf:
            - type: string
            - type: 'null'
          title: Network
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: Url
        username:
          anyOf:
            - type: string
            - type: 'null'
          title: Username
        id:
          anyOf:
            - type: string
            - type: 'null'
          title: Id
        current:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Current
        num_sources:
          anyOf:
            - type: integer
            - type: 'null'
          title: Num Sources
        confidence:
          anyOf:
            - type: string
            - type: 'null'
          title: Confidence
        last_seen:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Seen
      type: object
      title: SocialResponse
      description: Social response.
    SkillResponse:
      properties:
        cleaned:
          anyOf:
            - type: string
            - type: 'null'
          title: Cleaned
        raw:
          items:
            type: string
          type: array
          title: Raw
          default: []
      type: object
      title: SkillResponse
      description: Skill response.
    LanguageResponse:
      properties:
        cleaned:
          anyOf:
            - type: string
            - type: 'null'
          title: Cleaned
        raw:
          items:
            type: string
          type: array
          title: Raw
          default: []
        proficiency:
          anyOf:
            - type: string
            - type: 'null'
          title: Proficiency
      type: object
      title: LanguageResponse
      description: Language response.
    ExperienceOrganizationResponse:
      properties:
        name:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        website:
          anyOf:
            - type: string
            - type: 'null'
          title: Website
        linkedin_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Linkedin Url
        linkedin_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Linkedin Id
        industry:
          anyOf:
            - type: string
            - type: 'null'
          title: Industry
        size:
          anyOf:
            - type: string
            - type: 'null'
          title: Size
        legion_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Legion Id
      type: object
      title: ExperienceOrganizationResponse
      description: Organization within an experience entry.
    EducationOrganizationResponse:
      properties:
        name:
          anyOf:
            - $ref: '#/components/schemas/CleanedRawResponse'
            - type: 'null'
        website:
          anyOf:
            - type: string
            - type: 'null'
          title: Website
        linkedin_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Linkedin Url
      type: object
      title: EducationOrganizationResponse
      description: Organization within an education entry.
  headers:
    TotalCountStatus:
      description: >-
        `exact` when the response `total` is the full row count matching the
        WHERE clause across the database. `estimate` when the exact count
        exceeded its time budget (broad, low-selectivity queries) and `total` is
        the query planner's row estimate (a rough magnitude, not a precise
        figure). `page` when neither was available and `total` is just the size
        of the returned page.
      schema:
        type: string
        enum:
          - exact
          - estimate
          - page
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      in: header
      name: API-Key

````