List single-email validation results

Download OpenAPI spec
GET /api/v1/verify
API key required Base https://api.emailvalidator.ai 60 requests per minute per account

List the single-email validations submitted with this API key's account, newest first. This is how a result is recovered when its id was not kept: every other read is by id, and an id you no longer hold cannot be guessed.

In-flight checks are listed too, with status: pending and a null result — so a verification submitted with a callback_url is findable before it finishes, not only after. Filter on status to select one lifecycle, on outcome to select a verdict, or on both.

Only work submitted through the API is returned — validations run from the web dashboard belong to the dashboard, not to this key.

Paging — the response is a cursor-paged list object. Follow next_cursor as starting_after to walk towards older results; pass it as ending_before to walk back towards newer ones. has_more tells you whether another page exists in the direction you are walking, and next_cursor is present only when it does. A cursor that will not decode is 400 invalid_request with param naming the parameter it arrived in — answering the first page instead would give the while (has_more) drain loop a fresh cursor forever. Omitting the parameter is still the first page, and a cursor that decodes but points past the end is still an empty page.

Retention — results are removed 7 days after submission. Once removed, a check is indistinguishable from one that never existed and GET /api/v1/verify/{id} answers 404.

On this page

Parameters

query · parameters

ParameterTypeDescription
limit integer 1–100 · default 25 Number of results to return per page. Values outside 1–100 are clamped. example: 25
starting_after string Cursor from a previous response's next_cursor. Returns the page of results immediately after it, walking towards older results. example: MTc0OTU2NzIwMDAwMDAwMDAwfDNmYTg1...
ending_before string Cursor from a previous response. Returns the page of results immediately before it, walking back towards newer results. Ignored when starting_after is also supplied, and — like starting_after — a value that will not decode is rejected with 400 invalid_request rather than silently treated as the first page, even when starting_after would have taken precedence. example: MTc0OTU2NzIwMDAwMDAwMDAwfDNmYTg1...
status string Return only verifications in this LIFECYCLE state. Matched case-insensitively; any other value — including a verdict word like deliverable — is a 400 naming status, rather than a silently unfiltered list. The two filters have separate vocabularies on purpose. pending complete example: complete
outcome string Return only verifications carrying this VERDICT. Matched case-insensitively; any other value — including a lifecycle word like pending — is a 400 naming outcome. Only completed verifications can match one, since a pending check has no outcome. deliverable invalid catch-all unknown example: deliverable

Responses

200
A page of validation results, newest first. · application/json
400
The status filter is not one of the documented lifecycle states, the outcome filter is not one of the documented verdicts, or a supplied starting_after / ending_before cursor could not be decoded. All are code: invalid_request with param naming the offending parameter. · application/json
401
Missing or invalid API key. · application/json
403
The API key authenticated but is not scoped for this endpoint (code: insufficient_scope). It is a 403 rather than a 401 on purpose — the credential is valid, so retrying with it can never help; a key holding the read scope is needed. · application/json
429
Rate limit exceeded. · application/json
500
Unexpected server error. The body carries code internal_error plus a request_id to quote in a support request, and never any exception detail. · application/json

Response schema · 200 · VerificationList

A cursor-paged page of single-email verifications, newest first.
FieldTypeDescription
object string Always list — the discriminator that marks a paged collection. list example: list
data array of object The verifications on this page, ordered newest first — in-flight ones included, with status: pending. credits_remaining is null on a list row: a balance is a per-request figure, so read it from GET /api/v1/credits.
has_more boolean Whether more results exist beyond this page in the direction being paged. There is no total count: a cursor walk reveals it, and a per-page count would be stale on arrival. example: true
next_cursor string Opaque cursor for the next page, present only when has_more is true. Send it back as starting_after to continue forwards, or as ending_before to continue backwards. example: MTc0OTU2NzIwMDAwMDAwMDAwfDNmYTg1...

data · Verification · array of object

A single-email verification. This ONE object is what every representation of the resource returns: the synchronous 200, the 202 that accepts an async or timed-out request, both states of GET /api/v1/verify/{id}, every row of GET /api/v1/verify, and the verify.completed webhook payload.

Two axes. status is the LIFECYCLE (pending or complete) and never carries a verdict. The verdict is result.outcome, in the same vocabulary the CSV export and the dashboard use. result and recovery are both null while pending, because a check that has not finished has reached no conclusion — the terminal unknown is a conclusion, not an absence of one.

