Email Deliverability & DNS Health API

Every record that decides whether your mail lands, in one call

The Email Deliverability & DNS Health API returns a domain's email authentication and DNS posture as clean JSON.

no credit card1,000 free credits · instant API key · live in 10 seconds
Missing a Email Deliverability & DNS Health endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
E
/email-health/v1

12 active endpoints. Every call is 1 credit.

  • POST/email-health/v1/check
  • POST/email-health/v1/spf
  • POST/email-health/v1/dmarc
  • POST/email-health/v1/dkim
  • POST/email-health/v1/mx
  • POST/email-health/v1/blacklist
  • POST/email-health/v1/mta_sts
  • +5 more

What Email Deliverability & DNS Health endpoints does ReefAPI ship?

12 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

12 endpoints

check

1 cr

Full email-health audit.

required
domain
optional
selector, selectors, bimi_selector, skip_blacklist

spf

1 cr

Parse + validate the SPF record.

required
domain
optional

dmarc

1 cr

Parse the DMARC policy at _dmarc.<domain>.

required
domain
optional

dkim

1 cr

DKIM selector lookup (<selector>._domainkey.<domain>).

required
domain
optional
selector, selectors

mx

1 cr

MX records (sorted by preference) + a mail-provider guess from the exchange hostnames.

required
domain
optional

blacklist

1 cr

DNSBL reputation.

required
domain
optional
ips

mta_sts

1 cr

MTA-STS.

required
domain
optional

bimi

1 cr

BIMI brand-logo record at <selector>._bimi.<domain>.

required
domain
optional
selector

tls_rpt

1 cr

SMTP TLS Reporting (RFC 8460) record at _smtp._tls.<domain>.

required
domain
optional

dnssec

1 cr

DNSSEC signing status.

required
domain
optional

dane

1 cr

DANE for SMTP (RFC 7672).

required
domain
optional

batch

1 cr

Run the full 'check' audit on up to 25 domains in one call (each with score + grade).

required
domains
optional
skip_blacklist

Every parameter, every allowed value →

Email Deliverability & DNS Health API

3 of 12 endpoints, ready to run

View docs ↗

The full audit — a graded score with a per-record breakdown, a flat summary of booleans, the issues found, and each record parsed out in its own block.

