---
title: "Reverse Lookup by Email"
method: POST
path: "/v2/people/enrich/by-email"
tags: ["People"]
---

# Reverse Lookup by Email

`POST /v2/people/enrich/by-email`

## Request

- Base URL: `https://api.village.ai`
- URL: `https://api.village.ai/v2/people/enrich/by-email`
- Auth: HTTP bearer

Reverse email lookup: find out who an email address belongs to. If Village does not already know the address, it is sent to Apollo.io to identify its owner, and the match is saved to Village; a profile Village does not have yet is then fetched from HarvestAPI and saved too. Use this when a signup, inbound reply, or CRM row gives you only an email and you need the person behind it. Returns the same profile data as enrich_person — full name, headline, current title and company, location, profile photo URL, and LinkedIn URL. People can have their data removed by emailing privacy@village.ai or support@village.ai.

## Request body

- EnrichByEmailRequest: Request for reverse email lookup
  - `email` string, email, required: Work or personal email address of the person to look up
  - `mode` 'cached_first' | 'cached_only' | 'realtime_only': How to source the data. `cached_first` (default): return Village's cached profile if it is recent, otherwise fetch live — credited only when it fetches. `cached_only`: never fetch live, and report a miss when the profile is not already cached (404 on the single endpoints, a per-item not-found on the bulk ones) — never credited. `realtime_only`: always fetch live, and credited whenever that fetch returns data; a fetch that finds nothing is still free.

## Response `200`

Person found for this email

- object
  - `data` EnrichBasicResponse, required: Response for basic person enrichment
    - `full_name` string, required
    - `linkedin_url` string, required
    - `avatar` string
    - `headline` string, nullable, required: LinkedIn headline
    - `location` Location, nullable, required: Geographic location
      - `city` string, nullable
      - `state` string, nullable
      - `country` string, nullable
    - `work_relevant` WorkRelevant, nullable, required: Current or most relevant work position and company
      - `title` string, required
      - `start_date` string, nullable, required
      - `end_date` string, nullable, required
      - `company` object, nullable, required: Employer information, including employers not yet resolved to Postgres
        - `id` integer, nullable, required: Postgres company ID, or null when the employer has not been resolved
        - `name` string, required: Company name
        - `linkedin_url` string, uri, nullable: LinkedIn company page URL
        - `domain` string, nullable: Company website domain
        - `website` string, nullable: Company website stored in Postgres
        - `industry` string, nullable: Primary industry
        - `employee_count` integer, nullable: Number of employees
        - `image_url` string, uri, nullable: Company logo URL
        - `location` object, nullable: Company HQ location
          - `city` string, nullable
          - `state` string, nullable
          - `country` string, nullable
        - `headquarters` string, nullable: Raw headquarters string
        - `type` string, nullable: Company type (e.g. Public, Private)
        - `founded_year` integer, nullable: Year the company was founded
        - `funding` union: Funding data, passed through from storage as-is. Two shapes are possible and callers must handle both: an OBJECT summarising the most-recent round (keys `last_round_stage`, `price`, `investors`, `last_round_date`, `number_of_rounds`), or an ARRAY of per-round objects (keys `date`, `type`, `amount`, `currency`, `investors`) written by the refresh pipeline. An empty array means no funding data, which is the large majority of companies. All money, date and count fields are display strings, not numbers or ISO dates — don't parse or range-filter them.
          - object
            - `price` string, nullable
            - `investors` object[], nullable
              - …
            - `last_round_date` string, nullable
            - `last_round_stage` string, nullable
            - `number_of_rounds` union
              - …
          - object[]
            - `date` string, nullable
            - `type` string, nullable
            - `amount` union
              - …
            - `currency` string, nullable
            - `investors` string, nullable
          - unknown
    - `work_history` WorkExperience[], required
      - `title` string, required
      - `start_date` string, nullable, required
      - `end_date` string, nullable, required
      - `company` object, nullable, required: Employer information, including employers not yet resolved to Postgres
        - `id` integer, nullable, required: Postgres company ID, or null when the employer has not been resolved
        - `name` string, required: Company name
        - `linkedin_url` string, uri, nullable: LinkedIn company page URL
        - `domain` string, nullable: Company website domain
        - `website` string, nullable: Company website stored in Postgres
        - `industry` string, nullable: Primary industry
        - `employee_count` integer, nullable: Number of employees
        - `image_url` string, uri, nullable: Company logo URL
        - `location` object, nullable: Company HQ location
          - `city` string, nullable
          - `state` string, nullable
          - `country` string, nullable
        - `headquarters` string, nullable: Raw headquarters string
        - `type` string, nullable: Company type (e.g. Public, Private)
        - `founded_year` integer, nullable: Year the company was founded
        - `funding` union: Funding data, passed through from storage as-is. Two shapes are possible and callers must handle both: an OBJECT summarising the most-recent round (keys `last_round_stage`, `price`, `investors`, `last_round_date`, `number_of_rounds`), or an ARRAY of per-round objects (keys `date`, `type`, `amount`, `currency`, `investors`) written by the refresh pipeline. An empty array means no funding data, which is the large majority of companies. All money, date and count fields are display strings, not numbers or ISO dates — don't parse or range-filter them.
          - object
            - `price` string, nullable
            - `investors` object[], nullable
              - …
            - `last_round_date` string, nullable
            - `last_round_stage` string, nullable
            - `number_of_rounds` union
              - …
          - object[]
            - `date` string, nullable
            - `type` string, nullable
            - `amount` union
              - …
            - `currency` string, nullable
            - `investors` string, nullable
          - unknown
    - `last_enrichment_at` string, nullable, required: ISO 8601 timestamp of the last refresh from a third-party data provider. Null when the profile has never been provider-enriched (network-synced data only). Use it to judge staleness before paying for a realtime_only re-enrich.
  - `metadata` object, required
    - `request_id` string, required

## Other responses

- `400`: Bad request - invalid parameters
- `401`: Unauthorized - missing or invalid authentication
- `404`: No person found for this email address
- `503`: Enrichment temporarily unavailable - retry
- `504`: Enrichment timed out - retry

---

[API](https://skmtc.dev/village/apis/village-v2-api.md) - [All operations](https://skmtc.dev/village/apis/village-v2-api/llms.txt) - [OpenAPI document](https://skmtc.dev/village/apis/village-v2-api/revisions/aebe21a1a544?raw)
