Read your numbers into Prometheus
From Teams up
From Teams up, https://www.mailmoni.com/metrics gives Prometheus your organization's numbers in its own text format: messages by source and DMARC result, when the last report arrived, how each DNS check went and how many alerts are open. Prometheus reads it with an API token.
Set up the scrape
An admin creates a token under Settings → Developer → API tokens, as API tokens explains. Add this job to prometheus.yml, with the token in place of YOUR_TOKEN:
scrape_configs:
- job_name: mailmoni
scheme: https
metrics_path: /metrics
scrape_interval: 60s
authorization:
credentials: YOUR_TOKEN
static_configs:
- targets: ["www.mailmoni.com"]
Prometheus sends the token in the Authorization header. The page that shows a new token shows this job with the token already in it.
How often to scrape
/metrics has a count of its own for each token and clock hour, apart from the API's:
| Plan | Scrapes per hour, per token |
|---|---|
| Starter | 0 |
| Pro | 0 |
| Teams | 360 |
| Enterprise | 1,800 |
A scrape reads numbers at most 5 minutes old, so one scrape a minute is enough. A scrape over the count gets rate_limited with a Retry-After header.
The series
| Series | What it counts | Labels |
|---|---|---|
mailmoni_messages | Messages reported for the domain, by source and DMARC result, over the last complete UTC day (1d) or the last seven (7d). | domain source result window |
mailmoni_last_report_timestamp_seconds | When the newest report of this kind for the domain was stored, as a Unix timestamp. | domain kind |
mailmoni_dns_check_ok | 1 when the latest DNS check of this record found nothing worse than information, else 0. | domain check |
mailmoni_dns_last_check_timestamp_seconds | When the domain's DNS records were last checked, as a Unix timestamp. | domain |
mailmoni_open_alerts | Open alerts for the domain, by severity. | domain severity |
The descriptions are in English, as Prometheus shows them. The names and labels are fixed, so dashboards and alert rules built on them keep working.
The labels
domain: every verified primary domain of the organization. A subdomain's mail is counted in its primary domain'smailmoni_messages, so asum()counts it once. The DNS series list each subdomain as well.source: the sending service's name,unidentifiedfor mail we could not match to a service, andotherfor everything outside each domain's top 25 sources by volume in the7dwindow.result:passorfail, for DMARC.window:1dfor the last complete UTC day,7dfor the last seven. Both end yesterday, so today's reports show up tomorrow.kind:aggregateortls, the kind of report.check: the DNS record the check read, such asdmarcorspf.severity: the severity of the open alerts.
Example queries
The share of each domain's mail that passed DMARC in the 7d window:
sum by (domain) (mailmoni_messages{result="pass", window="7d"})
/ sum by (domain) (mailmoni_messages{window="7d"})
DNS checks that found a warning or a problem, anything worse than a note:
mailmoni_dns_check_ok == 0
Domains with no aggregate report stored for two days:
time() - mailmoni_last_report_timestamp_seconds{kind="aggregate"} > 2 * 86400
A domain that has never stored an aggregate report has no such series, so this query does not list it. absent() finds a series that is missing:
absent(mailmoni_last_report_timestamp_seconds{domain="example.com", kind="aggregate"})
When the plan changes
Below Teams, /metrics answers plan with status 403. The tokens are kept, and a scrape works again once the organization is on a plan from Teams up.
Published 27 October 2026 · Checked 27 October 2026