1 credit1 required · 0 optional
POST/email-health/v1/check
ok5919 ms · 4 records · sample
{
  "ok": true,
  "meta": {
    "api": "email-health",
    "endpoint": "check",
    "mode": "live",
    "latency_ms": 5918.5,
    "record_count": 4,
    "cache_hit": false
  },
  "data": {
    "domain": "stripe.com",
    "score": {
      "score": 90,
      "max": 100,
      "grade": "A",
      "breakdown": {
        "mx": {
          "score": 20,
          "max": 20,
          "note": "5 MX record(s) — Google Workspace"
        },
        "spf": {
          "score": 22,
          "max": 22,
          "note": "valid SPF, 7/10 lookups, all=~"
        },
        "dmarc": {
          "score": 22,
          "max": 22,
          "note": "p=reject pct=100"
        },
        "dkim": {
          "score": 16,
          "max": 16,
          "note": "DKIM found (google, s1, s2, mandrill, zendesk1, zendesk2, cm)"
        },
        "blacklist": {
          "score": 10,
          "max": 10,
          "note": "clean across 15 DNSBLs"
        },
        "mta_sts": {
          "score": 0,
          "max": 4,
          "note": "absent"
        },
        "dnssec": {
          "score": 0,
          "max": 3,
          "note": "unsigned"
        },
        "tls_rpt": {
          "score": 0,
          "max": 2,
          "note": "absent"
        },
        "bimi": {
          "score": 0,
          "max": 1,
          "note": "absent"
        }
      }
    },
    "summary": {
      "has_spf": true,
      "spf_valid": true,
      "has_dmarc": true,
      "dmarc_enforced": true,
      "has_dkim": true,
      "has_mx": true,
      "mx_provider": "Google Workspace",
      "has_bimi": false,
      "mta_sts_enforced": false,
      "dnssec_signed": false,
      "has_tls_rpt": false,
      "has_dane": false,
      "blacklisted": false,
      "blacklist_listings": 0
    },
    "issues": [
      "2 IP(s) have no PTR/rDNS record (receivers may reject mail with no reverse DNS)",
      "no MTA-STS TXT at _mta-sts.stripe.com"
    ],
    "spf": {
      "domain": "stripe.com",
      "found": true,
      "record": "v=spf1 ip4:198.2.180.60/32 ip4:13.111.2.227/32 include:spf1.stripe.com include:greenhouse-outbound-mail.stripe.com include:_spf.qualtrics.com ~all",
      "valid": true,
      "dns_lookups": 7,
      "void_lookups": 0,
      "policy": "softfail (recommended)",
      "mechanisms": [
        "ip4:198.2.180.60/32",
        "ip4:13.111.2.227/32",
        "include:spf1.stripe.com"
      ],
      "includes": [
        "spf1.stripe.com",
        "greenhouse-outbound-mail.stripe.com",
        "_spf.qualtrics.com"
      ],
      "all_qualifier": "~",
      "issues": [],
      "include_tree": [
        {
          "target": "spf1.stripe.com",
          "record": "v=spf1 include:_spf.google.com include:amazonses.com include:mail.zendesk.com ~all",
          "lookups": 3,
          "void": 0
        },
        {
          "target": "greenhouse-outbound-mail.stripe.com",
          "record": "v=spf1 ip4:69.72.40.93 ip4:69.72.40.94 ip4:69.72.40.95 ip4:69.72.40.96 ip4:69.72.40.97 ip4:69.72.40.98 ip4:69.72.40.99 ip4:69.72.47.205 include:greenhouse-outbound-mail-old.stripe.com",
          "lookups": 1,
          "void": 0
        },
        {
          "target": "_spf.qualtrics.com",
          "record": "v=spf1 ip4:162.247.216.0/22 ip4:139.60.152.0/22 ip4:98.97.248.0/21 ip4:64.69.212.0/24 ip4:54.186.193.102/32 ip4:52.222.73.120/32 ip4:52.222.73.83 ip4:52.222.62.51 ip4:52.222.75.85 ip4:52.222.89.228 ip4:160.1.62.192 ip4:52.61.91.9 ip4:15.200.21.50 ip4:15.200.201.185 ip4:15.200.44.248 -all",
          "lookups": 0,
          "void": 0
        }
      ]
    },
    "dkim": {
      "domain": "stripe.com",
      "found": true,
      "record_exists": true,
      "wildcard_revoke": false,
      "selectors_tested": [
        "google",
        "20230601",
        "20161025"
      ],
      "selectors_found": [
        "google",
        "s1",
        "s2"
      ],
      "selectors_with_record": [
        "google",
        "s1",
        "s2"
      ],
      "records": [
        {
          "selector": "google",
          "found": true,
          "usable": true,
          "name": "google._domainkey.stripe.com",
          "record": "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4T1PE2vh5xqRGzOrDnkoi03N/BFQ+GLa/xF69d8K0QOZBxTJbttc2DxcPdpvxqQRQOheompWvzCvWw/SH/NMgq72ulPKz2nHQbU6wIucXMf/sizgnsy+Ihiw9S5c/5sBMHUVZStqhHMuY8BGx0wGLavSmMFzBNdchT4g+46OuhQIDAQAB",
          "_bytes": 448,
          "key_type": "rsa",
          "public_key_present": true,
          "revoked": false,
          "key_bits": 1024,
          "flags": null
        },
        {
          "selector": "20230601",
          "found": false,
          "usable": false,
          "name": "20230601._domainkey.stripe.com",
          "record": null,
          "_bytes": 543
        },
        {
          "selector": "20161025",
          "found": false,
          "usable": false,
          "name": "20161025._domainkey.stripe.com",
          "record": null,
          "_bytes": 543
        }
      ],
      "issues": []
    },
    "dmarc": {
      "domain": "stripe.com",
      "found": true,
      "record": "v=DMARC1; p=reject; pct=100; fo=1; rua=mailto:[email protected]; ruf=mailto:[email protected];",
      "valid": true,
      "policy": "reject",
      "subdomain_policy": "reject",
      "pct": 100,
      "rua": [
        "mailto:[email protected]"
      ],
      "ruf": [
        "mailto:[email protected]"
      ],
      "adkim": "r",
      "aspf": "r",
      "fo": "1",
      "issues": [],
      "tags": {
        "v": "DMARC1",
        "p": "reject",
        "pct": "100",
        "fo": "1",
        "rua": "mailto:[email protected]",
        "ruf": "mailto:[email protected]"
      },
      "enforced": true
    },
    "mx": {
      "domain": "stripe.com",
      "found": true,
      "count": 5,
      "records": [
        {
          "preference": 10,
          "exchange": "aspmx.l.google.com"
        },
        {
          "preference": 20,
          "exchange": "alt1.aspmx.l.google.com"
        },
        {
          "preference": 20,
          "exchange": "alt2.aspmx.l.google.com"
        }
      ],
      "hosts": [
        "aspmx.l.google.com",
        "alt1.aspmx.l.google.com",
        "alt2.aspmx.l.google.com"
      ],
      "provider": "Google Workspace",
      "issues": []
    },
    "bimi": {
      "domain": "stripe.com",
      "found": false,
      "record": null,
      "selector": "default",
      "logo_url": null,
      "vmc_url": null
    },
    "mta_sts": {
      "domain": "stripe.com",
      "found": false,
      "record": null,
      "id": null,
      "policy": null,
      "mode": null,
      "mx": [],
      "max_age": null,
      "policy_fetched": false,
      "issues": [
        "no MTA-STS TXT at _mta-sts.stripe.com"
      ]
    },
    "tls_rpt": {
      "domain": "stripe.com",
      "found": false,
      "record": null,
      "rua": []
    },
    "dnssec": {
      "domain": "stripe.com",
      "validated_ad_flag": false,
      "has_ds_record": false,
      "signed": false
    },
    "dane": {
      "domain": "stripe.com",
      "found": false,
      "mx_hosts_checked": [
        "aspmx.l.google.com",
        "alt1.aspmx.l.google.com",
        "alt2.aspmx.l.google.com"
      ],
      "hosts": [
        {
          "mx_host": "aspmx.l.google.com",
          "name": "_25._tcp.aspmx.l.google.com",
          "found": false,
          "records": [],
          "dnssec_validated": false
        },
        {
          "mx_host": "alt1.aspmx.l.google.com",
          "name": "_25._tcp.alt1.aspmx.l.google.com",
          "found": false,
          "records": [],
          "dnssec_validated": false
        },
        {
          "mx_host": "alt2.aspmx.l.google.com",
          "name": "_25._tcp.alt2.aspmx.l.google.com",
          "found": false,
          "records": [],
          "dnssec_validated": false
        }
      ],
      "record_count": 0,
      "issues": []
    },
    "blacklist": {
      "domain": "stripe.com",
      "checked_ips": [
        "142.250.147.26",
        "142.250.147.27",
        "142.251.127.26"
      ],
      "ptr_records": {
        "142.250.147.26": "rd-in-f26.1e100.net",
        "142.250.147.27": "rd-in-f27.1e100.net",
        "142.251.127.26": "lcfrai-in-f26.1e100.net",
        "172.253.152.27": "yulpptr-in-f27.1e100.net",
        "198.137.150.111": null,
        "198.202.176.111": null
      },
      "listings": [],
      "listed_count": 0,
      "clean": true,
      "checks_run": 90,
      "resolver_refused_count": 0,
      "zones_checked": [
        "bl.spamcop.net",
        "b.barracudacentral.org",
        "dnsbl-1.uceprotect.net"
      ],
      "paid_key_zones": [
        {
          "zone": "zen.spamhaus.org",
          "name": "Spamhaus ZEN",
          "reason": "returns 127.255.255.254 on public resolvers — needs a Spamhaus DQS (Data Query Service) key"
        },
        {
          "zone": "cbl.abuseat.org",
          "name": "Spamhaus CBL/XBL",
          "reason": "served via Spamhaus infra — same public-resolver refusal"
        }
      ],
      "issues": [
        "2 IP(s) have no PTR/rDNS record (receivers may reject mail with no reverse DNS)"
      ]
    }
  }
}
Real response, fetched from the live endpoint with the parameters on the left — trimmed to the first few rows, with seller names left out. Press Try it for the untrimmed response.

