curl --request POST \
--url https://api.finowl.co/v1/email/validate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"email": "jane@gmail.com"
}
'{
"email": "jane@gmail.com",
"verdict": "valid",
"reason": "accepted",
"syntax_valid": true,
"local_part": "jane",
"domain": "gmail.com",
"domain_exists": true,
"mx_found": true,
"mx_records": [
"gmail-smtp-in.l.google.com",
"alt1.gmail-smtp-in.l.google.com",
"alt2.gmail-smtp-in.l.google.com",
"alt3.gmail-smtp-in.l.google.com",
"alt4.gmail-smtp-in.l.google.com"
],
"mail_provider": "google",
"disposable": false,
"role": false,
"free_provider": true,
"did_you_mean": null
}Validate an email
Check whether an email address can receive mail, and catch typos, disposable and role addresses.
curl --request POST \
--url https://api.finowl.co/v1/email/validate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"email": "jane@gmail.com"
}
'{
"email": "jane@gmail.com",
"verdict": "valid",
"reason": "accepted",
"syntax_valid": true,
"local_part": "jane",
"domain": "gmail.com",
"domain_exists": true,
"mx_found": true,
"mx_records": [
"gmail-smtp-in.l.google.com",
"alt1.gmail-smtp-in.l.google.com",
"alt2.gmail-smtp-in.l.google.com",
"alt3.gmail-smtp-in.l.google.com",
"alt4.gmail-smtp-in.l.google.com"
],
"mail_provider": "google",
"disposable": false,
"role": false,
"free_provider": true,
"did_you_mean": null
}Good to know
- Branch on
verdict.validmeans send,invalidmeans the address cannot receive mail, andriskymeans it probably can but deserves a second look. Usereasonto explain why. validis about the domain, not the mailbox. Finowl never connects to the mail server, so it cannot tell whetherjane@exists at a valid domain. Confirm ownership with a verification email when it matters.riskyhas two causes.disposableaddresses work but are usually thrown away within hours.a_record_fallbackmeans the domain has no MX record, which often means mail was never set up.- Offer
did_you_mean, don’t apply it. Forjane@gmail.co, show “Did you mean jane@gmail.com?” and let the user accept it. The address they typed might be correct. - Bad syntax is a
200, not an error. Send raw form input and readreason: invalid_syntax. Only an empty or over-long string returnsinvalid_input. - Send internationalized domains as punycode. Convert
jane@münchen.detojane@xn--mnchen-3ya.defirst. Unicode domains returnreason: invalid_syntax. roledoesn’t change the verdict. Addresses likesupport@are real, but they reach a team, not a person.dns_unavailableis free. If DNS doesn’t answer, the request returns503and is not charged. Try again after a short delay.
Guide: sign-up fraud checks
Authorizations
Your Finowl API key, for example finowl_3f9a.... Create keys in the dashboard under API Keys.
Body
The address to validate. Leading and trailing spaces are removed. Any string from 1 to 254 characters is accepted, so you can send raw form input and read the verdict. Send internationalized domains in punycode (xn--) form. Unicode domains return invalid_syntax.
1 - 254"jane@gmail.co"
Response
The check completed. invalid and risky verdicts are still successful responses.
The address that was checked, after trimming.
The overall answer. Branch on this.
valid: the syntax is correct and the domain accepts mail. The mailbox itself is not probed.risky: the address can probably receive mail, but it is disposable or the domain has no MX record and relies on its A or AAAA record.invalid: the address cannot receive mail.
valid, risky, invalid The most important reason for the verdict.
accepted(valid): the domain has mail servers.invalid_syntax(invalid): the address is not a well-formed email address.domain_not_found(invalid): the domain does not exist in DNS.null_mx(invalid): the domain publishes a null MX record (RFC 7505), which means it accepts no mail.no_mail_server(invalid): the domain has no MX record and no A or AAAA record.disposable(risky): the domain is a known disposable email service.a_record_fallback(risky): the domain has no MX record, so mail would go to its A or AAAA record (RFC 5321). This often means mail is not set up.
accepted, invalid_syntax, domain_not_found, null_mx, no_mail_server, disposable, a_record_fallback true when the address is well formed.
The part before the @. Empty when the syntax is invalid and it cannot be found.
The part after the @, lowercased. Empty when the syntax is invalid and it cannot be found.
true when the domain exists in DNS. false when the syntax is invalid.
true when the domain publishes at least one usable MX record.
The domain's mail server hostnames, most preferred first, lowercase and without a trailing dot. At most 10. Empty when none were found.
10Who runs the domain's mail servers, detected from the MX hostnames. other for any other host. null when there is no MX record. Treat values you don't recognize like other.
google, microsoft, yahoo, apple, zoho, proton, yandex, mimecast, proofpoint, fastmail, gmx, ovh, amazon_ses, other, null true when the domain, or a parent domain, is on the open-source list of disposable email services.
true when the local part, ignoring any +tag, is a role mailbox such as admin, info, sales, support or noreply. Role addresses are usually shared by a team. This does not change the verdict.
true when the domain is a free personal mailbox provider such as gmail.com, outlook.com or web.de.
A corrected address when the domain looks like a typo of a popular mail domain, such as gmail.co for gmail.com. null otherwise. Suggest it to the user. Never replace the address without asking.