API Documentation

Everything you need to integrate MailCheck email verification into your application.

Official SDKs

Start integrating faster with our officially maintained SDKs

Node.js / TypeScript

npm install mailcheck-dev

import { MailCheck } from 'mailcheck-dev';

const mc = new MailCheck('sk_live_...');

// Verify a single email
const result = await mc.verify('user@example.com');
console.log(result.valid);       // true
console.log(result.score);       // 85

Python

pip install mailcheck-dev

from mailcheck import MailCheck

mc = MailCheck("sk_live_your_api_key")
result = mc.verify("user@example.com")
print(f"Valid: {result['valid']}")
print(f"Score: {result['score']}")

Both SDKs support single email verification, bulk verification, and email authentication analysis with full TypeScript/Python type safety.

JavaScript Widget

Embed real-time email verification directly into your website forms

Add the widget script to your HTML and it will automatically validate all email input fields on your page. No complex setup required.

Installation

Add this script tag to your HTML (replace pk_live_your_key with your public API key from the Widget Keys page):

<script src="https://api.mailcheck.dev/widget.js" data-key="pk_live_your_key"></script>

Configuration

Customize the widget using data attributes:

<script src="https://api.mailcheck.dev/widget.js"
          data-key="pk_live_your_key"
          data-color="#10B981"
          data-position="below"
          data-selector="input[type="email"]"></script>
AttributeDefaultDescription
data-keyrequiredYour public API key (starts with pk_live_)
data-color#10B981Primary color for validation indicators
data-positionbelowWhere to show feedback: below or above the input
data-selectorinput[type="email"]CSS selector for email inputs to validate

Features

  • Real-time validation — Checks email on blur with 300ms debounce
  • Visual feedback — Shows checkmark for valid emails, error for invalid
  • Typo suggestions — Suggests corrections for common typos (e.g., gmial.comgmail.com)
  • Dynamic form support — Automatically detects newly added email inputs via MutationObserver
  • Fail open — If validation service is unavailable, forms still submit normally

Getting a Public Key

Public keys are different from API keys. Create one at /dashboard/keys to get a key starting with pk_live_. These keys are restricted to specific domains for security.

API Usage

The widget uses the /v1/verify endpoint with GET requests. Results include typo suggestions that the widget displays as clickable links.

Authentication

All API requests require a Bearer token in the Authorization header.

Authorization: Bearer sk_live_your_api_key_here

Get your API key from the API Keys page. Keep it secret — treat it like a password.

Verify Email

POST /v1/verify

Verify a single email address. Returns validation results including syntax, disposable detection, and DNS/MX checks.

Request Body

{
  "email": "user@example.com"
}

Rate Limits

Plan Rate Limit Monthly Quota
Free 10 requests/minute 100 verifications
Starter 60 requests/minute 5,000 verifications
Pro 120 requests/minute 25,000 verifications
Enterprise Unlimited Custom

All API responses include rate limit headers: X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.

Response (200)

{
  "email": "user@example.com",
  "valid": true,
  "score": 90,
  "reason": "deliverable",
  "checks": {
    "syntax": "pass",
    "disposable": "pass",
    "mx": "pass",
    "smtp": "pass",
    "role": "pass",
    "free_provider": true
  },
  "details": {
    "mxHost": "mx1.example.com",
    "is_role": false,
    "is_free_provider": true,
    "free_provider_name": "Gmail",
    "is_disposable": false,
    "has_typo_suggestion": false,
    "risk_level": "low",
    "catch_all": false
  },
  "cached": false,
  "credits_remaining": 4850
}

Caching: Results are cached for 30 days. Subsequent verifications of the same email within this period return cached results (see cached: true) and do not consume verification credits.

cURL

curl -X POST https://api.mailcheck.dev/v1/verify \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"email": "test@example.com"}'

Node.js

const res = await fetch('https://api.mailcheck.dev/v1/verify', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_your_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ email: 'test@example.com' }),
});
const data = await res.json();
console.log(data.valid); // true

Python

import requests

resp = requests.post(
    'https://api.mailcheck.dev/v1/verify',
    headers={'Authorization': 'Bearer sk_live_your_key'},
    json={'email': 'test@example.com'},
)
data = resp.json()
print(data['valid'])  # True

Bulk Verify Emails

POST /v1/verify/bulk

Verify up to 100 email addresses in a single request. Results are returned in the same order as the input array.

Request Body

{
  "emails": ["user1@example.com", "user2@gmail.com", "bad@tempmail.com"],
  "webhook_url": "https://your-server.com/webhook"  // optional
}

Response (200)

{
  "results": [
    {
      "email": "user1@example.com",
      "valid": false,
      "score": 15,
      "reason": "Disposable email provider (example.com)",
      "checks": { "syntax": "pass", "disposable": "fail", "mx": "skip", "smtp": "skip" },
      "details": { "isDisposable": true },
      "cached": false
    },
    {
      "email": "user2@gmail.com",
      "valid": true,
      "score": 100,
      "reason": "deliverable",
      "checks": { "syntax": "pass", "disposable": "pass", "mx": "pass", "smtp": "pass" },
      "details": { "mxHost": "gmail-smtp-in.l.google.com", "catchAll": false },
      "cached": false
    },
    ...
  ],
  "total": 3,
  "unique_verified": 3,
  "credits_remaining": 47
}

