Email check

Check one email address for throwaway domains, typos, missing mail servers, new domains, role inboxes and (optionally) the mailbox itself.

POST /v1/email/check · 1 credit (+5 with verify_mailbox)

Request

Field Type Required Description
email string yes The address to check.
verify_mailbox boolean no Also ask the domain's mail server whether this mailbox exists. Adds up to a few seconds and 5 credits. Charged only if the server was actually asked. Default false.
curl https://veqen-app.com/v1/email/check \
  -H "Authorization: Bearer $VEQEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "jane.doe+promo@gmial.com"}'
r = requests.post(
    "https://veqen-app.com/v1/email/check",
    headers={"Authorization": f"Bearer {VEQEN_API_KEY}"},
    json={"email": "jane.doe+promo@gmial.com"},
    timeout=10,
)
const r = await fetch("https://veqen-app.com/v1/email/check", {
  method: "POST",
  headers: { Authorization: `Bearer ${VEQEN_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ email: "jane.doe+promo@gmial.com" }),
});

You can also use GET /v1/email/check?email=... for quick tests. Prefer POST in production so addresses don't end up in URL logs.

Response

Typo domains like this are often registered by throwaway services, so this one is both a typo and disposable:

{
  "email": "jane.doe+promo@gmial.com",
  "valid_syntax": true,
  "normalized": "jane.doe+promo@gmial.com",
  "canonical": "jane.doe@gmial.com",
  "local_part": "jane.doe+promo",
  "domain": "gmial.com",
  "disposable": true,
  "free_provider": false,
  "role_account": false,
  "plus_addressed": true,
  "did_you_mean": "jane.doe+promo@gmail.com",
  "domain_info": {
    "exists": true,
    "accepts_mail": true,
    "mx": [],
    "null_mx": false,
    "spf": false,
    "dmarc": false,
    "registered_at": "2003-05-12",
    "age_days": 8562,
    "registrar": "GoDaddy.com, LLC"
  },
  "mailbox": null,
  "risk": {
    "score": 93,
    "level": "high",
    "verdict": "refuse",
    "reasons": [
      { "code": "disposable_domain", "impact": 90, "message": "gmial.com hands out throwaway inboxes." },
      { "code": "possible_typo", "impact": 30, "message": "Looks like a typo of gmail.com." },
      { "code": "plus_addressed", "impact": 5, "message": "Uses a +tag, so one inbox can sign up many times." }
    ]
  }
}

Fields

Field What it tells you
valid_syntax false means it isn't an email address at all. syntax_error then explains why.
normalized The address with a lower-cased, standard domain.
canonical The inbox it really lands in: +tags removed, and for Gmail, dots removed too. Compare this to spot one person making many accounts.
disposable The domain hands out throwaway inboxes (Mailinator, 10 Minute Mail and thousands more).
free_provider A consumer mailbox like Gmail or Outlook. Normal for people, unusual for a B2B signup.
role_account A shared inbox such as info@ or support@.
plus_addressed The address has a +tag.
did_you_mean A suggested fix for a likely typo. Show it: "Did you mean jane@gmail.com?"
domain_info.accepts_mail Whether mail can be delivered to the domain: it has MX records, or (as the email standard allows) an address record to fall back on. false means mail can never arrive. null means DNS couldn't be reached.
domain_info.mx Mail servers, most preferred first.
domain_info.age_days Days since the domain was registered, when the registry publishes it.
mailbox Only when verify_mailbox was true. result is deliverable, undeliverable, catch_all (the server accepts any address) or unknown.
risk Score, level, verdict and reasons. See risk scores and reasons.

Typical handling

risk = result["risk"]
if result.get("did_you_mean"):
    ask_user(f"Did you mean {result['did_you_mean']}?")
elif risk["verdict"] == "refuse":
    reject("Please use a permanent email address you can receive mail at.")
elif risk["verdict"] == "review":
    require_email_confirmation()
else:
    accept()

Frequently asked questions

Does the email check send an email?

No. We look at the address and its domain's DNS records. Even with verify_mailbox, we only start an SMTP conversation and stop before any message is sent.

Why is mailbox verification optional?

It's slower (up to a few seconds), some mail providers always answer "yes" (catch-all), and large providers like Gmail don't reveal whether a mailbox exists. For signup forms, the default check plus email confirmation is usually the best mix. Mailbox verification shines for cleaning lists of business addresses.