---
title: "Person email"
description: "POST /v1/person/email — a name and company domain, or a LinkedIn URL, in; the person's verified work email out (or null)."
canonical: "https://kingminos.com/docs/api/person-email/"
sourceKind: "source-mdx"
---

import TryItLink from '../../../../components/docs/TryItLink.astro';

`POST https://api.kingminos.com/v1/person/email`

<TryItLink method="POST" path="/v1/person/email" />

Send what you have, top level or under `person`:
- **Name route:** `first_name` + `last_name` + `company_domain` (`domain` is an alias). A full name packed into `first_name` with `last_name` blank is split.
- **LinkedIn route:** `linkedin_url`. A LinkedIn company page is `400 invalid_linkedin_url`.

Send one route or both. A name without a domain, or a domain without a name and no `linkedin_url`, is `400 validation_failed` (`insufficient_input`). KingMinos never guesses an address from a naming pattern.

You get back the person's work email, for outbound sequencing and CRM email fill. Only verified addresses are delivered.

`person.email` answers for API tenant keys (`osr_…`). It does not stamp Salesforce Contacts or Leads.

```bash
curl 'https://api.kingminos.com/v1/person/email' \
  -H 'Authorization: Bearer <your-key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "first_name": "Anna",
    "last_name": "Example",
    "company_domain": "example.com",
    "routing": { "path": "balance" }
  }'
```

## Paths and price

You pay for the outcome, not the call. A delivered email (`found`) bills the path's price **once**. Everything else costs **0**: not found, `conflict`, `catch_all`, a person or domain mismatch, an answer below your confidence floor, and a timeout.

| `routing.path` | What it does | Credits on a delivered email |
| --- | --- | --- |
| `speed` | One email finder. A second runs when the first found nothing, or alongside a slow first finder so it still answers in time. | 2 |
| `balance` (default) | `speed`, then an independent mailbox check on the found address. | 2.5 |
| `accuracy` | Two finders. The independent check runs when only one found the address. | 3.5 |
| `coverage` | `accuracy`, plus the LinkedIn route when you sent `linkedin_url`. When the finders return two different addresses, each is checked independently, and the one that passes is delivered (see Confidence). | 5 |

Lookups stop 8 s after the request starts on `speed` and `balance`, and 10 s after on `accuracy` and `coverage`.

**Your own vendor key (BYOK):** when the finder that decided the answer ran on a key you stored under [Vendor keys](/docs/api/credentials/), a delivered email bills a flat 0.1 credit instead of the path price. You pay your vendor directly.

**Legacy aliases** (`value`, `auto`, `fast`, `name_only`) are `400 invalid_routing`. Send one of the four paths.

**Vendor isolation:** `routing.only` and `routing.ignore` limit which vendors a path may use. An unknown provider returns `400 unknown_provider`. A `routing.max_provider_credits` below the path price returns `max_credits_reached` before anything runs (0 credits).

## What comes back

| Layer | Fields | Use |
| --- | --- | --- |
| Control | `es_decision`, `answer.outcome`, `answer.confidence` | Whether to stamp. |
| Answer | `result.email`, `result.email_status` | The address. `email_status` is `valid` on `found`. |
| Evidence | `result.status`, `result.route`, `result.confidence`, `result.flags`, `result.candidates`, `result.person` | Humans and logs. |
| Billing | `usage.credits`, `usage.hops` | What ran and what was billed. |

`result.route` is `name` or `linkedin`: the identifier that found the address. On `found`, `result.candidates` has one row per source with `email` and `agrees`, and `result.person` echoes the identity you sent. On anything else `result.email` is `null`, `result.person` is `null`, and `result.candidates` carries no address.

**Outcomes:**

| `answer.outcome` / reason | What happened | Credits |
| --- | --- | --- |
| `found` | A verified work email at or above your floor. | path price |
| `conflict` | Sources returned two different addresses and nothing settled it. No address. | 0 |
| `catch_all` | The domain accepts every address, so the mailbox cannot be proven. Withheld. | 0 |
| `not_found` / `sources_disagree` | The independent mailbox check said the found address is invalid. | 0 |
| `not_found` / `person_mismatch` | Sources only returned someone else. | 0 |
| `not_found` / `below_min_confidence` | Below your confidence floor. The confidence is kept. | 0 |
| `not_found` / `zero_hits` | Nothing found. | 0 |
| `not_found` / `compliance_blocked` | The found address belongs to someone who asked not to be looked up. Withheld. | 0 |
| `not_found` / `provider_error` | A source failed or timed out. Retry later. | 0 |

**Stamp rule:** write `result.email` on a billed `found` answer when `answer.confidence` meets your floor.

**Confidence:** two independent sources agreeing on the address give `high`: two finders returning it, or one finder plus a `valid` independent mailbox check. One source gives `medium`. On `coverage`, two different addresses are each checked by the other finder's independent mailbox check: when exactly one passes and the other fails, the passing address is delivered at `low` with the `conflict_settled_by_check` flag. Otherwise it stays a `conflict`. The other paths never settle a conflict.

**Confidence floors:** `speed` and `coverage` default to `low`, `balance` to `medium`, `accuracy` to `high`. Send `min_confidence` (`high`, `medium` or `low`) to override. Below the floor the address comes back blank, the confidence stays, and the call costs 0.

**Identity checks.** A wrong person's email is worse than none, so these are dropped before anything is delivered:
- a source person whose first or last name conflicts with yours (`person_mismatch`);
- an address on a different company's domain (`domain_mismatch`);
- a personal mailbox such as a free consumer address (`personal_mailbox`). This endpoint returns work emails.

`next_steps` suggests a retry only when it adds a step, for example `coverage` after a below-floor answer, or after a miss when you sent both a name + domain and a `linkedin_url`.

### Flags

| Flag | Meaning |
| --- | --- |
| `finders_agree` | Two finders returned the same address. |
| `verified_by_second_vendor` | An independent mailbox check confirmed the address. |
| `single_source` | One source answered. |
| `person_mismatch` | A source returned someone else, which was dropped. |
| `domain_mismatch` | A source returned an address on another domain, which was dropped. |
| `personal_mailbox` | A source returned a personal mailbox, which was dropped. |
| `conflict_settled_by_check` | `coverage` only: two different addresses came back, and independent checks passed this one and failed the other. Delivered at `low`. |

## Cache

Delivered emails are cached for 30 days. Misses are not cached. The cache key includes the names, `company_domain`, the LinkedIn slug, the path, `min_confidence` and `routing.only` / `ignore`. A repeat call replays with `usage.cached: true` at 0 credits.

To skip the cache read, send one of:
- `skip_cache: true`;
- `X-Router-Cache: bypass`;
- `Cache-Control: no-cache`.

`DELETE /v1/subjects/email:<address>` (the found email) or `li:<slug>` erases cached answers and the runs behind them.

`dry_run: true` is offline and instant: no lookups, not cached, 0 credits.

## Errors

`400 validation_failed` with one of these reasons:
- `insufficient_input`
- `invalid_linkedin_url`
- `invalid_domain`
- `min_confidence`

Also `400 invalid_routing`, `400 unknown_provider` and `400 invalid_compliance`. A `linkedin_url` whose owner asked not to be looked up returns `451 subject_suppressed` at 0 credits; do not retry. Business misses stay HTTP `200`.
