Sign inGet Started

Look up an email address

One call tells you whether an address will accept mail. Use it at signup, or before acting on a lead, to keep addresses that would bounce out of your sending in the first place. Everything here needs an API key with the lookup scope.

Look up an address

const answer = await bird.lookup.email({ email: "aisha.khan@example.com" });
// result is an open vocabulary; delivery_confidence is always comparable.
console.log(answer.result, answer.delivery_confidence);

Look up a batch

Use POST /v1/lookup/email/batch to assess up to 1,000 addresses in one request:
Code example
curl -X POST "https://us1.platform.bird.com/v1/lookup/email/batch" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"emails":["aisha.khan@example.com","not-an-email"]}'
The response's data array contains one assessment per input, in submission order. Malformed addresses receive individual assessments. Duplicate addresses remain separate entries and each answered entry is billed. Surrounding whitespace is trimmed and case is preserved.
Keep each request within 128 KiB. Split larger lists into separate batches. If you opt in to idempotent retries, use a distinct key for each batch. Responses up to 256 KiB can be retained for replay; larger responses are returned without replay protection, so retrying can perform and charge for another batch. See the batch API reference.

How to write the address

Send a bare address, exactly as you hold it. A single-address lookup rejects display-name forms such as Aisha <aisha@example.com> rather than unwrapping them. Batch lookups return an assessment for each submitted string.
The part before the @ is passed through as written rather than lowercased, and the email field preserves that case. Batch responses trim surrounding whitespace; match each result to the input at the same position. Send the address in the case you hold it rather than normalising it first: result is generally the same either way, but delivery_confidence is not always identical, so changing the case can change the answer you get.

The five verdicts

result is the field to decide on.
valid: the address exists and accepts mail. Send.
neutral: it could not be confirmed either way, usually because the receiving domain answers every recipient the same way. Sending is reasonable; a neutral address is not a bad address, it is an unanswerable one.
risky: it probably accepts mail but is likelier than most to bounce or complain. Role addresses, disposable addresses and low-reputation addresses land here. Whether to send is a judgement about your own tolerance for complaints, and flags tells you which kind of risk it is.
undeliverable: it does not accept mail. Do not send. reason says why: invalid_syntax for a malformed address, invalid_domain when the domain does not accept mail at all, invalid_recipient when the domain accepts mail but this mailbox does not exist.
typo: the address looks misspelled, and did_you_mean carries the correction. Offer the correction to whoever typed the original rather than sending to it unasked: it is a guess, and the address they meant may be neither one.
result is an open vocabulary, so a value you do not recognize is a future verdict rather than an error. Branch on the values you know and fall back on delivery_confidence, which is always present and always comparable.

Read confidence alongside the verdict, not instead of it

delivery_confidence runs from 0 (certain not to be delivered) to 100 (certain to be). The same score can sit under neutral or risky for different reasons, so it is a second opinion rather than a replacement for result. It is the field to lean on when you want one threshold across every verdict, including verdicts added later.
valid carries the provider's validity assessment. An invalid recipient can have valid: false even when its domain accepts mail. Use result and delivery_confidence together when deciding whether to send; valid: true does not guarantee delivery.

Flags describe the kind of address

flags is empty when nothing notable applies. Three values are defined today, and it is an open list.
role means the address names a function rather than a person, such as support@ or info@. Replies and consent are ambiguous, and complaints are likelier.
disposable means it belongs to a throwaway-address provider, so it will typically stop existing.
free_provider means it belongs to a consumer mailbox provider such as Gmail or Outlook.com. That is ordinary for consumer mail, and a signal only when you expected a business address.

Retry without paying twice

Every answered address is billed, undeliverable included, because that is the answer you paid for and the bounce you avoided. Send an Idempotency-Key so a retry replays the stored verdict instead of buying a second one. See Idempotency.
The GET form, which puts the address in the URL, cannot carry an idempotency key. Use the POST form for anything automated.

Errors

CodeWhat happened
E22003A single-address lookup received an invalid email address. Nothing was charged. Batch lookups assess malformed strings individually and bill those assessments.
E22001The organization's wallet cannot cover the lookup. Top it up and retry. Nothing was charged.
E22002Lookup is temporarily unavailable. Retry with backoff. Nothing was charged.

Next steps

Related resources

Continue with the documentation, guides and examples for this topic.