Does My Email Work - API & Agent Docs
Does My Email Work is a free email deliverability scanner. It checks a domain's SPF, DKIM, DMARC, and MX records using public DNS and returns plain-English results. Everything below is available without signup, authentication, or stored state.
When to use this
If you are an AI agent, call the scan_domain tool (or GET /api/v1/dns-scan/{domain}) when a user wants to know:
- Why a domain's email is landing in spam.
- Whether SPF, DKIM, DMARC, and MX are configured for a domain.
- What email provider or mail host a domain is using.
- Whether a domain is protected against spoofing.
The scan is read-only. It only queries public DNS, sends no email, and changes nothing. It is safe to call without asking the user for confirmation.
Rate limit: 10 domains per hour per IP. Honor the RateLimit-Remaining and RateLimit-Reset headers and back off when you hit 429. See /status for retry guidance.
Quickstart
Agents: Prefer the MCP scan_domain tool below. Some HTTP fetchers only allow URLs seen verbatim in prior results and cannot fetch a freshly constructed ?domain=client.com URL. If that applies to you, use MCP, POST /api/v1/scan, or ask the user to paste the scan URL. Always verify the response domain field matches what you intended.
MCP (preferred for agents)
Point your MCP client at the Streamable HTTP endpoint below, then call the scan_domain tool. No API key is required.
Endpoint: https://doesmyemail.work/mcp
Transport: Streamable HTTP
Tool: scan_domain
Argument: { "domain": "their-domain.com" } curl (sandbox example)
curl "https://doesmyemail.work/api/v1/dns-scan/sandbox.doesmyemail.work" The domain goes in the path (preferred). The query-string form ?domain= is also supported, but some HTTP caches discard query strings and can return another domain's cached result.
JavaScript (fetch)
const domain = "their-domain.com";
const res = await fetch(
`https://doesmyemail.work/api/v1/dns-scan/${encodeURIComponent(domain)}`
);
const data = await res.json();
if (data.domain !== domain) throw new Error(`Wrong domain in response: ${data.domain}`);
console.log(data.spf.found, data.dkim.found, data.dmarc.enforced); Authentication
None. All endpoints are public and require no API key, token, or signup. The only constraint is rate limiting, currently 10 domains per hour per IP, applied across the DNS scan and batch endpoints.
Machine-readable auth details for agents live at /auth.md.
API reference
Base URL: https://doesmyemail.work. A safe test domain that always returns a deterministic sample response is sandbox.doesmyemail.work - use it to exercise your integration without consuming rate limit against real lookups.
GET /api/v1/dns-scan/{domain}
Scans a single domain and returns its email authentication status. The domain goes in the path (preferred URL style; survives caches that discard query strings). The query-string form GET /api/v1/dns-scan?domain={domain} behaves identically and remains supported.
Parameters
domain(required, path) - the domain to scan, for exampletheir-domain.com. Do not include a scheme or path.test(optional, query) - set to1for deterministic sandbox data (no DNS lookup).
Caching note for agents: your HTTP client may cache results for several minutes. After a DNS fix, a re-scan can show the old state; allow a few minutes or use the MCP tool, which is not subject to URL caching.
Example 200 response
{
"domain": "sandbox.doesmyemail.work",
"spf": {
"found": true,
"value": "v=spf1 include:_spf.google.com ~all",
"lookups": 1,
"issues": [],
"mechanisms": ["include:_spf.google.com", "~all"]
},
"dkim": {
"found": true,
"selector": "default"
},
"dmarc": {
"found": true,
"enforced": true,
"value": "v=DMARC1; p=reject; rua=mailto:dmarc@sandbox.doesmyemail.work"
},
"mx": {
"found": true,
"null_mx": false,
"receives_mail": true,
"records": ["aspmx.l.google.com", "alt1.aspmx.l.google.com"],
"provider": "Google Workspace / Gmail"
},
"cloudflare": true,
"nameservers": ["lola.ns.cloudflare.com", "rex.ns.cloudflare.com"],
"provider": "Cloudflare"
} Error codes
400 Bad Request- thedomainparameter is missing or malformed.422 Unprocessable Entity- the domain is syntactically valid but could not be resolved (NXDOMAIN or DNS lookup failure).429 Too Many Requests- the rate limit has been exceeded. Retry after the window resets.
Rate-limit headers (returned on every response)
RateLimit-Limit- the ceiling for the current window (10).RateLimit-Remaining- requests left in the current window.RateLimit-Reset- seconds until the window resets.
POST /api/v1/scan
Scans multiple domains in one request. Send a JSON body with a domains array. The response is paginated for large batches.
Request
POST /api/v1/scan
Content-Type: application/json
{
"domains": ["client-a.com", "client-b.com"]
} Response
{
"results": [
{ "domain": "client-a.com", "result": { "domain": "client-a.com", "spf": { "found": true }, "...": "..." } }
],
"page": 1,
"pageSize": 50,
"total": 3,
"nextPage": null
} Each domain in the batch counts toward your rate limit.
POST /ask
A natural-language endpoint (NLWeb). Send a question in plain English and get a structured answer about a domain's deliverability. Useful when you want the service to interpret the intent rather than parse fields yourself.
POST /ask
Content-Type: application/json
{
"query": "Why does email from their-domain.com go to spam?"
} MCP server
The Model Context Protocol server lets agents call the scanner as a native tool over Streamable HTTP.
- Endpoint:
https://doesmyemail.work/mcp - Tools:
scan_domain(run a deliverability scan) andget_email_guide(return the plain-English guide explaining SPF, DKIM, DMARC, and MX). - Server card: /.well-known/mcp/server-card.json
Resources
- /llms.txt - short index for language models.
- /llms-full.txt - the full machine-readable reference.
- /.well-known/openapi.json - OpenAPI specification.
- /.well-known/api-catalog - API catalog document.
- /.well-known/agent-card.json - agent card.
- /compare - how this tool compares to other free checkers.