API Documentation

Integrate email validation into your application with a simple REST API. Validate single addresses in real time or process entire lists in bulk.

MCP

Not writing code? Connect your AI assistant instead

The same validation runs over the Model Context Protocol, so Claude, Cursor, or any MCP client can call it directly — OAuth sign-in, no API key. Point your client at https://mcp.mailrook.com/mcp.

MCP setup guide

Quick start

Validate an email address with a single request:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.mailrook.com/v1/validate/[email protected]

Authentication

All API requests require a Bearer token in the Authorization header. Generate your API key from the dashboard after signing up.

Authorization: Bearer YOUR_API_KEY

Base URL

https://api.mailrook.com

Endpoints

GET /v1/validate/{email}

Validate a single email

Validates one email address and returns detailed verification results. Typical response time is under 500ms.

Path parameters

email
string, required

The email address to validate (e.g. [email protected])

Query parameters

include
string, optional

Comma-separated list of extra data to include. Currently supported: enrichment. When provided, an enrichment object is added to the response containing website, tech stack, company, DNS, and WHOIS data.

Example request

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.mailrook.com/v1/validate/[email protected]

Example response

{
    "data": {
        "id": "673603dc-42da-474c-98cf-531ce11b1bf2",
        "email": "[email protected]",
        "normalized_email": "[email protected]",
        "username": "elon",
        "domain": "x.com",
        "mx_record": "aspmx.l.google.com",
        "provider": "google_workspace",
        "score": 80,
        "isv_format": true,
        "isv_domain": true,
        "isv_deliverable": true,
        "isv_nocatchall": false,
        "isv_nogeneric": true,
        "isv_nodisposable": true,
        "isv_nofreeemail": false,
        "isv_nouniversity": true,
        "result": "risky",
        "reason": "catch_all",
        "reason_label": "Catch-all domain (accepts all emails)",
        "email_security": [],
        "protection_level": "basic",
        "domain_info": {
            "has_spf": true,
            "has_dmarc": true,
            "has_website": true,
            "domain_age_days": 8450,
            "domain_created_at": "2003-03-17T00:00:00+00:00",
            "domain_expires_at": "2026-03-17T00:00:00+00:00",
            "registrar": "CSC Corporate Domains, Inc.",
            "registrant_org": "X Corp.",
            "registrant_country": "US",
            "ns_hosts": [
                "ns1.p09.dynect.net",
                "ns2.p09.dynect.net"
            ],
            "a_record_ip": "104.244.42.193",
            "asn": "AS13414",
            "asn_org": "Twitter Inc.",
            "email_security": [],
            "protection_level": "basic"
        }
    },
    "code": 0,
    "message": "ok"
}

Example request with enrichment

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.mailrook.com/v1/validate/[email protected]?include=enrichment

Example response with enrichment

{
    "data": {
        "id": "673603dc-42da-474c-98cf-531ce11b1bf2",
        "email": "[email protected]",
        "normalized_email": "[email protected]",
        "username": "elon",
        "domain": "x.com",
        "mx_record": "aspmx.l.google.com",
        "provider": "google_workspace",
        "score": 80,
        "isv_format": true,
        "isv_domain": true,
        "isv_deliverable": true,
        "isv_nocatchall": false,
        "isv_nogeneric": true,
        "isv_nodisposable": true,
        "isv_nofreeemail": false,
        "isv_nouniversity": true,
        "result": "risky",
        "reason": "catch_all",
        "reason_label": "Catch-all domain (accepts all emails)",
        "email_security": [],
        "protection_level": "basic",
        "domain_info": {
            "has_spf": true,
            "has_dmarc": true,
            "has_website": true,
            "domain_age_days": 8450,
            "domain_created_at": "2003-03-17T00:00:00+00:00",
            "domain_expires_at": "2026-03-17T00:00:00+00:00",
            "registrar": "CSC Corporate Domains, Inc.",
            "registrant_org": "X Corp.",
            "registrant_country": "US",
            "ns_hosts": [
                "ns1.p09.dynect.net",
                "ns2.p09.dynect.net"
            ],
            "a_record_ip": "104.244.42.193",
            "asn": "AS13414",
            "asn_org": "Twitter Inc.",
            "email_security": [],
            "protection_level": "basic"
        },
        "enrichment": {
            "domain": "example.com",
            "website": {
                "url": "https://example.com",
                "title": "Example Domain",
                "is_reachable": true,
                "is_crawl_blocked": false
            },
            "tech_stack": {
                "cms": "wordpress",
                "ecommerce": null,
                "pixels": [
                    "meta_pixel"
                ],
                "analytics": [
                    "google_analytics"
                ],
                "marketing": [],
                "chat": [],
                "affiliate": [],
                "email_security": [
                    "proofpoint"
                ]
            },
            "social_links": {
                "twitter": "example",
                "linkedin": "company/example",
                "github": "example"
            },
            "company": {
                "name": "Example Inc.",
                "industry": "Technology",
                "size": "51-200",
                "type": "Private",
                "founded": 2010,
                "city": "San Francisco",
                "state": "CA",
                "country_code": "US"
            },
            "dns": {
                "has_spf": true,
                "has_dmarc": true,
                "ns_hosts": [
                    "ns1.example.com"
                ],
                "a_record_ip": "93.184.216.34",
                "asn": "AS15133",
                "asn_org": "Edgecast Inc."
            },
            "whois": {
                "registrar": "RESERVED-Internet Assigned Numbers Authority",
                "registrant_org": "IANA",
                "registrant_country": "US",
                "domain_created_at": "1995-08-14T00:00:00+00:00",
                "domain_expires_at": "2025-08-13T00:00:00+00:00",
                "domain_age_days": 10818
            }
        }
    },
    "code": 0,
    "message": "ok"
}
POST /v1/validate/batch

