# Reverse Email Lookup

Finds the person behind an email address, work or personal, and returns their full LinkedIn profile and their company: up to 25 addresses per call, each with its own entry in `results`, in the order you sent them.

A person found costs 1 credit. An address nobody matches, or a value that is not an email address, costs nothing. The same address twice in one call is looked up and charged once, and so is the same person behind two addresses.

The profile has the same fields as Enrich People. The company is the employer of the current position, plus the domain of the address when it is a work address; for the full company profile, send it to Enrich Companies. The address itself is not checked over SMTP: for a verified work email, use Enrich People with `include_email`.

## Authentication

Send your API key as a Bearer token: `Authorization: Bearer gtk_…`. Create the key under **Connect assistant → API keys**. A missing, invalid or revoked key is **401**, including while an API is closed. On an endpoint of the Signals API or the Company API, a valid key while that API is closed for your organization answers **403** `api_not_enabled`, with what the key can do instead; the other endpoints work with every key. Every response includes `mySDR-Api-Version`, `mySDR-Request-Id` and `Cache-Control: no-store`, and a response to an accepted key also `X-RateLimit-*` (so not a 401, a 405, an OPTIONS or a 404 for an unknown path); every error has `type`, `message`, `param` and `request_id`.

### Body parameters

- **`emails`** `string[]` · **required** — 1 to 25 email addresses, work or personal, e.g. `jane@acme.example`.
- **`max_credits`** `integer` — Stop before the call costs more than this. An address is looked up only while a person still fits, at 1 credit, in the order you sent them; an address that finds nobody costs nothing and leaves the room to the next. Addresses left over are not looked up and get `skipped`.

## Response

- **`results`** `object[]` — One entry per address you sent, in the same order.
- **`results[].input`** `string` — The address as you sent it.
- **`results[].status`** `string` — `matched` (see `person` and `company`), `not_found` (nobody known with this address), `invalid_email` (not an email address), `error` (the lookup failed; nothing was charged, retry later) or `skipped` (`max_credits` left no room; not looked up). One of: `matched`, `not_found`, `invalid_email`, `error`, `skipped`.
- **`results[].person`** `object | null` — The profile when the status is `matched`, with the fields of Enrich People (without `email`); otherwise null.
- **`results[].company`** `object | null` — `name` and `linkedin_url` of the current employer (null when the profile shows none), and `domain`: the domain of the address when it is a work address, otherwise null. Null unless the status is `matched`.
- **`results[].credits_charged`** `integer` — What this entry cost. An address you sent twice is charged on its first entry.
- **`results[].save_input`** `object` — With a matched person: this person as one entry of `leads` for POST /tables/leads, with the address you sent as `email` (no `email_status`: the address was not checked).
- **`results[].error`** `object` — With `error` and `skipped`: `type` (`upstream_error` or `max_credits_exceeded`) and `message`.
- **`credits_used`** `integer` — Credits this call used.

## Credits

1 credit per person found; nobody found costs nothing. Errors and empty lookups are free. A call that spent credits puts that number in `credits_used`, in `X-Credits-Used` and in `X-Credits-Charged`. When the wallet can be read, the response also sends `X-Credits-Remaining`.

## Errors

- **400** `invalid_request` — The body is not valid JSON, a field is unknown or has the wrong type, or a value is not allowed.
- **401** `authentication_error` — The Authorization header is missing, or the key is unknown or revoked.
- **403** `permission_error` — API access is not part of your plan, or your account is suspended.
- **429** `rate_limit_error` — More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header.
- **429** `daily_limit_reached` — The request could take your organization over its daily credit limit. The limit resets at midnight (Europe/Brussels).
- **502** `upstream_error` — The data source did not answer. Retry later.
- **503** `service_unavailable` — The API is temporarily unavailable. Retry later.
- **500** `internal_error` — Something went wrong on our side.
- **402** `max_credits_exceeded` — max_credits is below the price of one lookup (1 credit). Nothing was looked up.

## Example

### cURL

```bash
curl -X POST "https://mysdr.app/api/v1/person/reverse-email" \
  -H "Authorization: Bearer $MYSDR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "emails": [
      "jane@acme-analytics.example",
      "nobody@example.com"
    ]
  }'
```