Test and live are separate namespaces. livemode says which one this verification belongs to, and a key only ever sees resources of its own mode: a sandbox (ev_test_) key cannot list or fetch a live verification, and a live key never sees a canned sandbox one.

FieldTypeDescription
object string Always verification — the discriminator that marks this resource type. verification example: verification
id string · uuid The verification's ID, present on every representation. Pass it to GET /api/v1/verify/{id}. example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
created_at string · date-time UTC timestamp when the verification was accepted. It does not change when the verification completes, which is what makes the list's cursor stable while checks finish. example: 2025-06-10T14:02:09.180Z
livemode boolean true when the verification was submitted with a LIVE key; false when it came from an ev_test_ sandbox key and the verdict is therefore a canned test result rather than a real probe. Test and live are separate namespaces — a key only ever sees resources of its own mode — so this is constant for any one key, and it is what makes a stored response, a log line or a webhook body self-describing after the fact. example: true
status string

The verification's LIFECYCLE — and only its lifecycle:

  • pending — accepted and still running. result and recovery are both null.
  • complete — finished. result carries the verdict.

It never carries a verdict word. A client can switch on it without knowing whether the check happened to finish inside the request.

pending complete example: complete
email string The address as submitted. A recovery never replaces it. example: alice@example.com
result object · null The verdict. null while status is pending.
recovery object · null A probe-confirmed alternative address, when contact recovery found one. null while pending, and null when no recovery was surfaced.
completed_at string · date-time · null UTC timestamp when the verification finished. null while pending. example: 2025-06-10T14:02:11.432Z
credits_remaining integer · null Credit balance after this request. null for system/demo accounts, and null on list rows, webhook payloads and SSE frames — a balance is a per-request figure, so read it from GET /api/v1/credits. example: 4820
result_url string Where to fetch the finished verification. Present only while status is pending; once complete you are already holding what it would point at. example: /api/v1/verify/3fa85f64-5717-4562-b3fc-2c963f66afa6
callback_secret string

A per-verification override of the account signing secret, revealed EXACTLY ONCE — on the 202 that accepts a request carrying a callback_url. It is deliberately absent from GET /api/v1/verify/{id}, from list rows and from the webhook payload. Verifying with the account secret (whsec_…) works without it.

Shape: cs_ + 64 hex characters for a single verification (bv_ + 64 hex for a batch job). It is NOT whsec_-shaped — that prefix belongs to the ACCOUNT signing secret, a different value with a different lifetime.

example: cs_9f2a4c6e...

result · VerificationResult · object

The verdict. null while status is pending.
FieldTypeDescription
outcome string

