Skip to content
looot docs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Verify an email address

Check whether an email address is deliverable before you send to it, read the status looot normalizes across providers, and know what a catch-all or risky result means.

people.email.verify checks one address at a time. Use it on addresses you already have, or after people.email.find on an address you just found (see Enrich a lead list).

What it costs

Read the live price with search before you run a batch:

search {"filters": {"capability": "people.email.verify"}, "prefer": "cheapest"}

On 2026-09-28 the cheapest listed people.email.verify provider priced around $0.0019 per call. Multiply by the number of addresses and check balance first for a batch.

Run the check

Send email. Add fallback so a provider that cannot reach the mailbox does not end the check.

run {"endpointId": "job:people.email.verify", "input": {"email": "jane.doe@example.com"}, "idempotencyKey": "verify-jane-doe-1", "fallback": true}
curl -s "https://api.looot.ai/v1/runs?wait=20" \
  -H "Authorization: Bearer $LOOOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "endpointId": "job:people.email.verify",
    "input": {"email": "jane.doe@example.com"},
    "idempotencyKey": "verify-jane-doe-1",
    "fallback": true
  }'
looot run job:people.email.verify \
  --input '{"email": "jane.doe@example.com"}' \
  --wait

Read the status

normalized.fields.status is one of five values:

Status What it means
valid the mailbox exists and accepts mail
invalid the mailbox does not exist or the domain rejects it
catch_all the domain accepts any address at it, so this one is unproven either way
risky the provider found signals against sending (a role address, a disposable domain, a full mailbox)
unknown the provider could not reach a verdict, or answered with something looot does not recognize

normalized.fields.deliverable is a plain true/false, present only when the provider itself reports deliverability as a separate field.

Decide what to do with each status

  • valid: safe to send to.
  • invalid: drop it.
  • catch_all and risky: do not send automatically. Show these to a person, or run a second provider with fallback and compare.
  • unknown: treat like catch_all, and note which provider answered (servedProviderId) in case a different one does better on that domain.

What the answer looks like

Field What it is
status run status: completed, failed, queued, running
outcome hit, weak, miss, error, rejected, skipped or pending
servedProviderId the provider that actually answered
actualCost what this run charged
normalized.fields email, status, deliverable
route.summary fallback runs only, e.g. “zerobounce: guessed ($0.01). hunter: found ($0.0245). Charged $0.0345.”

On a miss or error

  • The provider cannot reach a verdict: status is unknown, outcome is often miss. With fallback, the next provider gets a try inside the same hold.
  • A malformed address never reaches a provider: the run fails with validation_error and charges nothing. The error names the field, e.g. “email: not-an-email is not an email address”.
  • insufficient_balance: the run is blocked and not charged. Use top_up, then retry with a new idempotencyKey.

Was this page helpful?