Validation
Groundmail validation checks an email address before you accept it or send to it. It works in two places:
- On every send, automatically: recipients that cannot receive email are held back before they bounce. See Recipients held back by Groundmail validation.
- On demand, with
POST /validate: one address at a time, for signup forms and imports.
Both are free. Validation never sends anything to the address.
Base URL: https://api.groundmail.dev
Authentication
Authorization: Bearer gm_…Any key with emails:send or emails:read (sending keys included). Call it from your server, never from the browser: the key must stay secret.
Validate an address
POST /validate
{ "email": "ada@gmial.com" }200
{
"email": "ada@gmial.com",
"domain": "gmial.com",
"verdict": "risky",
"reasons": ["possible_typo"],
"suggestion": "ada@gmail.com",
"disposable": false,
"role": false
}| Field | Meaning |
|---|---|
email |
The address as checked: trimmed and lowercased. |
domain |
Its domain, or null when it has none. |
verdict |
valid, risky or invalid (below). |
reasons |
Everything that was found, in a fixed order. Empty for a clean valid. |
suggestion |
The address with a likely-mistyped domain corrected (gmial.com → gmail.com, yahoo.con → yahoo.com), or null. |
disposable |
A throwaway-inbox service. |
role |
A team or queue mailbox (info@, support@, noreply@) rather than a person. |
Verdicts and reasons
verdict |
Reasons that lead to it | What to do |
|---|---|---|
invalid |
syntax (the address cannot exist), no_mail_server (the domain does not exist or takes no email), mailbox_not_found (the mailbox is known not to exist), previously_bounced (it hard-bounced for a Groundmail sender in the last 90 days) |
Reject it, or ask for another address. Mail to it would bounce. |
risky |
disposable, catch_all (the domain accepts every address, so the mailbox cannot be confirmed), possible_typo (see suggestion) |
Accept it, or ask "Did you mean …?" with suggestion. |
valid |
none, or only role |
Accept it. |
role is informational: role mailboxes receive email, so it never changes the verdict on its own. Whether to accept disposable and role addresses is your call; Groundmail never holds them back on send.
valid means nothing wrong was found, not that a person reads the mailbox. Validation does not open a connection to the recipient's mail server.
Errors
| Status | code |
When |
|---|---|---|
| 400 | validation_error |
email is missing or longer than 320 characters. |
| 401 | unauthorized |
Missing or invalid API key. |
| 403 | insufficient_scope |
The key has neither emails:send nor emails:read. |
| 429 | rate_limited |
More than 120 requests a minute or 5,000 an hour for this key. Wait for Retry-After. |
A malformed address is not an error: it returns 200 with verdict: "invalid" and reasons: ["syntax"].
On a signup form
import { Groundmail } from 'groundmail'
const groundmail = new Groundmail(process.env.GROUNDMAIL_API_KEY!)
export async function checkSignupEmail(email: string) {
const result = await groundmail.validate(email)
if (result.verdict === 'invalid') {
return { ok: false, message: 'That email address cannot receive email.' }
}
if (result.suggestion) {
return { ok: true, message: `Did you mean ${result.suggestion}?` }
}
return { ok: true }
}SDK
const result = await groundmail.validate('ada@gmial.com')
// result.verdict: 'valid' | 'risky' | 'invalid'CLI
groundmail validate ada@gmial.comExits 2 when the verdict is invalid.
MCP
The validate_email tool takes email and returns the same result.
curl
curl -X POST https://api.groundmail.dev/validate \
-H "Authorization: Bearer $GROUNDMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"ada@gmial.com"}'On send
The send-time checks are on by default. An account owner can turn off the two that draw on what Groundmail has seen across senders (previously_bounced and mailbox_not_found) in Settings → Suppressions; invalid addresses and domains with no mail server are always held back. Held-back recipients are not added to your suppression list.
OpenAPI
openapi/groundmail.yaml (validateEmail)