How Mailgi keeps mail safe
Where data lives, how credentials are stored, how mail is signed, and what we don't have yet.
Mailgi stores mailbox content in Germany, keeps API keys and session tokens only as one-way hashes, signs every domain's mail with DKIM, SPF and DMARC, and sends webhooks that carry no message content. It has no SOC 2 report yet. Everything below describes the service as it runs today.
Where data lives
The full processor list is on the privacy page. The one exception to EU hosting is the encrypted nightly backup.
| Data | Where | Notes |
|---|---|---|
| Mailbox content | Germany (Hetzner) | Separate from the account database |
| Accounts, organisations, usage | EU, Frankfurt (Supabase) | Postgres |
| Outbound relay | EU, Ireland (AWS SES) | Per-organisation sending reputation |
| Nightly backup | US (AWS S3, us-east-1) | Encrypted on our server before upload, key never sent to AWS |
| Logs and errors | EU (CloudWatch, Sentry) | Application logs and error tracking |
Credentials
API keys are hashed
Stored only as one-way hashes. We can't recover a key, so we can't email you one; lost keys are revoked and replaced. Agents can mint extra keys per task, with expiry, and revoke them individually.
Dashboard sign-in by one-time code
Login codes sent by email expire after ten minutes; session tokens are also stored as hashes.
Registration tokens for custom domains
An agent can only claim an address on your domain with a token a human created in the dashboard. Invalid, revoked and unverified tokens all return the same error, so the response leaks nothing.
DKIM, SPF and DMARC on every domain
Mailgi generates and holds each domain's DKIM key and publishes it under its own selector, aligns SPF with a dedicated MAIL FROM subdomain, and recommends DMARC. A custom domain cannot send until the records verify.
Content-free webhooks
A webhook says that mail arrived, from whom and when, and gives a fetch URL. Subjects and bodies never pass through your endpoint, and reading the message needs the agent's API key.
Signed webhooks
HMAC-SHA256 over the timestamp and raw body, in x-mailgi-signature, with a per-endpoint secret shown once. Reject old timestamps to stop replays.
Contacts kept as keyed hashes
To tell new recipients from known ones we keep per-agent keyed hashes, not addresses, so the table can't be read as a list of who talks to whom.
Abuse controls
Unattended registration only works if sending is hard to abuse.
Layered sending limits
Per API key, per agent, per organisation by domain age, and one shared bucket for the @mailgi.xyz domain. The lowest limit wins. Full numbers on the pricing page.
Automatic suspension
Bounces and complaints are tracked per organisation, and sending is suspended when they cross a threshold.
No bulk features
No lists, imports or campaigns. Every send is one API call naming its own recipients, at most 50 per field.
Paid outbound
Mail to the outside world is paid from a prepaid balance, and whoever pays is accountable for that wallet's mail.
What we don't have yet
No SOC 2 or ISO 27001 report
If your procurement needs one, we're not the right choice today.
No dedicated IPs
Outbound shares relay infrastructure; reputation is isolated per organisation, not per IP.
Deleting an agent
Revokes its keys immediately and burns the address for good. The privacy page describes retention.
Reporting a vulnerability
hello@mailgi.xyz
Subject starting security:. A person reads it. Please give us a reasonable chance to fix an issue before publishing it.
One POST to start.
No signup form, no OAuth, no card to start. Receiving is free.
Open the dashboard →