How the Email Deliverability & DNS Health API works

Email Deliverability & DNS Health is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 184 engines.

02
Call
POST /email-health/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 credit per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Finding out why the invoices stopped arriving

Deliverability failures are almost never the message. They are a policy that says reject, an SPF record that quietly exceeded its lookup budget, or a DKIM selector that was rotated and never republished.

01check
POST/email-health/v1/check
{"domain": "yourcompany.com"}

One call covering every record. Returns a graded score with per-record points and an issues list naming what is wrong.

02spf
POST/email-health/v1/spf
{"domain": "yourcompany.com"}

When SPF is the problem. The lookup count against the limit of ten is the field that explains the failures nobody can reproduce.

Two well-known domains we measured scored A and C on the same rubric, and in both cases the breakdown named the exact records responsible rather than leaving a number to interpret.

request
curl -X POST https://api.reefapi.com/email-health/v1/check \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"domain":"google.com"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "email-health",
    "endpoint": "check",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

How the 0–100 deliverability score is weighted

The score is not a black box: every response returns score.breakdown with each section's earned points, its maximum and a note explaining the number. Those maxima are fixed and shown below. If you only care about one dimension, call that section's standalone action instead of check — the weights tell you which ones the score barely moves for.

SectionMax pointsWhat earns them
spf22a valid SPF record, DNS lookups within the limit, and an all-qualifier that is not +all
dmarc22a published policy at _dmarc.<domain>; p=quarantine at pct=100 measured full marks
mx20at least one resolvable MX record
dkim16at least one selector with a usable public key
blacklist10no DNSBL listings across the domain's A and MX-host IPs
mta_sts4an _mta-sts TXT plus a fetchable policy file
dnssec3the zone is signed — resolver AD flag and a DS record at the parent
tls_rpt2a TLS-RPT record at _smtp._tls.<domain>
bimi1a BIMI record with a logo URL

