Skip to content
REST API v1 · the complete surface

API Reference

Integrate DDMARC into your own systems. Manage domains, retrieve reports, and automate your email authentication workflow over plain JSON and HTTPS.

01 — Getting oriented

Base URL and shape

RESTful

JSON over HTTPS. No envelope on list responses.

API keys

X-API-Key, or Authorization: Bearer.

Rate limited

Hourly, pooled per organization.

Scoped

read, write or admin, per key.

Base URL
https://api.ddmarc.com/api/v1

Every 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.

02 — Getting in

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.

Included from Protect ($29/mo).Start a 14-day trial →See the Protect plan →

Preferred: X-API-Key header
X-API-Key: ddmarc_<64 hex characters>
Also accepted: Authorization header
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 a key in client-side code or a public repository. Store it in a secrets manager, and revoke keys you no longer use.
03 — End to end

A request and its response

cURL
curl -X GET "https://api.ddmarc.com/api/v1/domains?limit=100&offset=0" \
  -H "X-API-Key: $DDMARC_API_KEY"

List endpoints return a bare JSON array — there is no data / meta envelope, and resource ids are integers.

200 OK · application/json
[
  {
    "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"
  }
]
04 — The surface

Every endpoint

Path parameters shown in braces are integers, except {customer_public_id}, which is an opaque string.

Domains

GET/api/v1/domainsList all domains
POST/api/v1/domainsAdd 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-checkCheck the domain's live DNS records
POST/api/v1/domains/{domain_id}/verifyVerify domain ownership
POST/api/v1/domains/{domain_id}/rotate-tokenRotate the domain's RUA/RUF tokens
GET/api/v1/domains/{domain_id}/recommendationsGet configuration recommendations
Full reference: Domains API.

Reports

GET/api/v1/reportsList DMARC aggregate reports
GET/api/v1/reports/{report_id}Get report details
GET/api/v1/reports/stats/summaryGet aggregated report statistics
POST/api/v1/reports/uploadUpload a DMARC report file
GET/api/v1/reports/export/csvExport report records as CSV
Full reference: Reports API.

Dashboard analytics

