The Unspam platform can be accessed via API. API access is available exclusively on specific subscription plans. Please ensure your current plan supports API usage before integrating.
On this page:
All API requests should be made to: https://api.unspam.email/ext/v2
All requests require a Bearer token. You can find your API token on the Subscription page under API Token. Include it in every request as a header:
Authorization: Bearer YOUR_API_TOKEN
Browse the interactive API documentation (Swagger UI) for detailed endpoint descriptions, request/response schemas, and the ability to try endpoints directly.
Import the Postman collection to get started quickly with all available endpoints.
Prefer to drive Unspam from an AI assistant? The same functionality is available through our MCP server for Claude, ChatGPT, Cursor, and other MCP-compatible clients.
Fetch the enabled mailboxes you can run a test against. Use the returned id values to target specific mailboxes when starting a test.
curl https://api.unspam.email/ext/v2/inbox-placement/mailboxes \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
[
{ "id": 3, "name": "Mailbox 1", "address": "mailbox1@example.com" },
{ "id": 7, "name": "Mailbox 2", "address": "mailbox2@example.com" }
]
Step 1. Start a new test. Pass specific mailboxes IDs, or omit the field to use all available mailboxes. The response returns the test id and the mailboxes to send to.
curl -X POST https://api.unspam.email/ext/v2/inbox-placement \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mailboxes": [3, 7]
}'
{
"id": "abc123",
"mailboxes": [
{ "id": 3, "name": "Mailbox 1", "address": "mailbox1@example.com" },
{ "id": 7, "name": "Mailbox 2", "address": "mailbox2@example.com" }
]
}
Step 2. Send your email to each mailbox address, including the test id in the email body.
# Send your email to the mailbox addresses above.
# Include the test id ("abc123") somewhere in the email body.
# Wait a few minutes for delivery to be processed.
Step 3. Fetch the result with the test id — it shows the per-mailbox placement.
curl https://api.unspam.email/ext/v2/inbox-placement/abc123 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"id": "abc123",
"status": "completed",
"started_at": "2026-05-12T10:21:00Z",
"completed_at": "2026-05-12T10:24:00Z",
"results": [
{
"mailbox": { "id": 3, "name": "Mailbox 1", "address": "mailbox1@example.com" },
"status": "inbox",
"tab": "primary",
"sender": "news@yourdomain.com",
"sender_ip": "203.0.113.10",
"blacklists": 0
}
],
"report_url": "https://app.unspam.email/inbox-test/abc123",
"client_preview_id": null
}
The response includes client_preview_id — the id of this test's client preview (email-client renderings), or null if none has been created yet. Pass it to GET /client-previews/{id} to fetch the preview (see the Client Previews flow below).
inbox_address property.inbox_address.Step 1. Start a new test. The response returns the test id and the inbox_address to send your email to.
curl -X POST https://api.unspam.email/ext/v2/spam-check \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"id": "abc123",
"inbox_address": "spam-check-abc123@inbox.unspam.email"
}
Step 2. Send the email you want to analyze to the returned inbox_address.
# Send your email to the inbox_address above.
# Wait a few minutes for the system to analyze it.
Step 3. Fetch the result with the test id — it includes the spam score and per-check details.
curl https://api.unspam.email/ext/v2/spam-check/abc123 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"id": "abc123",
"status": "completed",
"created_at": "2026-05-12T10:21:00Z",
"completed_at": "2026-05-12T10:23:00Z",
"sender": "news@yourdomain.com",
"score": 9.2,
"results": [
{
"id": "spf",
"name": "SPF",
"test_info": "...",
"value": [ { "id": "spf_pass", "name": "Pass", "status": "ok" } ],
"meta": null
}
],
"report_url": "https://app.unspam.email/spam-check/abc123",
"client_preview_id": null
}
You can also fetch the email Screenshots (/spam-check/{id}/screenshots) and the Heatmap (/spam-check/{id}/heatmap) once the test is completed. To render the email across many email clients/devices, use the universal Client Previews resource (/client-previews) — see the Client Previews flow below.
The response also includes client_preview_id — the id of this test's client preview (email-client renderings), or null if none has been created yet. Pass it to GET /client-previews/{id} to fetch the preview.
Client Previews render an email across real email clients/devices (iOS Mail, Gmail, Outlook, etc.). Create a preview with POST /client-previews, then poll it until every device is rendered. Rendering is asynchronous: devices come back pending, so poll GET /client-previews/{id} until each device is completed (or failed).
device_key + name) via the Available Devices endpoint (GET /client-preview-devices) to render only specific ones.POST /client-previews. Set email_source to one of spam-check, inbox-placement, raw-data or email (see the four variants below). Optionally pass devices (an array of device_keys) — omit it to render all available devices.id, its status, an inbox_address (only for the email source), and the per-device previews array.GET /client-previews/{id} until status is completed. Each device then exposes its original image, thumbnail, and download URL.The request body accepts:
email_source (string, required) — spam-check, inbox-placement, raw-data or email.source_id (string) — required for spam-check and inbox-placement (the source's result id); its subject/body are pulled from the source. Omit for raw-data and email.subject (string) — required for raw-data (max 255). Ignored/derived otherwise.body (string, HTML) — required for raw-data. Ignored/derived otherwise.devices (string[]) — optional device keys from /client-preview-devices. Omit to use all available devices.The list endpoint (GET /client-previews, paginated, per_page defaults to 15) only returns previews whose email_source is raw-data or email and whose status is pending or completed. Previews created from a spam-check or inbox-placement are reached instead via that source's client_preview_id field.
Fetch the clients you can render against. Use the returned device_key values to target specific devices via the devices field when creating a preview.
curl https://api.unspam.email/ext/v2/client-preview-devices \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
[
{ "device_key": "ios_mail", "name": "iOS Mail" },
{ "device_key": "gmail_web", "name": "Gmail (Web)" },
{ "device_key": "outlook_chrome", "name": "Outlook (Chrome)" }
]
Pass the spam check's result id as source_id; the subject and body are pulled from that source. Omit devices to render all available devices.
curl -X POST https://api.unspam.email/ext/v2/client-previews \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email_source": "spam-check",
"source_id": "abc123"
}'
{
"id": "def456",
"email_source": "spam-check",
"status": "pending",
"inbox_address": null,
"previews": [
{
"device_key": "ios_mail",
"device_name": "iOS Mail",
"status": "pending",
"original": null,
"thumbnail": null,
"download": null
}
]
}
Same as the spam-check variant, but reference an inbox placement test's result id as source_id.
curl -X POST https://api.unspam.email/ext/v2/client-previews \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email_source": "inbox-placement",
"source_id": "abc123"
}'
{
"id": "def456",
"email_source": "inbox-placement",
"status": "pending",
"inbox_address": null,
"previews": [
{
"device_key": "ios_mail",
"device_name": "iOS Mail",
"status": "pending",
"original": null,
"thumbnail": null,
"download": null
}
]
}
Supply your own subject and HTML body instead of a source_id. Here we render only two specific devices.
curl -X POST https://api.unspam.email/ext/v2/client-previews \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email_source": "raw-data",
"subject": "Welcome!",
"body": "<html><body>Hello</body></html>",
"devices": ["ios_mail", "gmail_web"]
}'
{
"id": "def456",
"email_source": "raw-data",
"status": "pending",
"inbox_address": null,
"previews": [
{
"device_key": "ios_mail",
"device_name": "iOS Mail",
"status": "pending",
"original": null,
"thumbnail": null,
"download": null
},
{
"device_key": "gmail_web",
"device_name": "Gmail (Web)",
"status": "pending",
"original": null,
"thumbnail": null,
"download": null
}
]
}
Create a preview with email_source: "email" and no other fields. The response is a draft preview containing an inbox_address. Send the email you want to render to that address — the received message becomes the content, and rendering then proceeds like the other sources.
Step 1. Create the draft preview and read the returned inbox_address.
curl -X POST https://api.unspam.email/ext/v2/client-previews \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email_source": "email"
}'
{
"id": "def456",
"email_source": "email",
"status": "draft",
"inbox_address": "abc123@preview.unspam.email",
"previews": [
{
"device_key": "ios_mail",
"device_name": "iOS Mail",
"status": "pending",
"original": null,
"thumbnail": null,
"download": null
}
]
}
Step 2. Send the email you want to render to the returned inbox_address.
# Send your email (from your mail client / ESP) to the inbox_address above.
# The received message becomes the content that gets rendered.
# Wait a few moments for it to be received before continuing.
Step 3. Poll the preview until status moves from draft to completed (see below).
Fetch the preview with its id until status is completed (values: draft, pending, completed, failed; draft applies only to the email source before its message arrives). Each device's original, thumbnail and download are null until that device finishes rendering.
curl https://api.unspam.email/ext/v2/client-previews/def456 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"id": "def456",
"email_source": "raw-data",
"status": "completed",
"inbox_address": null,
"previews": [
{
"device_key": "ios_mail",
"device_name": "iOS Mail",
"status": "completed",
"original": "https://api.unspam.email/storage/client_previews/2026/07/3f/3f9a2c8e1d4b.jpg",
"thumbnail": "https://api.unspam.email/storage/client_previews/2026/07/7b/7b1e5da0c62f.jpg",
"download": "https://api.unspam.email/ext/v2/client-previews/def456/devices/ios_mail/download"
},
{
"device_key": "gmail_web",
"device_name": "Gmail (Web)",
"status": "pending",
"original": null,
"thumbnail": null,
"download": null
}
]
}
Automatic testing lets you configure a test once and have it run on a recurring schedule (or on demand). Each run submits your email through your own SMTP server to the selected mailboxes and reports inbox placement. Configure the test once, then it runs automatically based on its schedule — or trigger an immediate run with Dispatch Now.
from_name, from_email and the smtp host/port/protocol/username/password). The response returns the sender id.id and an inbox_address.inbox_address. This captures the email template that every run will deliver. Wait a few moments for it to be received before continuing. (Alternatively, set the template directly from content with the Set Email endpoint — see the example below.)name, the sender_uuid from step 1, the providers (mailbox IDs from Available Mailboxes), the schedule (start_at, type, and days for specific_days), and the alert_settings.status to active if you want the test to run automatically on its schedule. Keep it disabled if you only intend to trigger runs manually. While active, the next run is generated automatically from the schedule.active and disabled tests can be dispatched manually, as long as they have a schedule and a sender. It returns a run_id with status in_queue.run_id.Register the SMTP credentials used to deliver the test. The response returns the sender id — keep it for the test configuration step.
curl -X POST https://api.unspam.email/ext/v2/scheduled-test-senders \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My Sender",
"service": "smtp",
"settings": {
"from_name": "Admin",
"from_email": "admin@no-reply.com",
"smtp": {
"host": "smtp.example.com",
"port": 465,
"protocol": "SSL",
"username": "user@example.com",
"password": "password"
},
"headers": {}
}
}'
Response:
{
"id": "2ded86a5-b2d9-4f29-921f-1aca66350209",
"name": "My Sender",
"service": "smtp",
"settings": { "...": "..." },
"error_code": null
}
Optionally verify the credentials with the sender's id. No request body is needed — it tests the stored settings.
curl -X POST https://api.unspam.email/ext/v2/scheduled-test-senders/2ded86a5-b2d9-4f29-921f-1aca66350209/test-connection \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
On success it returns { "status": "ok" }; on failure it returns 422 with { "status": "error", "message": "..." }.
Create a draft test, send the email you want to test to the returned address, then configure the schedule and activate it.
Step 1. Create a draft test. The response returns the test id and the inbox_address.
curl -X POST https://api.unspam.email/ext/v2/scheduled-tests \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"id": "9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321",
"status": "draft",
"inbox_address": "test-9b1c7e84@inbox.unspam.email"
}
Step 2. Send the email you want to test to the returned inbox_address.
# Send your email (from your mail client / ESP) to the inbox_address above.
# This captures the template every run will deliver.
# Wait a few moments for it to be received before continuing.
Step 3. Poll the test with a GET request to check whether the email has arrived. While the test is still in draft and email_subject / email_from are null, the email has not been received yet. Once it is received, those fields are populated — you can then configure the schedule and activate the test.
curl https://api.unspam.email/ext/v2/scheduled-tests/9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"id": "9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321",
"status": "draft",
"email_subject": "Welcome to our newsletter",
"email_from": "news@yourdomain.com",
"...": "..."
}
Step 4. Configure the test and set status to active so it runs on schedule. Use the sender id from the previous example as sender_uuid and mailbox IDs from Available Mailboxes as providers.
curl -X PUT https://api.unspam.email/ext/v2/scheduled-tests/9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My automatic test",
"status": "active",
"sender_uuid": "2ded86a5-b2d9-4f29-921f-1aca66350209",
"providers": [3, 7, 23],
"schedule": {
"start_at": "2026-06-18T10:21:00Z",
"type": "week",
"days": []
},
"alert_settings": {
"mode": "all",
"spam_level": null
}
}'
Instead of sending an email to the draft's inbox_address and waiting for it to be received, you can set the email template directly with the Set Email endpoint. This builds the email that every run will deliver from the content you provide. Transport and authentication headers (Received, DKIM, SPF/DMARC) are still applied by your sender's SMTP at send time.
Provide subject and html (and optionally text). from is optional — it defaults to the attached sender's from_email, then the test's existing from address. Optional headers let you add content headers such as List-Unsubscribe or Reply-To to better match production mail (structural headers managed by the builder are ignored).
curl -X PUT https://api.unspam.email/ext/v2/scheduled-tests/9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321/email \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"subject": "Welcome to our newsletter",
"from": "news@yourdomain.com",
"html": "<h1>Hello!</h1><p>Thanks for subscribing.</p>",
"text": "Hello! Thanks for subscribing.",
"headers": {
"Reply-To": "support@yourdomain.com",
"List-Unsubscribe": "<https://yourdomain.com/unsubscribe?id=123>",
"List-Unsubscribe-Post": "List-Unsubscribe=One-Click"
}
}'
On success the test is returned with its content populated and status set to disabled, ready to be configured and activated. After this you do not need to send an email to the inbox address.
The same setup as a scheduled test, but instead of waiting for the schedule you trigger each run manually with Dispatch Now. The test can stay disabled — manual dispatch works regardless of status, as long as the test has a schedule and a sender.
Step 1. Create a draft test (returns id and inbox_address).
curl -X POST https://api.unspam.email/ext/v2/scheduled-tests \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Step 2. Send the email you want to test to the returned inbox_address, and poll the test with a GET request until email_subject / email_from are populated (see the previous example).
Step 3. Configure the test. You can leave status as disabled since you will dispatch runs manually; a schedule and a sender_uuid are still required.
curl -X PUT https://api.unspam.email/ext/v2/scheduled-tests/9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My on-demand test",
"status": "disabled",
"sender_uuid": "2ded86a5-b2d9-4f29-921f-1aca66350209",
"providers": [3, 7, 23],
"schedule": {
"start_at": "2026-06-18T10:21:00Z",
"type": "week",
"days": []
},
"alert_settings": {
"mode": "all",
"spam_level": null
}
}'
Step 4. Trigger a run whenever you need it. The response returns a run_id with status in_queue.
curl -X POST https://api.unspam.email/ext/v2/scheduled-tests/9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321/dispatch-now \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"status": "in_queue",
"run_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
Step 5. Fetch the run result with the run_id once it completes.
curl https://api.unspam.email/ext/v2/scheduled-tests/9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321/runs/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Fetch the paginated history of runs for a test. Without a date range it defaults to the last month; you can filter with from / to (the range must not exceed 6 months) and page with page / per_page. Use a run's id to fetch its detailed result (see the previous example).
curl "https://api.unspam.email/ext/v2/scheduled-tests/9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321/runs?from=2026-05-01&to=2026-05-31&page=1" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"data": [
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "completed",
"inbox_rate": 0.85,
"tabs_rate": 0.1,
"spam_rate": 0.05,
"missing_rate": 0,
"scheduled_at": "2026-05-12T10:21:00Z",
"inbox_placements": []
}
],
"current_page": 1,
"last_page": 1,
"per_page": 10,
"total": 1
}
Fetch the detailed result of a single run using its id (from Dispatch Now or the runs list). It includes the overall rates and the per-mailbox inbox placement.
curl https://api.unspam.email/ext/v2/scheduled-tests/9b1c7e84-2f3a-4d6b-8c11-7a5e0d9f4321/runs/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "completed",
"inbox_placement_url": "https://app.unspam.email/inbox-test/abc123",
"inbox_rate": 0.85,
"tabs_rate": 0.1,
"spam_rate": 0.05,
"missing_rate": 0,
"scheduled_at": "2026-05-12T10:21:00Z",
"inbox_placements": [
{
"service": "<provider>",
"status": "completed",
"placement": "inbox",
"provider_account": {
"id": 3,
"name": "Mailbox 1",
"is_business_account": false
}
}
]
}
DMARC reports show who sends email on behalf of your domain and whether those messages pass DMARC. Register a domain, publish the returned DNS record, verify it, and aggregate reports from mailbox providers start arriving — usually within 24–48 hours.
pending_dns) and dns_instructions — the TXT record to publish on _dmarc.<your domain> whose rua tag points at your unique ingest address.merge_existing mode with the merged value — never replace an existing record blindly.check.rua_present is true (its status becomes active). You can re-read the current DNS record and the value to publish at any time via the DNS Instructions endpoint.Step 1. Create the domain. Keep the returned domain id and publish the record from dns_instructions.
curl -X POST https://api.unspam.email/ext/v2/dmarc/domains \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "yourdomain.com"
}'
{
"domain": {
"id": "3f9a2c8e-1d4b-4a6e-9c11-7a5e0d9f4321",
"domain": "yourdomain.com",
"status": "pending_dns",
"reports_received": false,
"current_policy": null,
"ingest_address": "reports+a1b2c3d4@dmarc.unspam.email",
"verified_at": null,
"first_report_at": null,
"last_report_at": null,
"dns_last_checked_at": null,
"dns_rua_present": false,
"created_at": "2026-05-12T10:21:00Z"
},
"dns_instructions": {
"host": "_dmarc.yourdomain.com",
"type": "TXT",
"value": "v=DMARC1; p=none; rua=mailto:reports+a1b2c3d4@dmarc.unspam.email",
"mode": "new_record",
"existing_record": null,
"ingest_address": "reports+a1b2c3d4@dmarc.unspam.email",
"warnings": [],
"guidance": ["..."]
}
}
Step 2. Publish the TXT record at your DNS provider.
# Create a TXT record on the returned host ("_dmarc.yourdomain.com")
# with the returned value.
# If "mode" is "merge_existing", use the merged value — it keeps your
# existing DMARC policy and adds the Unspam ingest address to "rua".
# DNS changes can take a while to propagate.
Step 3. Verify the domain — this tests whether it is ready to collect reports. It is ready when check.rua_present is true; the domain status then becomes active.
curl -X POST https://api.unspam.email/ext/v2/dmarc/domains/3f9a2c8e-1d4b-4a6e-9c11-7a5e0d9f4321/verify \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"domain": {
"id": "3f9a2c8e-1d4b-4a6e-9c11-7a5e0d9f4321",
"domain": "yourdomain.com",
"status": "active",
"dns_rua_present": true,
"...": "..."
},
"check": {
"record_found": true,
"rua_present": true
}
}
Reports usually start arriving within 24–48 hours of activation. To re-check the DNS record later — for example after changing your policy — call Verify Domain again, or read the current record with GET /dmarc/domains/{id}/dns-instructions.
Step 1. List the domain's aggregate reports, newest first. Filter with an optional from / to window (a report matches when its period overlaps the window) and page with page / per_page.
curl "https://api.unspam.email/ext/v2/dmarc/domains/3f9a2c8e-1d4b-4a6e-9c11-7a5e0d9f4321/reports?from=2026-05-01&to=2026-05-31" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"data": [
{
"id": "7b1e5da0-c62f-4e1a-b3d9-0f2a4c6e8a10",
"external_report_id": "1234567890",
"org_name": "google.com",
"org_email": "noreply-dmarc-support@google.com",
"reporter": { "auth_domain": "google.com", "display_name": "Google" },
"period_start": "2026-05-11T00:00:00Z",
"period_end": "2026-05-11T23:59:59Z",
"message_count_total": 120,
"message_count_pass": 118,
"message_count_fail": 2,
"received_at": "2026-05-12T04:10:00Z"
}
],
"links": { "...": "..." },
"meta": { "current_page": 1, "last_page": 1, "per_page": 10, "total": 1 }
}
Step 2. Fetch a single report with its id.
curl https://api.unspam.email/ext/v2/dmarc/reports/7b1e5da0-c62f-4e1a-b3d9-0f2a4c6e8a10 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"id": "7b1e5da0-c62f-4e1a-b3d9-0f2a4c6e8a10",
"external_report_id": "1234567890",
"org_name": "google.com",
"org_email": "noreply-dmarc-support@google.com",
"reporter": { "auth_domain": "google.com", "display_name": "Google" },
"period_start": "2026-05-11T00:00:00Z",
"period_end": "2026-05-11T23:59:59Z",
"message_count_total": 120,
"message_count_pass": 118,
"message_count_fail": 2,
"received_at": "2026-05-12T04:10:00Z",
"policy_published": { "p": "none", "adkim": "r", "aspf": "r" },
"generator": null,
"errors": null,
"domain": { "id": "3f9a2c8e-1d4b-4a6e-9c11-7a5e0d9f4321", "domain": "yourdomain.com" },
"records_count": 3
}
Step 3. Fetch the report's per-source records — one row per sending source, with the message count, disposition, and aligned DKIM/SPF results.
curl https://api.unspam.email/ext/v2/dmarc/reports/7b1e5da0-c62f-4e1a-b3d9-0f2a4c6e8a10/records \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"data": [
{
"id": "9c11a4e2-7a5e-0d9f-4321-3f9a2c8e1d4b",
"source_ip": "203.0.113.10",
"message_count": 100,
"disposition": "none",
"dmarc_dkim": "pass",
"dmarc_spf": "pass",
"override_reasons": null,
"header_from": "yourdomain.com",
"envelope_from": "yourdomain.com",
"envelope_to": null,
"spf": { "domain": "yourdomain.com", "scope": "mfrom", "result": "pass", "human_result": null },
"dkim_results": [
{ "domain": "yourdomain.com", "selector": "s1", "result": "pass", "human_result": null, "is_aligned": true }
],
"period_start": "2026-05-11T00:00:00Z"
}
],
"links": { "...": "..." },
"meta": { "current_page": 1, "last_page": 1, "per_page": 20, "total": 1 }
}
Only reports from trusted reporting organizations (Google, Microsoft, Yahoo, and other major providers) are included — reports from unvetted reporters are held back until the reporter is vetted.
All public API endpoints are rate-limited to 100 requests per minute per IP address. Authenticated requests are rate-limited per user account instead. Exceeding the limit will result in a 429 Too Many Requests response.