dane is returned but carries no points — it is reported as informational because almost no commercial mail platform publishes TLSA records, and scoring it would penalize domains for a decision their provider made.

What is checked, and what a passing grade does not promise

Measured on a large sender with a mature setup and on a minimal domain. The last row is the limit of any static audit.

Every modern record, not just the famous three

Beyond SPF, DKIM and DMARC the audit covers MX with the provider identified, MTA-STS including whether the policy file actually fetches, TLS-RPT, BIMI, DANE, DNSSEC and blacklist listings. The newer records are the ones that separate a deliverability setup from a compliance checkbox, and they are where most audits stop.

The SPF lookup budget is counted

SPF permits ten DNS lookups and silently fails past that, which is the single most common cause of intermittent, unreproducible rejections. The response returns the count against the limit, the void lookups, and the include tree expanded, so you can see which vendor's include is consuming the budget.

The score is decomposed with points and reasons

The grade breaks into MX, SPF, DMARC, DKIM and blacklist components, each with its points, its ceiling and a note saying why — 'p=reject pct=100', 'valid SPF, 7/10 lookups', 'no DKIM for tested selector(s)'. Two domains with the same grade can need entirely different work.

Against us: DKIM is selector-guessing, and it has to be

DKIM records live at selector names that are not discoverable from DNS — there is no way to list them. The audit probes the common ones and reports which it tested and which it found. A domain using an unusual selector will show no DKIM even when DKIM is correctly configured, so read the tested-selectors list before concluding anything.

Against us: a good grade is a configuration result, not a reputation one

Every record here can be perfect while your mail still lands in spam, because reputation is built on sending behaviour, complaint rates and engagement — none of which is visible in DNS. This audit tells you the setup is not the problem, which is genuinely useful precisely because it is the first thing to rule out.

What people build with Email Deliverability & DNS Health

The jobs this data is most often used for.

12

endpoints

1

credit per call

01

Deliverability tools call check to grade a sending domain's SPF, DKIM and DMARC before a campaign.

02

Security audits use dmarc and mta_sts to confirm a domain's anti-spoofing posture.

03

Onboarding flows use the overall score to warn customers about misconfigured email DNS.

