Start free
In this section

API: tokens, endpoints and webhooks

Which requests does the API answer?

From Pro up

The API answers the requests below. The OpenAPI document at https://www.mailmoni.com/api/v1/openapi.json describes each one in full: its parameters, the fields of its answer and the errors it can give. This table is built from that document, so the two always agree.

RequestWhat it does
GET /api/v1/alertsList alerts, newest first, with the same data as alert webhooks
GET /api/v1/domainsList the organization's live domains, each primary followed by its subdomains
GET /api/v1/domains/{domain}Get one domain with its subdomains, reporting address and DNS check counts
GET /api/v1/domains/{domain}/dnsGet the latest check of every DNS record, with each finding explained
GET /api/v1/domains/{domain}/dns/historyList what the domain's DNS records said over time, newest first
GET /api/v1/domains/{domain}/recordsList aggregate records for the window, newest first, with each record's explanation
GET /api/v1/domains/{domain}/reportsList one kind of report for the window, newest first
GET /api/v1/domains/{domain}/sourcesList the window's sources, largest first, with the app's verdict and explanation
GET /api/v1/domains/{domain}/sources/{source_id}Get one source with its explanation, what to do, its addresses and latest records
GET /api/v1/domains/{domain}/summaryMessages, DMARC results, policy and readiness for a window
POST /api/v1/exportsStart an export of one domain's records or report files
GET /api/v1/exports/{export_id}Read an export's status
GET /api/v1/exports/{export_id}/downloadDownload a ready export: CSV, NDJSON or a zip of report files
GET /api/v1/organizationRead the organization the token belongs to
GET /api/v1/reports/{kind}/{report_id}Get one parsed report
GET /api/v1/reports/{kind}/{report_id}/rawDownload the report file as received: XML for an aggregate report, JSON for a TLS report, the message for a forensic report kept in full

The API overview covers what every request shares: the token, the hourly count, pages, days and errors.

A domain in the path

A path takes one of your organization's domain names, a primary domain or a subdomain, such as example.com or mail.example.com. A subdomain reads its primary domain's sources and records, limited to mail sent from the subdomain, as the app shows them. A domain of another organization answers not_found, the same as one that does not exist.

Reports

A report's kind is aggregate, tls or forensic. The list of a domain's reports takes one kind in its kind parameter, and lists aggregate reports when you leave it out.

One aggregate report's answer holds at most 500 of its records. When the report has more, records_truncated is true and record_count says how many there are. The records request lists every record of a window, and each record names its report, so ask it for the report's days to get the rest.

The raw request gives the file we read the report from, already unpacked from any gzip or zip: the XML of an aggregate report, the JSON of a TLS report, and the original message of a forensic report we keep in full.

Start an export

From Teams up, a token with write access starts an export with POST /api/v1/exports. The body is a JSON object with these fields:

Field What it says
domain Required. The domain or subdomain. A subdomain exports its primary domain's data for mail sent from the subdomain.
kind Required. records_csv, records_ndjson, or raw for the report files in a zip.
from, to The days, as every request takes them. Without them, the last 7 days, ending yesterday.
report_kinds For raw only. Any of aggregate, tls and forensic. Without it, ["aggregate"].
header_from Only mail with this From domain. For a subdomain it can only be the subdomain itself.

Any other field is refused with invalid_parameter, which names the field.

curl -X POST https://www.mailmoni.com/api/v1/exports \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domain": "example.com", "kind": "records_csv", "from": "2026-10-01", "to": "2026-10-26"}'

The answer has status 202, the export's details and a Location header. Ask that address until the export's status is ready, or let the export.ready webhook tell you. Then download its download_url.

  • While the export is being built, the download answers export_running.
  • An export that failed has no file, and its download answers not_found. Start a new one.
  • We keep the file for 7 days. After that the download answers export_expired.
  • We build one export at a time for an organization, including the ones started in the app. A second request while one waits or is being built gets export_running.
  • An export started through the API sends no email. The export from the app does.

Published 27 October 2026 · Checked 27 October 2026