API Reference
Integrate DDMARC into your applications with our REST API. Manage domains, retrieve reports, and automate your email authentication workflow.
RESTful
JSON over HTTPS
API keys
X-API-Key or Bearer
Rate limited
Hourly, per plan
Scoped
read / write / admin
Base URL
https://api.ddmarc.com/api/v1Every path on this page already includes the /api/v1 prefix, so a full URL looks like https://api.ddmarc.com/api/v1/domains. All requests must be made over HTTPS.
Authentication
Programmatic access uses an API key. Create and revoke keys in the dashboard under Settings → Organization → API Keys, or through the /api/v1/api-keys endpoints. Keys are shown once at creation and require the Protect plan or higher.
X-API-Key: ddmarc_<64 hex characters>Authorization: Bearer ddmarc_<64 hex characters>The same Authorization: Bearer header also accepts a short-lived JWT access token from a dashboard sign-in. If both X-API-Key and Authorization are sent, the API key wins. See Authentication for key format, scopes and token lifetimes.
Keep your API key secure
Never expose your API key in client-side code or public repositories. Store it in a secrets manager and revoke keys you no longer use.
Example Request
curl -X GET "https://api.ddmarc.com/api/v1/domains?limit=100&offset=0" \
-H "X-API-Key: $DDMARC_API_KEY"Example Response
List endpoints return a bare JSON array — there is no data / meta envelope, and resource ids are integers.
[
{
"id": 42,
"domain": "example.com",
"rua_token": "a1b2c3d4e5",
"ruf_token": "f6g7h8i9j0",
"verification_token": "ddmarc-verify-9f3c1a",
"is_verified": true,
"verified_at": "2026-01-15T11:00:00Z",
"dmarc_verified": true,
"spf_verified": true,
"dkim_verified": false,
"admin_email": null,
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-02-01T08:12:44Z",
"reports_count": 1250,
"last_report_at": "2026-02-01T06:00:00Z"
}
]Endpoints
Path parameters shown in braces are integers, except {customer_public_id}, which is an opaque string.
Domains
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/domains | List all domains |
| POST | /api/v1/domains | Add a new domain |
| GET | /api/v1/domains/{domain_id} | Get domain details |
| DELETE | /api/v1/domains/{domain_id} | Remove a domain |
| GET | /api/v1/domains/{domain_id}/dns-check | Check the domain's live DNS records |
| POST | /api/v1/domains/{domain_id}/verify | Verify domain ownership |
| POST | /api/v1/domains/{domain_id}/rotate-token | Rotate the domain's RUA/RUF tokens |
| GET | /api/v1/domains/{domain_id}/recommendations | Get configuration recommendations |
Full reference: Domains API.
Reports
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/reports | List DMARC aggregate reports |
| GET | /api/v1/reports/{report_id} | Get report details |
| GET | /api/v1/reports/stats/summary | Get aggregated report statistics |
| POST | /api/v1/reports/upload | Upload a DMARC report file |
| GET | /api/v1/reports/export/csv | Export report records as CSV |
Full reference: Reports API.
Dashboard analytics
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/dashboard/stats | Get summary statistics |
| GET | /api/v1/dashboard/trend | Get authentication trend over time |
| GET | /api/v1/dashboard/geo | Get geographic distribution |
| GET | /api/v1/dashboard/heatmap | Get volume heatmap data |
| GET | /api/v1/dashboard/protocol-breakdown | Get SPF/DKIM pass-rate breakdown |
| GET | /api/v1/dashboard/top-sources | Get the highest-volume sending sources |
| GET | /api/v1/dashboard/policy-distribution | Get policy distribution across domains |
| GET | /api/v1/dashboard/compliance-scorecard | Get the per-domain compliance scorecard |
Aggregated analytics live under /dashboard. Most accept an optional domain_id and a dayswindow (1–365, capped to your plan's retention).
Senders
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/senders | List all senders |
| GET | /api/v1/senders/{sender_id} | Get sender details |
| PATCH | /api/v1/senders/{sender_id} | Update a sender's category, display name or notes |
| PATCH | /api/v1/senders/bulk | Bulk-update senders |
| GET | /api/v1/senders/isp-analytics | Get ISP/provider breakdown statistics |
| GET | /api/v1/senders/ip-trends | Get sender IP behaviour trends |
| GET | /api/v1/senders/{sender_id}/reputation | Get sender reputation detail |
| GET | /api/v1/senders/{sender_id}/remediation | Get suggested remediation for a sender |
A sender's state is changed by sending a category value to PATCH /api/v1/senders/{sender_id}. There are no separate approve or reject endpoints.
Failure analysis
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/failure-analysis/summary | Get failure totals and split by mechanism |
| GET | /api/v1/failure-analysis/root-causes | Get classified root causes with fix suggestions |
| GET | /api/v1/failure-analysis/root-causes/by-source | Get root causes grouped by sending source |
| GET | /api/v1/failure-analysis/sources | List failing sources |
| GET | /api/v1/failure-analysis/spoof-clusters | Get suspected spoofing campaign clusters |
| GET | /api/v1/failure-analysis/by-header-from | Get failures grouped by spoofed From identity |
| GET | /api/v1/failure-analysis/trend | Get failure trend over time |
| GET | /api/v1/failure-analysis/resolution-stats | Get time-to-resolution statistics |
Every endpoint accepts days(1–365, default 30) and an optional domain_id.
Forensic reports
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/forensic-reports | List forensic (RUF) reports |
| GET | /api/v1/forensic-reports/{report_id} | Get forensic report details |
| GET | /api/v1/forensic-reports/stats | Get forensic summary statistics |
| DELETE | /api/v1/forensic-reports/{report_id} | Delete a forensic report |
Forensic (RUF) reports require the Protect plan or higher.
DNS monitoring
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/dns-monitoring/overview | Get DNS monitoring overview for all domains |
| GET | /api/v1/dns-monitoring/health | Get DNS health across all domains |
| GET | /api/v1/dns-monitoring/domains/{domain_id}/history | Get a domain's DNS record history |
| GET | /api/v1/dns-monitoring/domains/{domain_id}/trends | Get a domain's DNS health trend |
| POST | /api/v1/dns-monitoring/domains/{domain_id}/check-now | Trigger an immediate DNS check |
| PUT | /api/v1/dns-monitoring/domains/{domain_id}/settings | Update a domain's monitoring settings |
Managed policy
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/domains/{domain_id}/policy | Get the managed DNS policy for a domain |
| POST | /api/v1/domains/{domain_id}/policy | Create a managed policy |
| PATCH | /api/v1/domains/{domain_id}/policy | Update a managed policy |
| POST | /api/v1/domains/{domain_id}/policy/publish | Publish the policy to DNS |
| GET | /api/v1/domains/{domain_id}/simulate-policy | Simulate the impact of a policy change |
Policy rollouts
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/rollouts | List policy rollouts across domains |
| GET | /api/v1/domains/{domain_id}/rollout | Get a domain's rollout status |
| POST | /api/v1/domains/{domain_id}/rollout | Create a rollout for a domain |
| POST | /api/v1/domains/{domain_id}/rollout/start | Start the rollout |
| POST | /api/v1/domains/{domain_id}/rollout/pause | Pause the rollout |
| POST | /api/v1/domains/{domain_id}/rollout/resume | Resume a paused rollout |
| POST | /api/v1/domains/{domain_id}/rollout/skip | Skip to the next stage |
| POST | /api/v1/domains/{domain_id}/rollout/rollback | Roll back to the previous stage |
| GET | /api/v1/domains/{domain_id}/rollout/history | Get rollout stage history |
A rollout belongs to a domain, so every mutating route is nested under /domains/{domain_id}/rollout. The bare /rollouts collection is read-only.
Alerts and alert rules
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/alerts | List alerts |
| POST | /api/v1/alerts/{alert_id}/read | Mark an alert as read |
| POST | /api/v1/alerts/read-all | Mark all alerts as read |
| PATCH | /api/v1/alerts/{alert_id}/snooze | Snooze an alert |
| GET | /api/v1/alerts/rules | List custom alert rules |
| POST | /api/v1/alerts/rules | Create a custom alert rule |
| PATCH | /api/v1/alerts/rules/{rule_id} | Update a custom alert rule |
| DELETE | /api/v1/alerts/rules/{rule_id} | Delete a custom alert rule |
| GET | /api/v1/alerts/preferences | Get notification preferences |
| PATCH | /api/v1/alerts/preferences | Update notification preferences |
| POST | /api/v1/alerts/webhook/test | Send a test webhook |
Alert rules are created under /alerts/rules, not on the bare /alerts collection, which is read-only.
TLS-RPT
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/tls-rpt | List TLS-RPT reports |
| GET | /api/v1/tls-rpt/{report_id} | Get TLS-RPT report details |
| GET | /api/v1/tls-rpt/stats/summary | Get TLS-RPT summary statistics |
| POST | /api/v1/tls-rpt/upload | Upload a TLS-RPT report file |
SMTP TLS reporting requires the Protect plan or higher.
ARC monitoring
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/arc-monitoring/overview | Get ARC monitoring overview |
| GET | /api/v1/arc-monitoring/domains/{domain_id}/chains | List ARC chains for a domain |
| GET | /api/v1/arc-monitoring/chains/{chain_id} | Get ARC chain details |
| GET | /api/v1/arc-monitoring/forwarders | List known forwarders |
| POST | /api/v1/arc-monitoring/forwarders | Add a trusted forwarder |
ARC chain monitoring requires the Growth plan or higher.
Lookalike domains
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/domains/{domain_id}/lookalikes | List detected lookalike domains |
| POST | /api/v1/domains/{domain_id}/lookalikes/scan | Trigger a lookalike domain scan |
Typosquat detection requires the Professional plan or higher.
API keys
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/api-keys | List API keys |
| POST | /api/v1/api-keys | Create an API key |
| DELETE | /api/v1/api-keys/{key_id} | Revoke an API key |
Key management is admin-only. See Authentication for scopes and per-plan key caps.
Team
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/team | List team members |
| POST | /api/v1/team/invite | Invite a team member |
| PATCH | /api/v1/team/members/{user_id}/role | Change a member's role |
| DELETE | /api/v1/team/members/{user_id} | Remove a team member |
| DELETE | /api/v1/team/invite/{invitation_id} | Revoke a pending invitation |
Activity log
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/activity | List activity log entries |
| GET | /api/v1/activity/actions | List available activity action types |
| GET | /api/v1/activity/export/csv | Export the activity log as CSV |
MSP Management
Partner Plan| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/msp/customers | List MSP customers |
| POST | /api/v1/msp/customers | Create a new customer |
| GET | /api/v1/msp/customers/{customer_public_id}/detail | Get customer details |
| DELETE | /api/v1/msp/customers/{customer_public_id} | Delete a customer |
| GET | /api/v1/msp/billing | Get MSP billing summary |
| GET | /api/v1/msp/branding | Get MSP branding config |
| PATCH | /api/v1/msp/branding | Update MSP branding |
MSP customer routes take {customer_public_id}, the customer's opaque public identifier — not an integer id.
Outbound notifications
There is no webhook CRUD resource. Outbound delivery is configured per user in notification preferences (GET / PATCH /api/v1/alerts/preferences) and fires when an alert is raised. You can send a probe to any URL with POST /api/v1/alerts/webhook/test. See Webhooks for the payload shape and the delivery guarantees that do and do not exist today.
Rate Limiting
API-key requests are metered hourly and pooled across your whole organization, not per key. There is no per-minute limit and no daily cap.
| Plan | Request limit | API keys |
|---|---|---|
| Monitor | No API access | — |
| Protect | 1,000 requests / hour | 1 key |
| Growth | 5,000 requests / hour | 3 keys |
| Professional | 10,000 requests / hour | 10 keys |
| Partner Starter | 25,000 requests / hour | Unlimited |
| Partner | 25,000 requests / hour | Unlimited |
| Enterprise | Custom | Unlimited |
Exceeding the cap returns 429 with a Retry-After: 3600 header. The API does not emit X-RateLimit-*headers, so do not rely on them for client-side budgeting — track your own request count, or back off when you see a 429.
Errors
| Code | Status | Description |
|---|---|---|
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Missing, invalid or expired API key |
| 403 | Forbidden | Key scope too low, or the feature is not on your plan |
| 404 | Not Found | Resource not found, or not owned by your organization |
| 422 | Unprocessable Entity | Request body or query failed validation |
| 429 | Too Many Requests | Hourly rate limit exceeded; see Retry-After |
| 500 | Internal Error | Server error - quote the request_id to support |
{
"detail": "Invalid API key"
}{
"detail": "Internal server error",
"request_id": "9f2b41c7-..."
}Validation failures (422) use FastAPI's structured form, where detail is an array of field errors rather than a string.
Client libraries
DDMARC does not publish official SDKs. The API is plain JSON over HTTPS with a single authentication header, so any HTTP client works — curl, fetch, requests, or your language's equivalent. If you need a generated client, the running API serves its own OpenAPI schema.