Limits

  • Maximum 100 emails per request
  • Each unique email counts as one verification credit
  • Duplicate emails are verified once but returned for each occurrence

Webhook (optional)

If webhook_url is provided, results will be POSTed to that URL after processing. Webhook delivery includes automatic retries with exponential backoff (30s, 2min, 10min, 30min, 2h). Must be an HTTPS URL (HTTP allowed for non-private hosts).

Webhook Payload

{
  "event": "bulk_verification_complete",
  "job_id": "uuid",
  "status": "completed",
  "summary": {
    "total": 3,
    "valid": 2,
    "invalid": 1,
    "risky": 0,
    "unknown": 0
  },
  "results": [ ...same as response results array... ],
  "timestamp": "2026-02-16T14:00:00.000Z"
}

Webhook Signature Verification

Each webhook request includes an X-MailCheck-Signature header containing an HMAC-SHA256 hex digest of the request body, signed with your API key as the secret. Verify it to ensure the webhook came from MailCheck:

// Node.js example
const crypto = require('crypto');

function verifyWebhook(body, signature, apiKey) {
  const expected = crypto
    .createHmac('sha256', apiKey)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

cURL

curl -X POST https://api.mailcheck.dev/v1/verify/bulk \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["user1@example.com", "user2@gmail.com"]}'

Verify Email Authenticity

POST /v1/verify/auth

Analyze email headers to detect spoofing, phishing, and CEO fraud. Privacy-first: only headers are processed — email body content is never read or stored.

Request Body

{
  "headers": "From: sender@example.com
Received: from ...",
  "trusted_domains": ["yourcompany.com"]  // optional
}

Send either headers (just the header block) or raw_email (full email — body is stripped automatically). trusted_domains enables lookalike detection against your organization's domains.

Response (200)

{
  "trust_score": 85,
  "verdict": "trusted",
  "from": {
    "address": "sender@example.com",
    "display_name": "Sender Name",
    "domain": "example.com"
  },
  "authentication": {
    "spf": { "result": "pass", "domain": "example.com", "ip": "1.2.3.4" },
    "dkim": { "result": "present", "domain": "example.com", "selector": "s1", "has_public_key": true },
    "dmarc": { "has_policy": true, "policy": "reject", "record": "v=DMARC1; p=reject; ..." }
  },
  "anomalies": [],
  "lookalike": { "is_lookalike": false },
  "privacy": { "body_processed": false, "headers_only": true },
  "credits_remaining": 95
}

Authentication Checks

  • SPF — Verifies the sending server is authorized by the domain's DNS records. If the email contains an Authentication-Results header (added by the receiving server like Gmail), we trust that result directly.
  • DKIM — Checks that a DKIM signature is present and the signing domain has a valid public key in DNS. Trusted from Authentication-Results when available.
  • DMARC — Verifies the domain publishes a DMARC policy (none/quarantine/reject). Trusted from Authentication-Results when available.

Anomaly Types

TypeSeverityDescription
from_replyto_mismatchHighFrom and Reply-To domains don't match — common phishing indicator
display_name_spoofingHighDisplay name contains an email address different from the actual sender
return_path_mismatchMediumReturn-Path domain doesn't match From domain
missing_message_idMediumNo Message-ID header — unusual for legitimate email
suspicious_mailerHighX-Mailer indicates a known phishing tool (e.g. GoPhish, King Phisher)

Lookalike Detection

Detects domains designed to impersonate trusted brands or your organization using techniques like typosquatting (gooogle.com), TLD swaps (company.co vs company.com), and character substitution (microsoft.com) to identify brand impersonation attempts.

Use Cases

  • CEO Fraud Detection — Detect emails impersonating executives by analyzing header authenticity and lookalike domains.
  • Phishing Prevention — Flag suspicious emails before users interact with them.
  • Email Security Auditing — Verify that your organization's emails pass SPF/DKIM/DMARC.
  • Incident Response — Quickly assess whether a reported email is legitimate.

Privacy

This endpoint never processes email body content. If you send a full email via raw_email, the body is stripped before analysis. Only headers are examined. This is by design — authenticity can be fully determined from headers alone.

cURL

curl -X POST https://api.mailcheck.dev/v1/verify/auth \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"headers": "From: sender@example.com
Received: from ...", "trusted_domains": ["yourcompany.com"]}'

Detection Features

Advanced email intelligence beyond basic validation

Role-Based Email Detection

Detects role-based addresses like info@, admin@, sales@, support@, etc. Role-based addresses are shared mailboxes rather than individual recipients, which typically have lower engagement rates. The checks.role field returns "warn" for role addresses and "pass" otherwise. A 10-point penalty is applied to role-based addresses.

Free Email Provider Detection

Identifies if an email uses a free provider (Gmail, Yahoo, Outlook, ProtonMail, etc. — 100+ providers). This is informational only and does not affect the score. Useful for B2B lead quality assessment. Check details.is_free_provider and details.free_provider_name.

Typo Suggestion Engine

Detects common domain typos (e.g., gmial.comgmail.com) using a database of known misspellings and Levenshtein distance matching. When a typo is detected, details.has_typo_suggestion is true and details.typo_suggestion contains the corrected email address.

Disposable Email Detection

Checks against a database of 5,000+ known disposable/temporary email providers (10minutemail, guerrillamail, mailinator, etc.). Disposable emails immediately fail verification.

Risk Level

Each result includes a details.risk_level field: "low" (score ≥ 80), "medium" (score 50-79), or "high" (score < 50).

Verification Scoring

How the confidence score (0-100) is calculated

CheckPointsDescription
Syntax15Valid email format (RFC 5322)
Disposable20Not a disposable/temporary email provider
MX Records30Domain has valid mail server records
SMTP35Mail server accepts the recipient
Role-based-10Penalty for role-based addresses (info@, admin@, etc.)

Emails scoring 60+ are considered valid. Catch-all domains receive a 10-point penalty. When SMTP is inconclusive (greylisting, timeout), 25 points are awarded as benefit of the doubt.

Note: SMTP verification uses Cloudflare Workers TCP sockets. In environments where TCP sockets are unavailable, SMTP checks are skipped and partial credit is given (max score 90).

Get Account Info

GET /v1/account

Returns your account details, plan, and current month's usage.

Response (200)

{
  "email": "you@example.com",
  "plan": "free",
  "monthly_limit": 100,
  "usage": {
    "current_month": 42,
    "remaining": 58
  },
  "api_key": {
    "prefix": "sk_live_abc",
    "created_at": "2026-02-01T00:00:00.000Z",
    "last_used_at": "2026-02-14T12:00:00.000Z"
  }
}

cURL

curl https://api.mailcheck.dev/v1/account \
  -H "Authorization: Bearer sk_live_your_key"

Rotate API Key

POST /v1/account/rotate-key

Revokes your current API key and generates a new one. Save the new key immediately — your old key stops working.

Response (200)

{
  "message": "API key rotated successfully",
  "api_key": "sk_live_new_key_here",
  "warning": "Your old key is now revoked. Save this new key."
}

cURL

curl -X POST https://api.mailcheck.dev/v1/account/rotate-key \
  -H "Authorization: Bearer sk_live_your_old_key"

Create Account (Programmatic)

POST /v1/signup — No auth required

Create a new account and receive an API key. No authentication required. Rate limited to 5 requests per hour per IP.

Request Body

{
  "email": "you@example.com",
  "password": "min8characters",
  "name": "Optional Name"
}

Response (201)

{
  "message": "Account created successfully",
  "customer_id": "uuid-here",
  "api_key": "sk_live_your_new_key",
  "plan": "free",
  "monthly_limit": 100
}

Error Codes

Common error responses you may encounter

StatusErrorDescription
400Validation errorMissing or invalid request parameters
401UnauthorizedMissing or invalid API key
403Account suspendedYour account has been deactivated
409ConflictResource already exists (e.g. duplicate email on signup)
429Rate limitedToo many requests — slow down
429Quota exceededMonthly verification limit reached
500Internal errorSomething went wrong on our end

All errors return JSON: { "error": "...", "message": "..." }

Example Error Responses

401 Unauthorized (invalid API key):

{
  "error": "unauthorized",
  "message": "Invalid API key provided"
}

429 Rate Limited:

{
  "error": "rate_limited",
  "message": "Too many requests. Please retry after 45 seconds.",
  "retry_after": 45
}

400 Validation Error:

{
  "error": "validation_error",
  "message": "Missing required field: email"
}

FAQ & Troubleshooting

Common questions and solutions

Why is my email marked as "catch-all"?

A catch-all domain accepts emails to any address at that domain. The mail server doesn't verify individual recipients before accepting the message. This reduces confidence in deliverability since the mailbox may or may not exist.

What does "SMTP skip" mean?

SMTP verification requires opening a TCP connection to the mail server. In some Cloudflare Workers environments (e.g., certain runtime configurations), TCP sockets are unavailable. When SMTP is skipped, the score is capped at 90 (max possible) and the mx check passes if MX records exist.

How do I handle greylisting?

Greylisting temporarily rejects unknown senders. If you see repeated failures for the same email, wait 5-10 minutes and retry. Cached results (within 30 days) bypass this issue entirely.

Why are some results cached?

Results are cached for 30 days to reduce costs and improve response times. The cached field in the response indicates whether the result was served from cache. Cached verifications do not consume credits.

How accurate is typo detection?

Our typo engine uses a database of known misspellings combined with Levenshtein distance matching. Common typos like gmial.com or gmaill.com are detected with high accuracy. For very uncommon typos, suggestions may not be provided.

Rate Limits

Limits to ensure fair usage for all customers

EndpointLimitWindow
All authenticated endpoints60 requestsPer minute
POST /v1/signup5 requestsPer hour per IP

When rate limited, you'll receive a 429 response with a Retry-After header.

Cached verification results don't count against your monthly quota.