Solution

You decide what MailKite ever sees.

Your webhook is the system of record — MailKite is the pipe. Pick per domain how much (if anything) gets kept: short auto-expiring retention by default, zero-retention passthrough so no message body is ever stored, or at-rest encryption with a public key you generate, so what we do store we can't read.

Why it fits

What you get

Zero-retention passthrough

Flip it on for a domain and MailKite never stores a message body — attachments arrive inlined as base64 instead of a stored, signed URL.

At-rest encryption, your key

Generate an RSA keypair, paste the public key in, and every message we do retain is encrypted to it — only your private key can ever decrypt it.

Per domain, not all-or-nothing

Set retention mode independently on each domain — a low-sensitivity product can keep default retention while a sensitive one runs zero-retention.

Attachments follow the same rule

On zero-retention or encrypted domains, attachments skip the signed-URL step entirely and arrive inline in the payload — nothing left behind to fetch later.

How it works

Three steps to live

  1. 1

    Pick a mode per domain

    Leave a domain on default short retention, or set it to zero-retention passthrough, from the dashboard or the API.

  2. 2

    Or generate a key for encryption

    Create an RSA keypair locally, keep the private key secret, and paste the public key into the domain's encryption setting.

  3. 3

    Decrypt with your own code

    Every message on an encrypted domain arrives as an envelope; unwrap it with your private key using the documented decrypt routine.

Show me

enable zero-retention

One call per domain — nothing else in your integration changes, except attachments arrive inline instead of as a link.

enable zero-retention
import { MailKite } from "mailkite";

const mk = new MailKite(process.env.MAILKITE_API_KEY);

// No message body is stored for this domain from here on.
await mk.request("PUT", "/api/domains/dom_…/retention", { zeroRetention: true });
Install Docs →
what changes
{
"domain": { "id": "dom_…", "domain": "myapp.ai", "zero_retention": 1 }
}

// Attachments on a zero-retention domain arrive inlined, no signed URL:
// { "filename": "po.pdf", "contentType": "application/pdf", "content": "JVBERi0x…" }
In the box

What's included

Questions

What does MailKite store by default?

Messages are kept for a short, auto-expiring retention window by default so you can list, inspect, and replay them briefly — after that they're gone, unless you set a longer window on a paid plan.

What's the difference between zero-retention and encryption?

Zero-retention means nothing is stored at all — your webhook holds the only copy. Encryption means we still store the message, but as ciphertext keyed to your public key, so we can't read it even though it exists.

Can I set this per domain instead of my whole account?

Yes — retention and encryption are configured per domain, so you can run different policies for different products on the same account.

Keep reading

Ready to build?

Start free on unlimited domains — no credit card. Or browse the other solutions.