---
title: "Email verify"
description: "POST /v1/email/verify — one email address in, one deliverability status out (valid, invalid, catch_all or unknown)."
canonical: "https://kingminos.com/docs/api/email-verify/"
sourceKind: "source-mdx"
---

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

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

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

Send one `email` (required, at most 320 characters). You get back whether the mailbox is deliverable: `valid`, `invalid`, `catch_all` or `unknown`. Use it for list hygiene before a send.

The address is lower-cased and look-alike host spellings are folded to one host before anything runs. A malformed address is an answer, not an error: it comes back `invalid` at 0 credits, so a junk row in a list still gets a status.

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

```bash
curl 'https://api.kingminos.com/v1/email/verify' \
  -H 'Authorization: Bearer <your-key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "anna@example.com",
    "routing": { "path": "accuracy" }
  }'
```

## How it checks

1. **Free local checks.** Syntax, reserved domains, and whether the domain exists and can receive mail. A failure here is `invalid` with `result.source: "local"` and costs 0. A DNS error or timeout never decides; the call moves on.
2. **Mailbox checks.** Independent mailbox checks answer the rest (`result.source: "vendor"`). How many run depends on the path.

## Paths and price

You pay for the outcome, not the call. A delivered `valid` or `invalid` from a mailbox check bills the path's price **once**. Everything else costs **0**: `catch_all`, `unknown`, a free local `invalid`, an answer below your confidence floor, checks that disagree, and a timeout.

| `routing.path` | What it does | Credits on a delivered answer |
| --- | --- | --- |
| `speed` | One mailbox check. A second runs only when the first did not answer. | 0.5 |
| `balance` (default) | One mailbox check, plus a second opinion when the first is inconclusive. | 1 |
| `accuracy` | Two independent checks. Delivers only when both agree. | 1.5 |
| `coverage` | Two independent checks. One conclusive check is enough to deliver. | 1.5 |

Checks 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 check that decided the answer ran on a key you stored under [Vendor keys](/docs/api/credentials/), a delivered answer 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. The free local checks always run. 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 send. |
| Answer | `result.status`, `result.email` | The status and the normalized address. |
| Evidence | `result.source`, `result.confidence`, `result.flags`, `result.mx_provider`, `result.checked_at`, `result.candidates` | Humans and logs. |
| Billing | `usage.credits`, `usage.hops` | What ran and what was billed. |

`result.candidates` has one row per mailbox check with its status and normalized verdict. There is no `person` and no name or employer on the response: a mailbox check is not a person lookup.

**Statuses:**

| `result.status` | Meaning | `es_decision` | Credits |
| --- | --- | --- | --- |
| `valid` | The mailbox accepts mail. | `hit` | path price |
| `invalid` (from a mailbox check) | The mailbox does not exist. | `hit` | path price |
| `invalid` (`source: "local"`) | Malformed address, reserved domain, or a domain that cannot receive mail. | `hit` | 0 |
| `catch_all` | The domain accepts every address, so a mailbox cannot be proven. Withheld. | `ambiguous` | 0 |
| `unknown` / `sources_disagree` | Checks disagree. Confidence `low`, flag `vendor_disagreement`. | `ambiguous` | 0 |
| `unknown` / `below_min_confidence` | Below your confidence floor. The withheld confidence is kept. | `miss` | 0 |
| `unknown` / `zero_hits` | No check could decide. | `miss` | 0 |
| `unknown` / `provider_error` | A check failed or timed out. Retry later. | `error` | 0 |

**Confidence:** two agreeing checks, or a free local `invalid`, give `high`. One check gives `medium`. Checks that disagree give `low` with status `unknown`.

**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 status comes back `unknown`, the confidence stays, and the call costs 0.

**Send rule:** send to `valid`. Do not send to `invalid`. Treat `catch_all` and `unknown` as unproven and decide by your own policy.

`next_steps` suggests a retry only when another path could change the answer, for example `balance` after a `speed` `unknown`. A `catch_all` or a split between checks gets no retry.

### Flags

Flags describe the mailbox. They never change the status.

| Flag | Meaning |
| --- | --- |
| `role_based` | A role address such as `sales@` or `info@`. |
| `free_mailbox` | A free consumer mailbox provider. |
| `disposable` | A disposable or temporary mailbox. |
| `relay` | A relay address. |
| `security_gateway` | The domain's mail passes through a security gateway. |
| `vendor_disagreement` | Checks disagreed. Status is `unknown`. |

## Cache and dry run

Answers are not cached. Every call runs fresh.

`dry_run: true` is offline and instant: no DNS lookup and no mailbox check, 0 credits.

## Errors

`400 validation_failed` with one of these reasons:
- `email_required`
- `email_too_long`
- `min_confidence`

Also `400 invalid_routing`, `400 unknown_provider` and `400 invalid_compliance`. An address whose owner asked not to be looked up returns `451 subject_suppressed` at 0 credits; do not retry, and suppress it in your own systems. Business misses stay HTTP `200`.