The verification VERDICT, carried by result.outcome (and accepted by the list's outcome filter):

  • deliverable — mailbox confirmed deliverable via SMTP.
  • invalid — mailbox does not exist or hard-rejected.
  • catch-all — domain accepts all addresses; deliverability unconfirmable.
  • unknown — could not determine (DNS failure, transient error, or no SMTP probe data).
deliverable invalid catch-all unknown example: deliverable
sub_status string Additional signal within the top-level status. Empty string when none applies. Derivation is first-match: disposable > role_based > accept_all > no_dns_entries > mailbox_not_found > greylisted > mail_server_did_not_respond. "" disposable role_based accept_all no_dns_entries mailbox_not_found greylisted mail_server_did_not_respond example: ""
risk string

Deliverability risk, assessed at PROBE TIME from everything the check observed — not derived from outcome, and not derivable from the other fields in this object. It reads the SMTP conversation's real status, the domain's mail-server state, DNS transience and the address's own syntax, several of which are not reported anywhere else on this response. So it is a genuinely independent signal, and it will sometimes disagree with what outcome and details on their own would suggest.

Broadly: high for a definitive rejection, a disposable domain, a domain with no mail server, or a structurally suspect address (a quoted or commented local part); medium for an accept-all domain, a role address, a non-ASCII local part, or a mailbox whose probe was DEFERRED by the server (a 4xx temporary failure — a real, common case whose outcome is unknown); low for a free-mail domain or an address we could not verify conclusively; none for a clean, confirmed mailbox with no such signal. Treat the four values as an ordered scale rather than as a formula over the other fields.

Returned for both live and test-mode keys (a test-mode key returns the canned risk the address's local part maps to). OMITTED — not reported as none — whenever the check carries no recorded assessment. This rule is WIDER than free_email's and details': those two are withheld only when the stored probe detail cannot be read, while risk is also absent on a healthy row that has no stored detail at all (a check completed before this became a recorded value, until it is backfilled), and while a check is still pending. An absent risk means unknown, never none.

none low medium high example: none
free_email boolean Whether the domain is a known free-email provider. Derived from the stored probe detail, so it is OMITTED — not reported as false — on the rare row whose stored detail cannot be read; see details. example: false
account string Local part of the email address (before @). example: alice
domain string Domain part of the email address (after @). example: example.com
details object Low-level DNS/SMTP signal. OMITTED on the rare row whose stored probe detail exists but cannot be read — a server-side data fault. The verdict in outcome comes from a separate, intact field and stays trustworthy, so the detail is withheld rather than reported as a row of falses that would read as a confident all-clear. A row that simply has no stored detail is not that case and still returns this object with its default values.

details · VerifyDetails · object

Low-level DNS/SMTP signal. OMITTED on the rare row whose stored probe detail exists but cannot be read — a server-side data fault. The verdict in outcome comes from a separate, intact field and stays trustworthy, so the detail is withheld rather than reported as a row of falses that would read as a confident all-clear. A row that simply has no stored detail is not that case and still returns this object with its default values.
FieldTypeDescription
role boolean Whether the local part is a role alias (e.g. admin, support, noreply). example: false
disposable boolean Whether the domain belongs to a known disposable/temporary email provider. example: false
catch_all boolean Whether the domain is configured to accept all addresses. example: false
mx_found boolean Whether at least one MX record was found for the domain. example: true
mx_record string · null The highest-priority MX hostname, or null when no MX records exist. example: mail.example.com
smtp_provider string · null Detected SMTP provider name (e.g. Google, Microsoft), or null when unknown. example: Google
smtp_code integer · null SMTP response code from the final RCPT TO probe, or null when no SMTP probe was attempted. example: 250

recovery · VerificationRecovery · object

A probe-confirmed alternative address, when contact recovery found one. null while pending, and null when no recovery was surfaced.
FieldTypeDescription
email string The recovered address. Never a substitute for email — that is what you sent. example: alice@gmail.com
outcome string deliverable when a probe confirmed a mailbox at the recovered address; catch-all when the fix landed on a domain that accepts everything. Drawn from the same vocabulary as result.outcome and the CSV's Outcome column, and identical to the CSV's RecoveredOutcome cell for the same row. deliverable catch-all example: deliverable

Error responses

400 401 403 429 500 · ApiProblem · object

Standard error response shape used by all error status codes.
FieldTypeDescription
status required integer HTTP status code mirrored in the body. example: 400
code required string Stable, machine-readable error code. Branch your code on this — never on the error text, which is prose and may be reworded at any time. example: invalid_email
error required string Human-readable error message. example: Invalid email format.
param string The request field the failure is attributable to. Omitted when the failure is not about one specific field. example: email
details array of string · null Optional per-field validation messages. Null when not applicable. example: ["email: required"]
doc_url string Link to the documentation for this error code. example: https://emailvalidator.ai/docs/get-started/errors
request_id string Correlation id for this request. Quote it in a support request — it is how a single call is found in the server logs. example: 0HNCV1TQ3PLRK:00000003

Example response · 200

{
  "object": "list",
  "data": [
    {
      "object": "verification",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "created_at": "2025-06-10T14:02:09.180Z",
      "livemode": true,
      "status": "complete",
      "email": "alice@example.com",
      "result": {
        "outcome": "deliverable",
        "sub_status": "",
        "risk": "none",
        "free_email": false,
        "account": "alice",
        "domain": "example.com",
        "details": {
          "role": false,
          "disposable": false,
          "catch_all": false,
          "mx_found": true,
          "mx_record": "mail.example.com",
          "smtp_provider": "Google",
          "smtp_code": 250
        }
      },
      "recovery": "openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464",
      "completed_at": "2025-06-10T14:02:11.432Z",
      "credits_remaining": "openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464"
    },
    {
      "object": "verification",
      "id": "8c1d0f22-9a44-4e31-b0aa-6f2e5c7d1234",
      "created_at": "2025-06-10T14:02:10.006Z",
      "livemode": true,
      "status": "pending",
      "email": "bob@example.com",
      "result": "openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464",
      "recovery": "openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464",
      "completed_at": "openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464",
      "credits_remaining": "openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464",
      "result_url": "/api/v1/verify/8c1d0f22-9a44-4e31-b0aa-6f2e5c7d1234"
    }
  ],
  "has_more": true,
  "next_cursor": "MTc0OTU2NzIwMDAwMDAwMDAwfDNmYTg1..."
}