Submit a batch of emails

Submit an array of email addresses for bulk validation. Returns a list ID that you can poll for results.

Request body

emails
array of strings, required

Array of email addresses to validate

Example request

curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["[email protected]", "[email protected]"]}' \
  https://api.mailrook.com/v1/validate/batch

Example response (201 Created)

{
    "data": {
        "list_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "emails_count": 2
    },
    "code": 0,
    "message": "ok"
}
POST /v1/validate/batch/upload

Upload a file for batch validation

Upload a CSV or TXT file containing one email per line. Maximum file size is 10 MB.

Request body (multipart/form-data)

file
file, required

A .csv or .txt file with one email address per line (max 10 MB)

Example request

curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "[email protected]" \
  https://api.mailrook.com/v1/validate/batch/upload

Example response

{
    "data": {
        "list_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "emails_count": 150
    },
    "code": 0,
    "message": "ok"
}
GET /v1/validate/list/{list_id}

Get batch results

Retrieve the results of a batch validation. Returns 202 while processing is in progress and 200 when complete.

Path parameters

list_id
string (UUID), required

The list ID returned from the batch submit or upload endpoint

Example request

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.mailrook.com/v1/validate/list/a1b2c3d4-e5f6-7890-abcd-ef1234567890

Response while processing (202)

{
    "data": [],
    "code": 0,
    "message": "List is still processing: 45 of 100 emails done"
}

Example response

{
    "data": [
        {
            "email": "[email protected]",
            "isv_format": true,
            "isv_domain": true,
            "isv_deliverable": true,
            "isv_nocatchall": true,
            "isv_nogeneric": true,
            "isv_nodisposable": true,
            "isv_nofreeemail": true,
            "isv_nouniversity": true,
            "protection_level": "enterprise"
        }
    ],
    "code": 0,
    "message": "ok"
}
GET /v1/enrich/{input}

Enrich a domain or email

Returns enrichment data for a domain or email address without performing email deliverability validation. Includes website info, tech stack, company data, DNS records, and WHOIS information.

Path parameters

input
string, required

An email address (e.g. [email protected]) or domain (e.g. example.com). When an email is provided, the domain is extracted automatically.

Example request

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.mailrook.com/v1/enrich/example.com

Example response

{
    "data": {
        "domain": "example.com",
        "website": {
            "url": "https://example.com",
            "title": "Example Domain",
            "is_reachable": true,
            "is_crawl_blocked": false
        },
        "tech_stack": {
            "cms": "wordpress",
            "ecommerce": null,
            "pixels": [
                "meta_pixel"
            ],
            "analytics": [
                "google_analytics"
            ],
            "marketing": [],
            "chat": [],
            "affiliate": [],
            "email_security": [
                "proofpoint"
            ]
        },
        "social_links": {
            "twitter": "example",
            "linkedin": "company/example",
            "github": "example"
        },
        "company": {
            "name": "Example Inc.",
            "industry": "Technology",
            "size": "51-200",
            "type": "Private",
            "founded": 2010,
            "city": "San Francisco",
            "state": "CA",
            "country_code": "US"
        },
        "dns": {
            "has_spf": true,
            "has_dmarc": true,
            "ns_hosts": [
                "ns1.example.com"
            ],
            "a_record_ip": "93.184.216.34",
            "asn": "AS15133",
            "asn_org": "Edgecast Inc."
        },
        "whois": {
            "registrar": "RESERVED-Internet Assigned Numbers Authority",
            "registrant_org": "IANA",
            "registrant_country": "US",
            "domain_created_at": "1995-08-14T00:00:00+00:00",
            "domain_expires_at": "2025-08-13T00:00:00+00:00",
            "domain_age_days": 10818
        }
    },
    "code": 0,
    "message": "ok"
}

