Pull DMARC data into your own tools. Build alerts, dashboards, and automations that fit your workflow.
The DMARCTrust dashboard shows you what is happening with your email authentication. The API lets you act on it. Pull your DMARC data into Slack, your SIEM, a cron job, or a custom dashboard, whatever your team already uses.
What people build with this API
Slack/Teams alerts when a new sender starts using your domain or authentication failures spike
SIEM integration to feed DMARC source data into Splunk, Datadog, or Grafana
Automated domain onboarding for MSPs managing hundreds of client domains
Scheduled CSV exports of daily stats and source data for compliance reporting
DNS health checks in CI/CD pipelines to catch misconfigurations before they go live
Prerequisites
An active DMARCTrust subscription (Starter or Pro plan)
At least one domain configured in your account
Getting started
Generate an API key
Go to Settings in your dashboard and scroll to the API keys section. Click Create API key, give it a name that describes its purpose (e.g., "Slack bot" or "Nightly export"), and copy the key. It is only shown once.
Every request requires a Bearer token in the Authorization header:
Authorization: Bearer dt_live_your_api_key_here
Missing or invalid keys return 401. Expired subscriptions return 403.
Rate limits
Client type
Limit
Authenticated (with API key)
30 requests/minute
Unauthenticated
2 requests/minute per IP
When rate limited, you get a 429 response with a retry_after field (seconds) and rate limit headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
Endpoints
Base URL: https://www.dmarctrust.com/api/v1
Account
GET /account
Returns your account details, subscription status, and 30-day usage statistics.
Domains
List all domains
GET /domains
Returns all domains in your account with their DNS status and activation state.
Resources use prefixed IDs so you can tell them apart at a glance:
Resource
Prefix
Example
User
usr_
usr_123
Domain
ud_
ud_19
Report
rpt_
rpt_915
Both prefixed and raw numeric IDs work: GET /domains/ud_19 and GET /domains/19 return the same result.
Error handling
All errors return a JSON object with a machine-readable code and a human-readable message:
{
"error": {
"code": "not_found",
"message": "The requested resource could not be found",
"request_id": "abc123-..."
}
}
HTTP status
Code
Meaning
400
bad_request
Malformed request or invalid parameters
401
invalid_api_key
API key is missing or invalid
403
subscription_required
No active subscription
403
retention_exceeded
Data is outside your plan's retention window
404
not_found
Resource does not exist or is not in your account
422
unprocessable_entity
Validation failed (e.g., invalid domain format)
429
rate_limit_exceeded
Too many requests. Check retry_after field.
Include the request_id when contacting support. It lets us find your exact request in our logs.
Integration examples
Slack alert for DMARC failures
This Python script checks for authentication failures in the last 48 hours and posts a summary to Slack. Run it as a daily cron job.
import requests, json, os
API_KEY = os.environ["DMARCTRUST_API_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]
BASE = "https://www.dmarctrust.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
# Get all domains
domains = requests.get(f"{BASE}/domains", headers=headers).json()["data"]
alerts = []
for d in domains:
resp = requests.get(
f"{BASE}/domains/{d['id']}/sources",
headers=headers, params={"range": "48h"}
).json()["data"]
for src in resp["sources"]:
rejected = src.get("rejected", 0)
quarantined = src.get("quarantined", 0)
if rejected + quarantined > 0:
alerts.append(
f"*{d['domain']}*: {src['sender_domain']} "
f"({rejected} rejected, {quarantined} quarantined)"
)
if alerts:
requests.post(SLACK_WEBHOOK, json={
"text": f"DMARC failures (last 48h):\n" + "\n".join(alerts)
})
Export daily stats to CSV
Pull 30 days of per-domain statistics and write them to a CSV file. Useful for compliance reports or feeding data into a spreadsheet.
import requests, csv, os
API_KEY = os.environ["DMARCTRUST_API_KEY"]
BASE = "https://www.dmarctrust.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
domains = requests.get(f"{BASE}/domains", headers=headers).json()["data"]
with open("dmarc_stats.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["domain", "date", "total", "spf_pass", "spf_fail",
"dkim_pass", "dkim_fail"])
for d in domains:
stats = requests.get(
f"{BASE}/domains/{d['id']}/stats", headers=headers
).json()["data"]["daily_stats"]
for day in stats:
writer.writerow([
d["domain"], day["date"], day["total_messages"],
day["spf_pass"], day["spf_fail"],
day["dkim_pass"], day["dkim_fail"]
])
DNS health check in a shell script
Check all domains and exit with a non-zero status if any DNS record is invalid. Plug this into a CI/CD pipeline or a monitoring cron.
#!/bin/bash
set -e
API_KEY="${DMARCTRUST_API_KEY}"
BASE="https://www.dmarctrust.com/api/v1"
ERRORS=0
DOMAINS=$(curl -s -H "Authorization: Bearer $API_KEY" "$BASE/domains" | jq -r '.data[] | .id')
for ID in $DOMAINS; do
DNS=$(curl -s -H "Authorization: Bearer $API_KEY" "$BASE/domains/$ID/dns")
DOMAIN=$(echo "$DNS" | jq -r '.data.domain')
DMARC_STATUS=$(echo "$DNS" | jq -r '.data.dmarc.status')
SPF_STATUS=$(echo "$DNS" | jq -r '.data.spf.status')
if [ "$DMARC_STATUS" != "valid" ] || [ "$SPF_STATUS" != "valid" ]; then
echo "FAIL: $DOMAIN (DMARC=$DMARC_STATUS, SPF=$SPF_STATUS)"
ERRORS=$((ERRORS + 1))
fi
done
if [ $ERRORS -gt 0 ]; then
echo "$ERRORS domain(s) have DNS issues"
exit 1
fi
echo "All domains healthy"
Client libraries
There is no official SDK. The API uses standard REST conventions, so any HTTP client works. Here are starter examples in three languages.
Python
import requests, os
API_KEY = os.environ["DMARCTRUST_API_KEY"]
BASE_URL = "https://www.dmarctrust.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
# List domains
domains = requests.get(f"{BASE_URL}/domains", headers=headers).json()["data"]
for d in domains:
print(f"{d['domain']}: {d['dns_status']}")
# Get reports for a specific domain
reports = requests.get(
f"{BASE_URL}/reports", headers=headers,
params={"domain_id": "ud_19", "limit": 50}
).json()["data"]
JavaScript (Node.js)
const API_KEY = process.env.DMARCTRUST_API_KEY;
const BASE_URL = "https://www.dmarctrust.com/api/v1";
async function apiGet(path, params = {}) {
const url = new URL(`${BASE_URL}${path}`);
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
const res = await fetch(url, {
headers: { Authorization: `Bearer ${API_KEY}` }
});
if (!res.ok) throw new Error(`API error: ${res.status}`);
return res.json();
}
// List domains
const { data: domains } = await apiGet("/domains");
// Get sources for a domain (last 48 hours)
const { data: sources } = await apiGet(`/domains/${domains[0].id}/sources`, { range: "48h" });
Ruby
require "net/http"
require "json"
API_KEY = ENV.fetch("DMARCTRUST_API_KEY")
BASE_URL = "https://www.dmarctrust.com/api/v1"
def api_get(endpoint, params = {})
uri = URI("#{BASE_URL}#{endpoint}")
uri.query = URI.encode_www_form(params) if params.any?
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{API_KEY}"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
JSON.parse(res.body)
end
# List domains
domains = api_get("/domains")
domains["data"].each { |d| puts "#{d['domain']}: #{d['dns_status']}" }
# Get DNS records
dns = api_get("/domains/ud_19/dns")
puts "DMARC: #{dns.dig('data', 'dmarc', 'status')}"
Managing API keys
All your keys are listed in Settings > API keys. For each key you can see the name, the first 12 characters (so you can identify it), when it was created, and when it was last used.
To revoke a key, click the trash icon next to it. Revoked keys stop working immediately. Any application using that key will get 401 responses.
Security practices
Use one key per application so you can revoke them independently.
Store keys in environment variables, not in code. Never commit them to git.
Rotate keys periodically. Create the new key, update your application, then revoke the old one.
Check "last used" dates to find unused keys and clean them up.
Need help? Include the request_id from error responses when contacting support. It lets us find your exact request in our logs.