FAQ
Common questions about integrating Primitive into your stack.
Getting started
Do I need to add a domain before I can send or receive?
No. Every account is auto-issued a managed *.primitive.email subdomain at signup. Inbound and outbound work immediately. Add your own domain when you want mail to come from your brand. Both can run side by side.
Can I just use the REST API without webhooks?
Yes. GET /api/v1/emails, /emails/{id}, and /emails/search let you pull mail on your own schedule. Webhooks are an option, not a requirement.
What languages have official SDKs?
Node.js, Python, and Go. They all share the same canonical surface (client.send, primitive.receive, client.reply, client.forward) and a generated typed REST client for advanced cases.
Sending
Who can I send to?
*.primitive.email, your verified domains, anyone who's sent you DMARC-aligned mail, and your org members. See Sending mail for the full rule list and the send_to_any_domain escape hatch.
What's the difference between async and synchronous send?
Async (default) returns immediately with status: "submitted_to_agent". The send completes in the background; poll GET /api/v1/sent-emails/{id} for the terminal status.
Synchronous (wait: true) holds the connection up to wait_timeout_ms (default 5s, max 30s) and returns the actual SMTP response. Use it when you need to know whether a receiver accepted the message before responding to your own caller.
How does idempotency work?
Pass an Idempotency-Key header. Same key + same payload returns the cached response without re-sending. Without a header, Primitive derives a key from a hash of the body. Gate denials are not cached, so you can fix the underlying issue and retry. The effective key is echoed in the response Idempotency-Key header.
What about send rate limits?
1,000 sends per hour and 10,000 per day per org, sliding window. 429 responses include a Retry-After header. Need higher limits? Reach out.
Does Primitive sign outbound mail?
Yes. DKIM with the active key for your From-domain; SPF/DMARC/TLS-RPT alignment via the records on Domains.
Receiving
Do I need to change my SPF/DKIM records to receive mail?
No. SPF and DKIM are for the sender side. To receive mail, you only need an MX record (and a TXT record to verify ownership). If you also want to send from the same domain via Primitive, that's when DKIM/SPF/DMARC come into play.
What if my webhook endpoint is down?
Primitive retries up to 6 times over ~10 hours:
- Immediate
- +60 seconds (inline)
- +5 minutes
- +30 minutes
- +2 hours
- +8 hours
The email is stored across all retries. After all 6 attempts fail, the row goes to failing and you can replay it from the dashboard or via POST /api/v1/emails/{id}/replay. We don't lose mail.
Can I replay a webhook manually?
Yes, from the dashboard logs, or via the API. Replays use the same event id, so if your handler tracks event ids for idempotency (recommended), duplicate replays are safe to ignore.
Should my webhook handler be idempotent?
Yes. Track the id field (evt_ + 64 hex chars, stable across retries) and skip events you've already processed. Always return 2xx for duplicates. An error response triggers a retry.
What if Primitive is down?
Senders get a temporary failure (451 SMTP) and their mail server retries automatically. That's how SMTP works: resilience is built into the protocol. Once we're back, queued mail flows through.
Do you store my emails?
Until delivery succeeds, by default. Opt into auto-discard to wipe body and attachments after your webhook acks. See Receiving mail.
Limits & edge cases
What's the maximum email size?
Inbound: 5MB during beta, expanding to 25MB (the standard SMTP limit). Outbound body: 256KB combined body_text + body_html.
How is spam handled?
We score every inbound email and include the SpamAssassin score in the webhook payload. You decide the threshold for what to accept. Per-domain spam thresholds are available on paid plans. We never silently drop mail.
Do blocked or filtered emails count toward my limits?
No. Only accepted emails that successfully trigger a webhook to your endpoint count.
How long are download URLs valid?
24 hours. Long enough for retries and async processing, short enough that bookmarking them isn't a security problem.
Security
Is signature verification required?
Technically no, practically yes. Without it, anyone who discovers your webhook URL can POST fake events. The signature proves the request actually came from Primitive. The SDKs handle verification automatically; just pass the secret. See Signature verification.
Can I rotate my webhook secret?
Yes, from the dashboard or via POST /api/v1/account/webhook-secret/rotate. The old secret is invalidated immediately, so update your handler before rotating. Limited to once per 60 minutes per org.
Where can my webhook URL point?
HTTPS only, port 443, public IP only. Private ranges ( RFC 1918, loopback, link-local, documentation, etc.) are blocked at egress, and the resolved IP is pinned for the duration of the request.
Self-hosting
Why not just run Postfix myself?
You can. But then you own IP reputation, spam filtering, TLS certs, MIME parsing, retry queues, monitoring, scaling, DKIM rotation, DMARC reporting, abuse handling. SMTP is layered, ancient, and full of footguns. Primitive does the operations work so you don't have to.
That said, PrimitiveMail is the open-source MX server we run internally. One-command install on a Linux VPS. Use it if owning the mail server matters to you.
What about AWS SES inbound?
SES drops emails into S3 as raw .eml files. You still need to parse MIME, extract attachments, build a webhook system, handle retries, do auth verification, etc. Primitive gives you parsed JSON with automatic webhook delivery, retries, and authentication results out of the box.