Enrichment fields

The enrichment object is returned by the /v1/enrich/{input} endpoint and optionally included in validation responses via ?include=enrichment.

Field Type Description
domain string The domain that was enriched
website
website.url string|null Resolved website URL
website.title string|null Page title from the website
website.is_reachable boolean Whether the website is reachable
website.is_crawl_blocked boolean Whether crawling is blocked by the website
tech_stack
tech_stack.cms string|null Detected CMS (e.g. wordpress, shopify)
tech_stack.ecommerce string|null Detected e-commerce platform
tech_stack.pixels array Tracking pixels detected (e.g. meta_pixel, tiktok_pixel)
tech_stack.analytics array Analytics tools (e.g. google_analytics, hotjar)
tech_stack.marketing array Marketing tools (e.g. hubspot, mailchimp)
tech_stack.chat array Chat/support widgets (e.g. intercom, zendesk)
tech_stack.affiliate array Affiliate/referral tools
tech_stack.email_security array Email security providers detected from MX records (e.g. proofpoint, mimecast)
social_links
social_links object|null Social media handles found on the website. Keys: twitter, instagram, facebook, youtube, tiktok, linkedin, github. Values are normalized handles/paths (e.g. "acme", "company/acme", "@acme").
company
company.name string|null Company name
company.industry string|null Industry classification
company.size string|null Employee count range (e.g. 51-200)
company.type string|null Company type (e.g. Private, Public)
company.founded integer|null Year founded
company.city string|null City
company.state string|null State or region
company.country_code string|null ISO 3166-1 alpha-2 country code
dns
dns.has_spf boolean|null Domain has an SPF record
dns.has_dmarc boolean|null Domain has a DMARC record
dns.ns_hosts array|null Nameserver hostnames
dns.a_record_ip string|null Primary A record IP address
dns.asn string|null Autonomous System Number
dns.asn_org string|null ASN organization name
whois
whois.registrar string|null Domain registrar
whois.registrant_org string|null Registrant organization
whois.registrant_country string|null Registrant country code
whois.domain_created_at string|null Domain registration date (ISO 8601)
whois.domain_expires_at string|null Domain expiration date (ISO 8601)
whois.domain_age_days integer|null Domain age in days since registration

Enrichment provider keys

Both /v1/enrich/{input} and /v1/validate/{email}?include=enrichment support third-party enrichment providers for deeper data. Pass provider API keys via the X-Enrich-Providers header as a JSON object:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  -H 'X-Enrich-Providers: {"snov": "your-snov-api-key"}' \
  https://api.mailrook.com/v1/enrich/example.com

Provider keys are never stored — they are only used for the current request. More providers will be added over time.

Response fields

Field Type Description
id string Unique identifier for this validation
email string The email address that was validated
normalized_email string Normalized form of the email (dots removed, +tags stripped, alias domains canonicalized)
username string Local part of the email (before @)
domain string Domain part of the email (after @)
mx_record string|null Primary MX record for the domain
provider string|null Detected email provider (e.g. gmail, google_workspace, microsoft_365, outlook, yahoo, protonmail, icloud, zoho, yandex, mailru, proofpoint, mimecast, aol, fastmail). Null if unknown.
score integer Overall quality score from 0 to 100
isv_format boolean Email has valid syntax (RFC compliant)
isv_domain boolean Domain exists and has valid DNS records
isv_deliverable boolean|null Mail server accepts email for this address. Null if unable to verify.
isv_nocatchall boolean|null Domain is not a catch-all (accepts mail for any address)
isv_nogeneric boolean Not a generic/role address (e.g. info@, support@)
isv_nodisposable boolean Not a disposable/temporary email address
isv_nofreeemail boolean Not from a free email provider (e.g. Gmail, Yahoo)
isv_nouniversity boolean Not from an educational institution domain
result string Overall result: deliverable, undeliverable, risky, or unknown
reason string Reason code: accepted_email, rejected_email, invalid_format, invalid_domain, disposable_email, catch_all, unable_to_verify, sender_blocked
reason_label string|null Human-readable reason label (e.g. "Mailbox not found"). Null for accepted_email.
email_security array Email security gateways detected from MX records (e.g. proofpoint, mimecast, barracuda). Empty array if none detected.
protection_level string Synthesized email protection level: none (no gateway or DMARC enforcement), basic (SPF + strict DMARC policy), or enterprise (dedicated security gateway like Proofpoint or Mimecast).
domain_info object|null Domain WHOIS and DNS information. Null if domain data is not yet available.
domain_info.has_spf boolean|null Domain has an SPF record
domain_info.has_dmarc boolean|null Domain has a DMARC record
domain_info.has_website boolean|null Domain has a reachable website
domain_info.domain_age_days integer|null Domain age in days since registration
domain_info.domain_created_at string|null Domain registration date (ISO 8601)
domain_info.domain_expires_at string|null Domain expiration date (ISO 8601)
domain_info.registrar string|null Domain registrar
domain_info.registrant_org string|null Registrant organization
domain_info.registrant_country string|null Registrant country code
domain_info.ns_hosts array|null Nameserver hostnames
domain_info.a_record_ip string|null Primary A record IP address
domain_info.asn string|null Autonomous System Number
domain_info.asn_org string|null ASN organization name
domain_info.email_security array Email security gateways (same as top-level email_security)
domain_info.protection_level string Protection level (same as top-level protection_level)