GET/api/v1/dashboard/statsGet summary statistics
GET/api/v1/dashboard/trendGet authentication trend over time
GET/api/v1/dashboard/geoGet geographic distribution
GET/api/v1/dashboard/heatmapGet volume heatmap data
GET/api/v1/dashboard/protocol-breakdownGet SPF/DKIM pass-rate breakdown
GET/api/v1/dashboard/top-sourcesGet the highest-volume sending sources
GET/api/v1/dashboard/policy-distributionGet policy distribution across domains
GET/api/v1/dashboard/compliance-scorecardGet the per-domain compliance scorecard
Aggregated analytics live under /dashboard. Most accept an optional domain_id and a days window (1–365, capped to your plan's retention).

Senders

GET/api/v1/sendersList 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/bulkBulk-update senders
GET/api/v1/senders/isp-analyticsGet ISP/provider breakdown statistics
GET/api/v1/senders/ip-trendsGet sender IP behavior trends
GET/api/v1/senders/{sender_id}/reputationGet sender reputation detail
GET/api/v1/senders/{sender_id}/remediationGet 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

GET/api/v1/failure-analysis/summaryGet failure totals and split by mechanism
GET/api/v1/failure-analysis/root-causesGet classified root causes with fix suggestions
GET/api/v1/failure-analysis/root-causes/by-sourceGet root causes grouped by sending source
GET/api/v1/failure-analysis/sourcesList failing sources
GET/api/v1/failure-analysis/spoof-clustersGet suspected spoofing campaign clusters
GET/api/v1/failure-analysis/by-header-fromGet failures grouped by spoofed From identity
GET/api/v1/failure-analysis/trendGet failure trend over time
GET/api/v1/failure-analysis/resolution-statsGet time-to-resolution statistics

Forensic reports

GET/api/v1/forensic-reportsList forensic (RUF) reports
GET/api/v1/forensic-reports/{report_id}Get forensic report details
GET/api/v1/forensic-reports/statsGet forensic summary statistics
DELETE/api/v1/forensic-reports/{report_id}Delete a forensic report

DNS monitoring

GET/api/v1/dns-monitoring/overviewGet DNS monitoring overview for all domains
GET/api/v1/dns-monitoring/healthGet DNS health across all domains
GET/api/v1/dns-monitoring/domains/{domain_id}/historyGet a domain's DNS record history
GET/api/v1/dns-monitoring/domains/{domain_id}/trendsGet a domain's DNS health trend
POST/api/v1/dns-monitoring/domains/{domain_id}/check-nowTrigger an immediate DNS check
PUT/api/v1/dns-monitoring/domains/{domain_id}/settingsUpdate a domain's monitoring settings

DNS policy

GET/api/v1/domains/{domain_id}/policyGet the managed DNS policy for a domain
POST/api/v1/domains/{domain_id}/policyCreate a managed policy
PATCH/api/v1/domains/{domain_id}/policyUpdate a managed policy
POST/api/v1/domains/{domain_id}/policy/publishPublish the policy to DNS
GET/api/v1/domains/{domain_id}/simulate-policySimulate the impact of a policy change

Policy rollouts

GET/api/v1/rolloutsList policy rollouts across domains
GET/api/v1/domains/{domain_id}/rolloutGet a domain's rollout status
POST/api/v1/domains/{domain_id}/rolloutCreate a rollout for a domain
POST/api/v1/domains/{domain_id}/rollout/startStart the rollout
POST/api/v1/domains/{domain_id}/rollout/pausePause the rollout
POST/api/v1/domains/{domain_id}/rollout/resumeResume a paused rollout
POST/api/v1/domains/{domain_id}/rollout/skipSkip to the next stage
POST/api/v1/domains/{domain_id}/rollout/rollbackRoll back to the previous stage
GET/api/v1/domains/{domain_id}/rollout/historyGet rollout stage history

Alerts

GET/api/v1/alertsList alerts
POST/api/v1/alerts/{alert_id}/readMark an alert as read
POST/api/v1/alerts/read-allMark all alerts as read
PATCH/api/v1/alerts/{alert_id}/snoozeSnooze an alert
GET/api/v1/alerts/rulesList custom alert rules
POST/api/v1/alerts/rulesCreate 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/preferencesGet notification preferences
PATCH/api/v1/alerts/preferencesUpdate notification preferences
POST/api/v1/alerts/webhook/testSend a test webhook

TLS-RPT

GET/api/v1/tls-rptList TLS-RPT reports
GET/api/v1/tls-rpt/{report_id}Get TLS-RPT report details
GET/api/v1/tls-rpt/stats/summaryGet TLS-RPT summary statistics
POST/api/v1/tls-rpt/uploadUpload a TLS-RPT report file

ARC monitoring

GET/api/v1/arc-monitoring/overviewGet ARC monitoring overview
GET/api/v1/arc-monitoring/domains/{domain_id}/chainsList ARC chains for a domain
GET/api/v1/arc-monitoring/chains/{chain_id}Get ARC chain details
GET/api/v1/arc-monitoring/forwardersList known forwarders
POST/api/v1/arc-monitoring/forwardersAdd a trusted forwarder

Lookalike domains

GET/api/v1/domains/{domain_id}/lookalikesList detected lookalike domains
POST/api/v1/domains/{domain_id}/lookalikes/scanTrigger a lookalike domain scan

API keys

GET/api/v1/api-keysList API keys
POST/api/v1/api-keysCreate an API key
DELETE/api/v1/api-keys/{key_id}Revoke an API key

Team

GET/api/v1/teamList team members
POST/api/v1/team/inviteInvite a team member
PATCH/api/v1/team/members/{user_id}/roleChange 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

GET/api/v1/activityList activity log entries
GET/api/v1/activity/actionsList available activity action types
GET/api/v1/activity/export/csvExport the activity log as CSV

MSP management

GET/api/v1/msp/customersList MSP customers
POST/api/v1/msp/customersCreate a new customer
GET/api/v1/msp/customers/{customer_public_id}/detailGet customer details
PATCH/api/v1/msp/customers/{customer_public_id}Rename a customer or set its domain cap (max_domains)
DELETE/api/v1/msp/customers/{customer_public_id}Delete a customer
POST/api/v1/msp/customers/{customer_public_id}/domainsEnroll a domain under a customer
GET/api/v1/msp/billingGet MSP billing summary
GET/api/v1/msp/billing/usagePer-customer domain usage
GET/api/v1/msp/brandingGet MSP branding config
PATCH/api/v1/msp/brandingUpdate MSP branding
Partner plan. MSP customer routes take {customer_public_id}, the customer's opaque public identifier — not an integer id.
There is no webhook 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 for the delivery guarantees that do and do not exist today.
05 — Budgeting

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.

MonitorNo API access—
Protect1,000 requests / hour1 key
Growth5,000 requests / hour3 keys
Professional10,000 requests / hour10 keys
Partner Starter25,000 requests / hourUnlimited
Partner25,000 requests / hourUnlimited
EnterpriseCustomUnlimited
No X-RateLimit headers
Exceeding the cap returns 429 with a Retry-After: 3600 header. The API does not emit X-RateLimit-* headers, so do not budget against them — track your own request count, or back off when you see a 429.
06 — When it goes wrong

Errors

CodeStatusWhat it means
400Bad RequestInvalid request parameters
401UnauthorizedMissing, invalid or expired API key
403ForbiddenKey scope too low, or the feature is not on your plan
404Not FoundResource not found, or not owned by your organization
422Unprocessable EntityRequest body or query failed validation
429Too Many RequestsHourly rate limit exceeded; see Retry-After
500Internal ErrorServer error — quote the request_id to support
401
{
  "detail": "Invalid API key"
}
500
{
  "detail": "Internal server error",
  "request_id": "9f2b41c7-..."
}

Validation failures (422) use FastAPI's structured form, where detail is an array of field errors, not a string.

07 — Tooling

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.