DMARC reports
Read aggregate and forensic DMARC reports for a sending domain, or upload your own.
- GET/domains/{id}/dmarc/reports
- GET/domains/{id}/dmarc/reports/{report_id}
- POST/domains/{id}/dmarc/reports
- GET/domains/{id}/dmarc/forensic
- GET/domains/{id}/dmarc/forensic/{report_id}
- GET/domains/{id}/dmarc/stats
- GET/domains/{id}/dmarc/sources
- GET/domains/{id}/dmarc/countries
- GET/domains/{id}/dmarc/asns
- GET/domains/{id}/dmarc/reporters
List aggregate reports
Returns the DMARC reports for a sending domain, newest first. Requires an API key with the full scope.
Emailit collects reports only for domains with DMARC reports turned on (dmarc_reports: true in Update a domain), which requires the Pro plan or higher. See DMARC reports.
The list includes forensic reports too. Pass type=aggregate to list only aggregate reports, or use List forensic reports for forensic details.
/domains/{id}/dmarc/reportsPath parameters
idstringrequireddom_…) or the domain name, for example acme.com.Query parameters
typestringaggregate or forensic.statusstringpending, processed, failed or duplicate.org_namestringgoogle.com.fromstring2026-09-01.tostringlimitintegerdefault: 25offsetintegerdefault: 0matchstringall (default) requires every filter. or matches any filter. See Filtering.
orderstringSort key for this list. See the sort keys below.
directionstringasc or desc.
The generic key.condition=value filters also work on type, status, org_name and created_at; those are also the sort keys for order. See Filtering.
Returns
Returns data, an array of report objects, and meta with total, limit and offset.
idstringdmr_.typestring | nullaggregate or forensic. null until an uploaded report is processed.sourcestringsmtp for reports Emailit received at the domain’s reporting address, upload for reports you uploaded.statusstringpending, processed, failed (see error_message) or duplicate (the same report was already processed).org_name, org_emailstring | nullexternal_report_idstring | nulldate_range_begin, date_range_endstring | nullpolicy_domain, adkim, aspf, p, sp, pct, fostring | integer | nullr or s), policy and subdomain policy (none, quarantine, reject), percentage and failure-reporting options.original_filenamestring | nullenvelope_tostring | nullcreated_at, updated_at, processed_atstring | nullReturns 404 if the domain doesn’t exist in the workspace.
{
"data": [
{
"object": "dmarc_report",
"id": "dmr_3Xu63kEs8KCiyOZ1TDgnttppitx",
"type": "aggregate",
"source": "smtp",
"status": "processed",
"org_name": "google.com",
"org_email": "noreply-dmarc-support@google.com",
"external_report_id": "4129847120347812934",
"date_range_begin": "2026-09-29 00:00:00+00",
"date_range_end": "2026-09-29 23:59:59+00",
"policy_domain": "acme.com",
"adkim": "r",
"aspf": "r",
"p": "none",
"sp": "none",
"pct": 100,
"fo": null,
"original_filename": null,
"error_message": null,
"envelope_to": "k2v9x4qa7m@dmarc.emailitmail.com",
"created_at": "2026-09-30 04:12:09.214377+00",
"updated_at": "2026-09-30 04:12:11.902154+00",
"processed_at": "2026-09-30 04:12:11.902154+00"
}
],
"meta": { "total": 1, "limit": 50, "offset": 0 }
}{
"error": "Domain not found"
}Retrieve a report
Retrieves one DMARC report. For an aggregate report, the response includes its records, one per sending source, sorted by message count. For a forensic report, it includes the failure sample in forensic. Requires an API key with the full scope.
Reports arrive only for domains with DMARC reports turned on, which requires the Pro plan or higher.
/domains/{id}/dmarc/reports/{report_id}Path parameters
idstringrequireddom_…) or the domain name.report_idstringrequireddmr_…).Query parameters
limitintegerdefault: 100offsetintegerdefault: 0Returns
Returns the report object (see List aggregate reports) plus:
recordsobject[]metaobjecttotal records, limit and offset.forensicobject | nullEach record has:
source_ipstringcountintegercountry_code, country_name, continent_code, asn, as_org, latitude, longitudestring | integer | number | nullnull when the IP couldn’t be located.dispositionstringnone, quarantine or reject.dkim, spfstringpass or fail.header_from, envelope_from, envelope_tostring | nulldkim_domain, dkim_selector, dkim_resultstring | nullspf_domain, spf_resultstring | nullreason_type, reason_commentstring | nullforwarded or mailing_list.Returns 404 if the domain or the report doesn’t exist.
{
"object": "dmarc_report",
"id": "dmr_3Xu63kEs8KCiyOZ1TDgnttppitx",
"type": "aggregate",
"source": "smtp",
"status": "processed",
"org_name": "google.com",
"org_email": "noreply-dmarc-support@google.com",
"external_report_id": "4129847120347812934",
"date_range_begin": "2026-09-29 00:00:00+00",
"date_range_end": "2026-09-29 23:59:59+00",
"policy_domain": "acme.com",
"adkim": "r",
"aspf": "r",
"p": "none",
"sp": "none",
"pct": 100,
"fo": null,
"original_filename": null,
"error_message": null,
"envelope_to": "k2v9x4qa7m@dmarc.emailitmail.com",
"created_at": "2026-09-30 04:12:09.214377+00",
"updated_at": "2026-09-30 04:12:11.902154+00",
"processed_at": "2026-09-30 04:12:11.902154+00",
"records": [
{
"object": "dmarc_report_record",
"source_ip": "198.51.100.24",
"count": 1840,
"country_code": "US",
"country_name": "United States",
"continent_code": "NA",
"asn": 64500,
"as_org": "Example Hosting",
"latitude": 37.751,
"longitude": -97.822,
"disposition": "none",
"dkim": "pass",
"spf": "pass",
"header_from": "acme.com",
"envelope_from": "emailit.acme.com",
"envelope_to": null,
"dkim_domain": "acme.com",
"dkim_selector": "emailit",
"dkim_result": "pass",
"spf_domain": "emailit.acme.com",
"spf_result": "pass",
"reason_type": null,
"reason_comment": null
},
{
"object": "dmarc_report_record",
"source_ip": "203.0.113.77",
"count": 12,
"country_code": "NL",
"country_name": "Netherlands",
"continent_code": "EU",
"asn": 64511,
"as_org": "Example Networks",
"latitude": 52.3824,
"longitude": 4.8995,
"disposition": "none",
"dkim": "fail",
"spf": "fail",
"header_from": "acme.com",
"envelope_from": "acme.com",
"envelope_to": null,
"dkim_domain": null,
"dkim_selector": null,
"dkim_result": null,
"spf_domain": "acme.com",
"spf_result": "softfail",
"reason_type": null,
"reason_comment": null
}
],
"meta": { "total": 2, "limit": 100, "offset": 0 }
}{
"error": "Report not found"
}Upload a report
Uploads a DMARC report you received elsewhere, for example from a mailbox you used before Emailit. Requires an API key with the full scope.
Emailit stores the file and processes it in the background: the response has status pending, and the report becomes processed, failed or duplicate (already imported) shortly after. Check it with Retrieve a report. Reports Emailit receives by email need DMARC reports turned on for the domain (Pro plan or higher); uploaded reports are processed either way.
/domains/{id}/dmarc/reportsPath parameters
idstringrequireddom_…) or the domain name.Body parameters
Send exactly one of content_base64 or content. The decoded report can be up to 10 MB.
content_base64string.xml, .xml.gz or .zip, and forensic reports as .eml (AFRF).contentstringfilenamestringoriginal_filename.Returns
Returns 202 Accepted with the new report object. type is null until processing detects it.
| Status | When |
|---|---|
400 |
Neither content_base64 nor content is set, or the value is empty. |
404 |
The domain doesn’t exist in the workspace. |
413 |
The decoded report is larger than 10 MB. |
{
"object": "dmarc_report",
"id": "dmr_3MjUXgcEBO0o7FkzeBdlrCY6NYk",
"type": null,
"source": "upload",
"status": "pending",
"org_name": null,
"org_email": null,
"external_report_id": null,
"date_range_begin": null,
"date_range_end": null,
"policy_domain": null,
"adkim": null,
"aspf": null,
"p": null,
"sp": null,
"pct": null,
"fo": null,
"original_filename": "google-acme.com-2026-09-29.xml.gz",
"error_message": null,
"envelope_to": null,
"created_at": "2026-10-01 12:03:55.607+00",
"updated_at": "2026-10-01 12:03:55.607+00",
"processed_at": null
}{
"error": "content_base64 or content is required"
}{
"error": "Report exceeds maximum size of 10485760 bytes"
}List forensic reports
Returns the processed forensic (RUF) reports for a domain, newest first. Each describes one message that failed DMARC. Headers are left out of the list; retrieve a forensic report to see them. Requires an API key with the full scope.
Reports arrive only for domains with DMARC reports turned on, which requires the Pro plan or higher. Few mailbox providers send forensic reports, and those that do may include personal data from the failed message.
/domains/{id}/dmarc/forensicPath parameters
idstringrequireddom_…) or the domain name.Query parameters
fromstringtostringlimitintegerdefault: 25offsetintegerdefault: 0The generic key.condition=value filters also work on org_name and created_at, with match, order and direction. See Filtering.
Returns
Returns data and meta (total, limit, offset). Each item has:
objectstringdmarc_forensic_report.id, report_idstringdmr_…).arrival_datestring | nullsource_ipstring | nullcountry_code, country_name, continent_code, asn, as_org, latitude, longitudestring | integer | number | nullauth_failurestring | nulldmarc, spf or dkim.authentication_resultsstring | nullAuthentication-Results header.original_mail_from, original_rcpt_to, subjectstring | nulldelivery_resultstring | nullreject or delivered.reported_domainstring | nullcreated_atstring | null{
"data": [
{
"object": "dmarc_forensic_report",
"id": "dmr_3MjUXgcEBO0o7FkzeBdlrCY6NYk",
"report_id": "dmr_3MjUXgcEBO0o7FkzeBdlrCY6NYk",
"arrival_date": "2026-09-28 17:44:02+00",
"source_ip": "203.0.113.77",
"country_code": "NL",
"country_name": "Netherlands",
"continent_code": "EU",
"asn": 64511,
"as_org": "Example Networks",
"latitude": 52.3824,
"longitude": 4.8995,
"auth_failure": "dmarc",
"authentication_results": "mx.example.net; dmarc=fail (p=none) header.from=acme.com; spf=softfail smtp.mailfrom=acme.com; dkim=none",
"original_mail_from": "billing@acme.com",
"original_rcpt_to": "ada@example.net",
"subject": "Your invoice is ready",
"delivery_result": "delivered",
"reported_domain": "acme.com",
"created_at": "2026-09-28 18:02:16.448210+00"
}
],
"meta": { "total": 1, "limit": 25, "offset": 0 }
}{
"error": "Domain not found"
}Retrieve a forensic report
Retrieves one forensic (RUF) report with the headers of the message that failed DMARC. Requires an API key with the full scope. Forensic reports can contain personal data, such as recipient addresses and subjects.
Reports arrive only for domains with DMARC reports turned on, which requires the Pro plan or higher.
/domains/{id}/dmarc/forensic/{report_id}Path parameters
idstringrequireddom_…) or the domain name.report_idstringrequireddmr_…) of a forensic report.Returns
Returns the forensic report with the fields described in List forensic reports, plus:
headersstring | nullReturns 404 if the domain doesn’t exist, the report doesn’t exist, or it isn’t a processed forensic report.
{
"object": "dmarc_forensic_report",
"id": "dmr_3MjUXgcEBO0o7FkzeBdlrCY6NYk",
"report_id": "dmr_3MjUXgcEBO0o7FkzeBdlrCY6NYk",
"arrival_date": "2026-09-28 17:44:02+00",
"source_ip": "203.0.113.77",
"country_code": "NL",
"country_name": "Netherlands",
"continent_code": "EU",
"asn": 64511,
"as_org": "Example Networks",
"latitude": 52.3824,
"longitude": 4.8995,
"auth_failure": "dmarc",
"authentication_results": "mx.example.net; dmarc=fail (p=none) header.from=acme.com; spf=softfail smtp.mailfrom=acme.com; dkim=none",
"original_mail_from": "billing@acme.com",
"original_rcpt_to": "ada@example.net",
"subject": "Your invoice is ready",
"delivery_result": "delivered",
"reported_domain": "acme.com",
"headers": "From: Acme Billing <billing@acme.com>\r\nTo: ada@example.net\r\nSubject: Your invoice is ready\r\nDate: Mon, 28 Sep 2026 17:43:58 +0000\r\nMessage-ID: <20260928174358.4f1c@mail.acme.com>",
"created_at": "2026-09-28 18:02:16.448210+00"
}{
"error": "Forensic report not found"
}Retrieve statistics
Summarizes the aggregate DMARC reports of a domain over a date range: how much mail receivers saw from your domain, how much passed, and where it came from. This is the data behind the Overview tab under Email APIDMARC reports. Requires an API key with the full scope.
Reports arrive only for domains with DMARC reports turned on (dmarc_reports: true in Update a domain), which requires the Pro plan or higher.
/domains/{id}/dmarc/statsPath parameters
idstringrequireddom_…) or the domain name.Query parameters
fromstring2026-09-01. Without it, all reports are counted.tostringReturns
Returns data with these fields. A message counts as passing when its DMARC-aligned DKIM or SPF result is pass.
total_volumeintegerpass_volume, fail_volumeintegerpass_ratenumber0 when there’s no volume.report_countintegerdispositionsobject[]disposition (none, quarantine, reject) and volume.dkim, spfobject[]result (pass or fail) and volume.dailyobject[]date as YYYY-MM-DD, UTC) with volume, pass_volume and fail_volume.daily_dispositions, daily_dkim, daily_spfobject[]date, disposition or result, and volume.top_countriesobject[]country_code, country_name, volume, pass_volume, fail_volume.top_asnsobject[]asn, as_org, volume, pass_volume, fail_volume.unknown_geo_volumeintegerReturns 404 if the domain doesn’t exist in the workspace.
{
"data": {
"total_volume": 3712,
"pass_volume": 3688,
"fail_volume": 24,
"pass_rate": 99.35,
"report_count": 6,
"dispositions": [
{ "disposition": "none", "volume": 3712 }
],
"dkim": [
{ "result": "pass", "volume": 3680 },
{ "result": "fail", "volume": 32 }
],
"spf": [
{ "result": "pass", "volume": 3676 },
{ "result": "fail", "volume": 36 }
],
"daily": [
{ "date": "2026-09-28", "volume": 1860, "pass_volume": 1848, "fail_volume": 12 },
{ "date": "2026-09-29", "volume": 1852, "pass_volume": 1840, "fail_volume": 12 }
],
"daily_dispositions": [
{ "date": "2026-09-28", "disposition": "none", "volume": 1860 },
{ "date": "2026-09-29", "disposition": "none", "volume": 1852 }
],
"daily_dkim": [
{ "date": "2026-09-28", "result": "pass", "volume": 1844 },
{ "date": "2026-09-28", "result": "fail", "volume": 16 },
{ "date": "2026-09-29", "result": "pass", "volume": 1836 },
{ "date": "2026-09-29", "result": "fail", "volume": 16 }
],
"daily_spf": [
{ "date": "2026-09-28", "result": "pass", "volume": 1842 },
{ "date": "2026-09-28", "result": "fail", "volume": 18 },
{ "date": "2026-09-29", "result": "pass", "volume": 1834 },
{ "date": "2026-09-29", "result": "fail", "volume": 18 }
],
"top_countries": [
{ "country_code": "US", "country_name": "United States", "volume": 3688, "pass_volume": 3688, "fail_volume": 0 },
{ "country_code": "NL", "country_name": "Netherlands", "volume": 24, "pass_volume": 0, "fail_volume": 24 }
],
"top_asns": [
{ "asn": 64500, "as_org": "Example Hosting", "volume": 3688, "pass_volume": 3688, "fail_volume": 0 },
{ "asn": 64511, "as_org": "Example Networks", "volume": 24, "pass_volume": 0, "fail_volume": 24 }
],
"unknown_geo_volume": 0
}
}{
"error": "Domain not found"
}List sending sources
Groups a domain’s aggregate DMARC data by source IP address, highest volume first. Use it to spot servers that send as your domain but fail SPF and DKIM. Requires an API key with the full scope.
Reports arrive only for domains with DMARC reports turned on, which requires the Pro plan or higher.
/domains/{id}/dmarc/sourcesPath parameters
idstringrequireddom_…) or the domain name.Query parameters
fromstringtostringlimitintegerdefault: 50offsetintegerdefault: 0Returns
Returns data and meta (limit, offset). The response has no total; request the next page until data has fewer items than limit. Each source has:
source_ipstringcountry_code, country_namestring | nullasn, as_orginteger | string | nullvolumeintegerpass_volume, fail_volumeintegerReturns 404 if the domain doesn’t exist in the workspace.
{
"data": [
{
"source_ip": "198.51.100.24",
"country_code": "US",
"country_name": "United States",
"asn": 64500,
"as_org": "Example Hosting",
"volume": 3688,
"pass_volume": 3688,
"fail_volume": 0
},
{
"source_ip": "203.0.113.77",
"country_code": "NL",
"country_name": "Netherlands",
"asn": 64511,
"as_org": "Example Networks",
"volume": 24,
"pass_volume": 0,
"fail_volume": 24
}
],
"meta": { "limit": 50, "offset": 0 }
}{
"error": "Domain not found"
}List countries
Groups a domain’s aggregate DMARC data by the country of the sending IP, highest volume first. Requires an API key with the full scope.
Reports arrive only for domains with DMARC reports turned on, which requires the Pro plan or higher.
/domains/{id}/dmarc/countriesPath parameters
idstringrequireddom_…) or the domain name.Query parameters
fromstringtostringlimitintegerdefault: 50offsetintegerdefault: 0Returns
Returns data and meta (limit, offset). Each country has:
country_codestring | nullnull groups IP addresses that couldn’t be located.country_namestring | nullcontinent_codestring | nullEU.volumeintegerpass_volume, fail_volumeintegerReturns 404 if the domain doesn’t exist in the workspace.
{
"data": [
{
"country_code": "US",
"country_name": "United States",
"continent_code": "NA",
"volume": 3688,
"pass_volume": 3688,
"fail_volume": 0
},
{
"country_code": "NL",
"country_name": "Netherlands",
"continent_code": "EU",
"volume": 24,
"pass_volume": 0,
"fail_volume": 24
}
],
"meta": { "limit": 50, "offset": 0 }
}{
"error": "Domain not found"
}List networks (ASNs)
Groups a domain’s aggregate DMARC data by the autonomous system (ASN) of the sending IP, highest volume first. A network usually maps to a hosting provider or email service, which makes it easier to recognize legitimate senders. Requires an API key with the full scope.
Reports arrive only for domains with DMARC reports turned on, which requires the Pro plan or higher.
/domains/{id}/dmarc/asnsPath parameters
idstringrequireddom_…) or the domain name.Query parameters
fromstringtostringlimitintegerdefault: 50offsetintegerdefault: 0Returns
Returns data and meta (limit, offset). Each network has:
asninteger | nullnull groups IP addresses that couldn’t be looked up.as_orgstring | nullvolumeintegerpass_volume, fail_volumeintegerReturns 404 if the domain doesn’t exist in the workspace.
{
"data": [
{
"asn": 64500,
"as_org": "Example Hosting",
"volume": 3688,
"pass_volume": 3688,
"fail_volume": 0
},
{
"asn": 64511,
"as_org": "Example Networks",
"volume": 24,
"pass_volume": 0,
"fail_volume": 24
}
],
"meta": { "limit": 50, "offset": 0 }
}{
"error": "Domain not found"
}List reporters
Lists the organizations that sent processed aggregate reports for a domain, most reports first. Requires an API key with the full scope.
Reports arrive only for domains with DMARC reports turned on, which requires the Pro plan or higher.
/domains/{id}/dmarc/reportersPath parameters
idstringrequireddom_…) or the domain name.Query parameters
fromstringtostringlimitintegerdefault: 50offsetintegerdefault: 0Returns
Returns data and meta (limit, offset). Each reporter has:
org_namestring | nullgoogle.com. Pass it as org_name to List aggregate reports to see its reports.org_emailstring | nullreport_countintegerReturns 404 if the domain doesn’t exist in the workspace.
{
"data": [
{ "org_name": "google.com", "org_email": "noreply-dmarc-support@google.com", "report_count": 30 },
{ "org_name": "Enterprise Outlook", "org_email": "dmarcreport@microsoft.com", "report_count": 28 },
{ "org_name": "Yahoo", "org_email": "dmarchelp@yahooinc.com", "report_count": 14 }
],
"meta": { "limit": 50, "offset": 0 }
}{
"error": "Domain not found"
}