Credits & headers

Calls are metered in credits. Every authenticated response carries your balance, so an integration can pace itself without a second request.

What each call costs

Operation Credits Notes
GET /v1/validate/{email} 1 Per address.
GET /v1/validate/{email}?include=enrichment 3 The validation plus the enrichment lookup.
GET /v1/enrich/{input} 2 Per domain.
POST /v1/validate/batch 1 Per unique address. The list is de-duplicated first, and the whole batch is charged up front — a batch you cannot afford is rejected with 402 and nothing is charged.
POST /v1/validate/batch/upload 1 Per unique address, charged up front, same as the JSON batch.
GET /v1/validate/list/{list_id} 0 Reading results is free — the batch was already charged on submission, so polling costs nothing.

Balance headers

Returned on every authenticated response, including the 402. Credits are spent soonest-to-expire first: the daily allowance, then the plan allowance, then purchased credits.

Header Type Description
X-Credits-Remaining integer Everything spendable right now: today's free allowance, plus whatever the plan has left this period, plus purchased credits. This is the one number to poll — it is what runs out.
X-Credits-Free-Today integer Of that total, how much is today's free allowance. Resets at midnight UTC.
X-Credits-Plan integer Of that total, how much of the plan's monthly allowance is left this billing period. Absent on accounts with no plan.
X-Credits-Paid integer Of that total, the purchased balance. Purchased credits never expire and are spent last.
X-Plan string Key of the active plan. Absent on accounts with no plan.

The three bucket headers add up to X-Credits-Remaining; read the total unless you need to know which bucket a call will draw from. Headers for a bucket you do not have are omitted rather than sent as zero, so treat a missing header as "not applicable", not as "empty".

Running out

Once your balance cannot cover a call, it returns 402 and nothing is charged. The body says which allowance ran out and when it comes back, so an integration can back off until then rather than retrying into a wall:

{
    "data": null,
    "code": 402,
    "message": "Insufficient credits to validate",
    "details": {
        "reason": "free_allowance_exhausted",
        "plan": null,
        "daily_free_allowance": 25,
        "free_resets_at": "2026-01-02T00:00:00+00:00",
        "hint": "Your free allowance for today is used up and it resets at midnight. A plan gives you a monthly allowance instead.",
        "billing_url": "https://mailrook.com/billing"
    }
}
details.reason Meaning
free_allowance_exhausted No plan on the account and today's free allowance is spent. It comes back at free_resets_at.
plan_allowance_exhausted The plan's allowance for this billing period is spent and there is no purchased balance to fall back on.

Error responses

Every response carries the same envelope: data, a numeric code, and a message. On success code is 0; on failure it mirrors the HTTP status, and data is null.

HTTP Status Meaning
200 Success.
201 Batch accepted. The body carries the list_id to poll.
202 Batch still processing. The message reports how many of the addresses are done; poll again.
401 Missing or invalid API key.
402 Out of credits. See the credits section below — the body says which allowance ran out and when it comes back.
404 Unknown list id, or no such endpoint.
422 Invalid email format, unresolvable domain, or a missing required field.
500 Internal server error.

Rate limits

API requests are rate-limited per account. If you exceed your limit, you will receive a 429 response. Contact us if you need higher limits for your use case.

Ready to get started?

Create a free account and get your API key in seconds.

Get your API key