dev.primitive/email
REMOTE · WWW.PRIMITIVE.DEV · SCANNED AUG 3
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Available components
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score →
Endpoint Security97
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. View diagnostics → Pass
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- The HSTS (Strict-Transport-Security) header is present. View diagnostics → Pass
- DNSSEC is configured correctly; the domain's records validate against the full chain to the root. View diagnostics → Pass
- The authorisation server offers only Dynamic Client Registration (RFC 7591), which MCP 2026-07-28 deprecated in favour of Client ID Metadata Documents. View diagnostics → Partial
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability84
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (good).Pass
- Tool/resource definitions use about 2978 tokens (~99/item across 30 items; 29 tools + 1 resources), lean.Pass
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management27
- Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage97
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 91% of tool parameters carry a description.Partial
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
- Supports UI / widget rendering.Pass
Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.
remote · www.primitive.dev
claude mcp add --transport http dev-primitive-email https://www.primitive.dev/mcp
[mcp_servers.dev-primitive-email] url = "https://www.primitive.dev/mcp"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"dev-primitive-email": {
"type": "remote",
"url": "https://www.primitive.dev/mcp",
"enabled": true
}
}
} openclaw mcp add dev-primitive-email --url https://www.primitive.dev/mcp --transport streamable-http
mcp_servers:
dev-primitive-email:
url: "https://www.primitive.dev/mcp" {
"mcpServers": {
"dev-primitive-email": {
"type": "http",
"url": "https://www.primitive.dev/mcp"
}
}
} The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 2 Aug 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.
- 1 Aug 26 +5
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 31 Jul 26 0
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 29 Jul 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.
- 28 Jul 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.
- 27 Jul 26 0
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 26 Jul 26 76
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 3 Aug 2026 · Probed https://www.primitive.dev/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=primitive.dev | CN=YE2,O=Let's Encrypt,C=US | 1 Aug 2026 | 30 Oct 2026 | ECDSA 256 | ECDSA-SHA384 | 6fbed9ebd59789d8bd951e2445d19856f00 |
| SANs: *.primitive.dev, primitive.dev | ||||||
| CN=YE2,O=Let's Encrypt,C=US (CA) | CN=Root YE,O=ISRG,C=US | 3 Sept 2025 | 2 Sept 2028 | ECDSA 384 | ECDSA-SHA384 | 4df3b15dd6c0784c507cd37b58e6f115 |
| CN=Root YE,O=ISRG,C=US (CA) | CN=ISRG Root X2,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | ECDSA 384 | ECDSA-SHA384 | 872165fc34b6e5fba8add5b3705fb53a |
| CN=ISRG Root X2,O=Internet Security Research Group,C=US (CA) | CN=ISRG Root X1,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | ECDSA 384 | SHA256-RSA | 6c8f1dc727c7117f7baf853ac980f9cd |
DNSSEC secure
Validation of www.primitive.dev. — Secure
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| dev. | present | 60074 | 8 | Verified |
| primitive.dev. | present | 2371 | 13 | Verified |
| www.primitive.dev. | Verified address RRset verified with the apex keys |
Authentication Enforced and verified
The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.
| Result | Enforced and verified |
|---|---|
| Enforced | On tool calls |
| HTTP status | 200 |
WWW-Authenticate challenge Bearer realm="Primitive MCP", resource_metadata="https://www.primitive.dev/.well-known/oauth-protected-resource/mcp", error="invalid_token", error_description="Bearer token required for /mcp"
Bearer realm="Primitive MCP", resource_metadata="https://www.primitive.dev/.well-known/oauth-protected-resource/mcp", error="invalid_token", error_description="Bearer token required for /mcp" | Header | Value |
|---|---|
| strict-transport-security | max-age=63072000; includeSubDomains |
| content-security-policy | base-uri 'self'; form-action 'self'; frame-ancestors 'none'; object-src 'none' |
| x-content-type-options | nosniff |
| x-frame-options | DENY |
| referrer-policy | strict-origin-when-cross-origin |
| permissions-policy | accelerometer=(), bluetooth=(), browsing-topics=(), camera=(), geolocation=(), gyroscope=(), hid=(), magnetometer=(), microphone=(), payment=(), serial=(), usb=() |
Protected resource metadata
| Document | https://www.primitive.dev/.well-known/oauth-protected-resource/mcp |
|---|---|
| Retrieved | Yes |
| Resource | https://www.primitive.dev/mcp |
| Authorisation server | https://www.primitive.dev |
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://www.primitive.dev/mcp | Verified | 200 | |
| http (plaintext) | http://www.primitive.dev/mcp | HTTPS enforced | 301 | https://www.primitive.dev/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.
addDomain Add domain ~72
Claim a new domain and receive the DNS records to publish. Returns dns_records with the exact records to add. If the domain has an mx_conflict (existing mail provider), re-call with confirmed: true to proceed. After publishing DNS records, call verifyDomain to complete setup.
| Name | Type | Req | Description |
|---|---|---|---|
| requestBody | object | yes | — |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
awaitReply Await reply ~183
Get the threaded reply to a sent email — the canonical 'did they reply yet?' call. Pass the sent email's id (from a sendEmail response). With wait=true it long-polls up to wait_timeout_ms for the reply to arrive (synchronous agent-to-agent chat); with wait=false (default) it returns immediately with the reply if one has arrived, else reply=null. Matches on the reply's threading, not a from/subject guess.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | The sent email id to fetch the reply for (from a sendEmail/replyToEmail response). |
| wait | string | — | When "true", long-poll until a reply arrives or wait_timeout_ms elapses. Default no-wait. |
| wait_timeout_ms | number | — | How long to wait when wait=true (1000–30000 ms, default 10000). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
cancelScheduledSend Cancel scheduled send ~93
Cancel a still-scheduled send before it dispatches (terminal status "canceled"; the same idempotency key becomes reusable). Pass the sent email id from a sendEmail response that used scheduled_at, or from listSentEmails. Returns a conflict error once the send has already started dispatching.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Sent email ID of the scheduled send, from a sendEmail response or listSentEmails. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
createEndpoint Create webhook endpoint ~61
Create a webhook endpoint to receive email.received events. If an endpoint with the same URL already exists but is deactivated, it is reactivated. After creating, call testEndpoint to confirm your signature verifier accepts the payload.
| Name | Type | Req | Description |
|---|---|---|---|
| requestBody | object | yes | — |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
createFilter Create filter ~38
Create a whitelist or blocklist filter rule. Patterns are stored lowercase. Per-domain filters require a Pro plan.
| Name | Type | Req | Description |
|---|---|---|---|
| requestBody | object | yes | — |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
deleteEndpoint Delete webhook endpoint ~37
Soft-delete a webhook endpoint. The endpoint will no longer receive deliveries.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Endpoint ID from listEndpoints or createEndpoint. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
deleteFilter Delete filter ~29
Delete a filter rule.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Filter rule ID from listFilters or createFilter. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
downloadDomainZoneFile Download DNS zone file ~104
Download a BIND-format DNS zone file for a domain. Useful when users want to import all required DNS records at once rather than copying them individually. Returns plain text in BIND zone file format.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Domain ID from listDomains or addDomain. |
| outbound_only | boolean | — | When true, include only outbound DNS records (SPF, DKIM, DMARC). Defaults to all records for unverified domains, outbound-only for verified. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
downloadEmailAttachments Download email attachments ~94
Download all attachments for an inbound email as a gzip-compressed tar archive. Returns the archive as a base64-encoded string along with the attachment count and SHA-256 digest. Prefer getEmail first to check the attachment manifest before downloading.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Inbound email ID. |
| token | string | — | Signed download token from a webhook payload. Optional — the bearer token is used when this is omitted. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
getAccount Get account ~33
Use this when you need the authenticated Primitive account summary, including email, plan, onboarding state, and webhook secret rotation time.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
getConversation Get conversation ~103
Get the full conversation an inbound email belongs to as ordered, chat-model-ready turns with bodies. Each message is oldest-first with a direction (inbound/outbound) and a derived role (inbound→user, outbound→assistant). For a brand-new message, returns just that one turn. The response includes a truncated boolean (true when the message cap was reached) and a message_count field.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | ID of any inbound email in the conversation. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
getEmail Get email ~54
Use this when you need full details for one inbound email ID, including parsed bodies, threading metadata, SMTP envelope, webhook state, and replies.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Inbound email ID from listEmails or searchEmails. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
getInboxStatus Get inbox status ~37
Use this when the user asks whether inbound email is ready or needs setup. Returns domains, routes, deployed Functions, and recent inbound activity.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
getOutboundStatus Get outbound status ~76
What can I send FROM? Lists this account's verified outbound (sendable) domains plus any domains still pending DNS verification, with next actions. Call this BEFORE sendEmail to pick a valid `from` domain — the account email is not necessarily sendable. The same sendable list is echoed in a cannot_send_from_domain error.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
getSentEmail Get sent email ~81
Get the full record for a single sent email by id, including body_text and body_html. Use to inspect delivery details for a specific send — e.g. the SMTP response on a bounced row, or the gate denial reason on a gate_denied row.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Sent email ID from listSentEmails or a /send-mail response. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
getThread Get thread ~100
Get a conversation thread by id: metadata plus all inbound and outbound messages interleaved oldest-first. Each message has a direction (inbound/outbound) and id; fetch inbound message bodies via getEmail, or outbound bodies via getSentEmail. Discover thread_id from any email or sent-email record. Compare message_count against messages.length to detect truncation.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Thread ID from the thread_id field on any email or sent-email. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
listDomains List domains ~45
List all inbound domains for the organization, both verified and unverified. Each domain includes its verification status and DNS records. Use before addDomain to check whether a domain is already claimed.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
listEmails List inbound emails ~300
Use this when you need to browse inbound emails received at verified domains with cursor pagination, status filters, date filters, or sender/recipient search.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | — | Backward (history) pagination cursor from a previous response's `meta.cursor` field: returns emails OLDER than this position, newest-first. Mutually exclusive with `since`. |
| date_from | string | — | Inclusive lower bound on created_at (ISO 8601). |
| date_to | string | — | Inclusive upper bound on created_at (ISO 8601). |
| domain_id | string | — | Filter to emails received on a specific verified domain. |
| limit | number | — | Maximum number of emails to return (1–100, default 50). |
| search | string | — | Free-text search across sender, recipient, and subject. |
| since | string | — | Forward-tail cursor (a `meta.cursor` value, format `{ISO datetime}|{UUID}`): returns emails strictly NEWER than this position, oldest-first, for lossless polling of just-arrived mail. Mutually exclus… |
| status | string | — | Filter to emails in this processing status. |
| wait | number | — | Long-poll up to this many seconds (0–30, default 0) holding the request for new mail instead of returning an empty page immediately. Requires `since`. Returns as soon as matching mail arrives, or an… |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
listEndpoints List webhook endpoints ~31
List all active webhook endpoints for the organization. Each endpoint shows its URL, enabled state, and optional domain restriction.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
listFilters List filters ~20
List all whitelist and blocklist filter rules for the organization.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
listSentEmails List sent emails ~229
List outbound emails sent by this org, with cursor pagination and filters. Bodies are omitted from list rows to keep responses small — use getSentEmail to fetch a specific row with full body. Useful for auditing delivery status, finding bounced sends, or checking gate-denied attempts.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | — | Pagination cursor from a previous response's `meta.cursor` field. |
| date_from | string | — | Inclusive lower bound on created_at (ISO 8601). |
| date_to | string | — | Inclusive upper bound on created_at (ISO 8601). |
| idempotency_key | string | — | Filter to rows with the given client idempotency key. |
| limit | number | — | Maximum number of sent emails to return (1–100, default 50). |
| request_id | string | — | Filter to the row matching a specific server-issued request_id from a /send-mail response. |
| status | string | — | Filter to rows in this status. Use "scheduled" to find pending scheduled sends (cancelable via cancelScheduledSend) and "canceled" for ones already canceled. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
listWebhookDeliveries List webhook deliveries ~155
List webhook delivery attempts with pagination and filters. Each delivery includes the target endpoint and a nested email object with sender/recipient/subject. Useful for diagnosing delivery failures or confirming a specific email was delivered.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | — | Pagination cursor from a previous response's `meta.cursor` field. |
| date_from | string | — | Inclusive lower bound on attempted_at (ISO 8601). |
| date_to | string | — | Inclusive upper bound on attempted_at (ISO 8601). |
| email_id | string | — | Filter by inbound email ID. |
| limit | number | — | Maximum number of delivery records to return (1–100, default 50). |
| status | string | — | Filter to deliveries in this status. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
replayWebhookDelivery Replay webhook delivery ~60
Re-send a stored webhook payload from a previous delivery attempt to its original endpoint. Rate limited per org (burst + sustained windows, shared budget with email webhook replays).
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Delivery ID (numeric string from listWebhookDeliveries). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
replyToEmail Reply to email ~65
Use this when the user has selected a specific inbound email and confirmed a reply. Sends real outbound email with threading handled server-side.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Inbound email ID to reply to. Threading headers are set server-side. |
| requestBody | object | yes | — |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
searchEmails Search inbound emails ~383
Use this when you need to find inbound emails with structured filters or full-text matching. Use sort=received_at_asc plus date_from for new-mail polling.
| Name | Type | Req | Description |
|---|---|---|---|
| body | string | — | Filter to emails whose body contains this string. |
| cursor | string | — | Pagination cursor from a previous response's `meta.cursor` field. |
| date_from | string | — | Inclusive lower bound on received_at (ISO 8601). |
| date_to | string | — | Inclusive upper bound on received_at (ISO 8601). |
| domain_id | string | — | Filter to emails received on a specific verified domain. |
| from | string | — | Filter to emails from this sender address or domain. |
| has_attachment | string | — | Filter to emails that have ("true") or lack ("false") attachments. |
| include_facets | string | — | Include aggregated facet counts (sender, domain, status) in the response (default true). |
| limit | number | — | Maximum number of emails to return (1–100, default 50). |
| q | string | — | Full-text query matched across subject, body, sender, and recipient. |
| reply_to_sent_email_id | string | — | Filter to inbound emails that are replies to a specific sent email ID. |
| snippet | string | — | Include a short body snippet in each result (default true). |
| sort | string | — | Sort order. Use received_at_asc with date_from for polling new mail. |
| spam_score_gte | number | — | Filter to emails with a spam score at or above this value. |
| spam_score_lt | number | — | Filter to emails with a spam score strictly below this value. |
| status | string | — | Filter to emails in this processing status. |
| subject | string | — | Filter to emails whose subject contains this string. |
| to | string | — | Filter to emails addressed to this recipient. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
sendEmail Send email ~90
Use this when the user has confirmed a new outbound email. Sends real email through Primitive's relay and can wait for the first SMTP delivery outcome, or schedule the send for a future time with scheduled_at.
| Name | Type | Req | Description |
|---|---|---|---|
| Idempotency-Key | string | — | Client-supplied idempotency key. Retrying with the same key returns the original result without re-sending. |
| requestBody | object | yes | — |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
sendEmailDemo Try a send (no signup) ~136
Send a SIMULATED email with no account required. Validates the body against the exact same schema as sendEmail (including cc/bcc, reply_to, tags, attachments, and scheduled_at), then returns a realistic synthetic success envelope (demo: true); it never actually sends, queues, or stores anything. Demo requests are capped at 16KB total body, so large attachments are rejected even though the schema allows them. Use this to let someone try Primitive and see the response shape before they sign up. To send for real, sign up for an API key and use sendEmail.
| Name | Type | Req | Description |
|---|---|---|---|
| requestBody | object | yes | — |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
testEndpoint Test webhook endpoint ~60
Send a sample email.received event to a webhook endpoint to verify your signature verifier. Rate limited to 4/min and 30/hr. Successful deliveries and verified-domain endpoints are exempt.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Endpoint ID from listEndpoints or createEndpoint. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.
verifyDomain Verify domain ~81
Check DNS records for a domain claim (MX, TXT, SPF, DKIM, DMARC). On success the domain becomes verified and starts receiving mail. On failure, returns which checks passed and which still need attention. If DNS propagation is incomplete, wait a few minutes and retry.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Domain ID returned by addDomain or listDomains. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | — | yes | — |
| status | number | yes | — |
| statusText | string | — | — |
| tool | string | yes | — |
No examples provided.