What Email Deliverability & DNS Health data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 184 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/email-health/v1/check \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"domain":"google.com"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/email-health/v1/check",
    headers={"x-api-key": REEF_KEY},
    json={
  "domain": "google.com"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Email Deliverability & DNS Health.

Get a free key →
What does a real-world score look like — is 100 the normal target?

No. A measured audit of github.com scored 86, grade B. It earned full marks on mx, spf and dmarc and 16/16 on dkim, then lost points on exactly the sections most large senders skip: mta_sts 0/4 (absent), dnssec 0/3 (unsigned), tls_rpt 0/2 (absent), bimi 0/1 (absent), and blacklist 6/10 for one listing. Treat the high-weight sections as pass/fail and the small ones as headroom.

Why does the SPF section report dns_lookups and void_lookups?

Because SPF's cost is capped at 10 DNS-resolving mechanisms, and blowing past it makes receivers fail the record entirely rather than soft-fail it. The parser follows every include: and redirect= and counts them for you. Measured on github.com: dns_lookups 10 — exactly at the limit — with void_lookups 0. Sitting at 10 means the next include your marketing team adds breaks authentication silently. void_lookups counts includes that resolve to nothing, which burn budget for no benefit.

How does DKIM lookup work if I do not know the selector?

DKIM has no discovery mechanism — a selector is an arbitrary label the sender chose — so with no selector given the check autoscans roughly 40 common ESP selectors and reports selectors_tested alongside selectors_found. Measured on github.com that found ten live: google, selector1, k1, k2, k3, s1, s2, zendesk1, zendesk2 and cm, which incidentally maps out which platforms send mail as that domain. Each record comes back with key_type, an RSA key_bits estimate (2048 in the measured case), public_key_present and revoked. If you know your selector, pass it and skip the scan.

Which blacklists are actually queried, and which are not?

The check resolves the domain's A and MX-host IPs, reverses them against public DNSBLs that answer public resolvers — SpamCop, Barracuda, UCEPROTECT, PSBL, Mailspike, GBUdb, DroneBL, SPFBL, s5h — and returns checked_ips, ptr_records, listings[] with the zone and its return codes, listed_count and a clean boolean. Spamhaus and CBL are deliberately not queried: they refuse public-resolver traffic and require a paid key, so they are reported in paid_key_zones rather than silently counted as clean. A measured github.com run made 75 individual checks and found one listing.

Why is a check call slow, and how do I speed it up?

A full check measured 9.7 seconds because the blacklist section is many IP-by-zone DNS queries — 75 of them in the measured run — while every other section is a handful of lookups. Pass skip_blacklist to drop that section, or call the standalone spf, dmarc, dkim, mx, bimi, mta_sts, tls_rpt, dnssec or dane actions when you only need one.

What is the difference between dmarc `policy` and `enforced`?

policy is the raw p= tag and enforced is the verdict after pct and subdomain policy are taken into account. Measured on github.com: policy 'quarantine', subdomain_policy 'reject', pct 100, enforced true. A domain publishing p=none, or p=reject at pct=10, has a DMARC record and is still not enforcing anything — which is why summary.dmarc_enforced exists as a separate boolean from summary.has_dmarc.

Can I pass an email address or a URL instead of a bare domain?

Yes. A full URL, a leading www., or a whole email address are all normalized to the registrable domain before any lookup runs, so [email protected] and https://www.example.co.uk/pricing both resolve to the same audit. The normalized value is echoed back as domain so you can confirm what was actually checked.

What is in summary versus the individual sections?

summary is a flat set of booleans meant for dashboards and alerting rules — has_spf, spf_valid, has_dmarc, dmarc_enforced, has_dkim, has_mx, mx_provider, has_bimi, mta_sts_enforced, dnssec_signed, has_tls_rpt, has_dane, blacklisted, blacklist_listings — while the per-section objects carry the raw records and parse trees. issues[] merges every section's complaints into one list, which is usually what you want to show a customer. mx_provider is a guess derived from the exchange hostnames (measured: 'Microsoft 365' for github.com), so treat it as a label, not a contract.

What is the Email Deliverability & DNS Health API?

Email Deliverability & DNS Health API is a ReefAPI endpoint group for email deliverability & dns health It returns live JSON through POST requests under /email-health/v1.

Is the Email Deliverability & DNS Health API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Email Deliverability & DNS Health calls use the same shared credit balance as every other ReefAPI engine.

Do I need an Email Deliverability & DNS Health login or account?

No login to Email Deliverability & DNS Health is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Email Deliverability & DNS Health data?

The page example is captured from a live check call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Email Deliverability & DNS Health API use?

Email Deliverability & DNS Health actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Email Deliverability & DNS Health from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call email-health actions with the same key, credit pool and JSON envelope used by normal REST requests.

18 Developer Tools APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Email Deliverability & DNS Health, you are one call away from the rest of the category — no second contract, no second integration.

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-30.