### JavaScript

```javascript
const response = await fetch('https://mysdr.app/api/v1/person/reverse-email', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.MYSDR_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "emails": [
      "jane@acme-analytics.example",
      "nobody@example.com"
    ]
  })
});
const body = await response.json();
```

### Python

```python
import json
import os
import urllib.request

payload = {
  "emails": [
    "jane@acme-analytics.example",
    "nobody@example.com"
  ]
}

request = urllib.request.Request(
    "https://mysdr.app/api/v1/person/reverse-email",
    headers={
    "Authorization": f"Bearer {os.environ['MYSDR_API_KEY']}",
    "Content-Type": "application/json"
    },
    data=json.dumps(payload).encode(),
    method="POST",
)
with urllib.request.urlopen(request) as response:
    body = json.load(response)
```

### Example response

```json
{
  "results": [
    {
      "input": "jane@acme-analytics.example",
      "status": "matched",
      "person": {
        "linkedin_url": "https://www.linkedin.com/in/jane-example",
        "linkedin_id": "ACwAAExample123",
        "public_identifier": "jane-example",
        "first_name": "Jane",
        "last_name": "Example",
        "full_name": "Jane Example",
        "headline": "CFO at Acme Analytics",
        "about": null,
        "location": {
          "text": "Ghent, Flemish Region, Belgium",
          "city": "Ghent",
          "state": "Flemish Region",
          "country": "Belgium",
          "country_code": "BE"
        },
        "picture_url": null,
        "connections_count": 500,
        "follower_count": 1204,
        "open_to_work": false,
        "hiring": false,
        "premium": true,
        "current_positions": [
          {
            "title": "Chief Financial Officer",
            "company_name": "Acme Analytics",
            "company_linkedin_url": "https://www.linkedin.com/company/acme-analytics",
            "location": "Ghent, Belgium",
            "employment_type": "Full-time",
            "workplace_type": "Hybrid",
            "start_date": {
              "year": 2026,
              "month": 7
            },
            "end_date": null,
            "is_current": true,
            "duration": "3 mos",
            "description": null
          }
        ],
        "experience": [
          {
            "title": "Chief Financial Officer",
            "company_name": "Acme Analytics",
            "company_linkedin_url": "https://www.linkedin.com/company/acme-analytics",
            "location": "Ghent, Belgium",
            "employment_type": "Full-time",
            "workplace_type": "Hybrid",
            "start_date": {
              "year": 2026,
              "month": 7
            },
            "end_date": null,
            "is_current": true,
            "duration": "3 mos",
            "description": null
          }
        ],
        "education": [
          {
            "school_name": "Ghent University",
            "school_linkedin_url": null,
            "degree": "Master of Science",
            "field_of_study": "Business Economics",
            "start_date": {
              "year": 2008,
              "month": null
            },
            "end_date": {
              "year": 2012,
              "month": null
            },
            "description": null
          }
        ],
        "skills": [
          "Financial Planning",
          "M&A"
        ],
        "languages": [
          {
            "name": "Dutch",
            "proficiency": "Native or bilingual proficiency"
          }
        ],
        "certifications": []
      },
      "company": {
        "name": "Acme Analytics",
        "linkedin_url": "https://www.linkedin.com/company/acme-analytics",
        "domain": "acme-analytics.example"
      },
      "credits_charged": 1,
      "save_input": {
        "name": "Jane Example",
        "linkedin_url": "https://www.linkedin.com/in/jane-example",
        "title": "Chief Financial Officer",
        "headline": "CFO at Acme Analytics",
        "company": "Acme Analytics",
        "company_linkedin_url": "https://www.linkedin.com/company/acme-analytics",
        "location": "Ghent, Flemish Region, Belgium",
        "country_code": "BE",
        "email": "jane@acme-analytics.example"
      }
    },
    {
      "input": "nobody@example.com",
      "status": "not_found",
      "person": null,
      "company": null,
      "credits_charged": 0
    }
  ],
  "credits_used": 1
}
```
