Authentication

Authenticate every request with a per-project API key.

The API authenticates with a per-project API key. Each key belongs to one project (one company) and can only act on that project's data.

The Bearer header

Send your key in the Authorization header on every request. There's no SDK yet — call the API directly with fetch, requests, or curl.

curl https://sendandretain.com/api/v1/emails \
  -H "Authorization: Bearer $AEM_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "to": "[email protected]", "template": "welcome" }'
const res = await fetch("https://sendandretain.com/api/v1/emails", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AEM_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ to: "[email protected]", template: "welcome" }),
});
import os, requests

requests.post(
    "https://sendandretain.com/api/v1/emails",
    headers={"Authorization": f"Bearer {os.environ['AEM_KEY']}"},
    json={"to": "[email protected]", "template": "welcome"},
)

A missing or invalid key returns 401 with code unauthorized.

Creating keys

Create keys in the dashboard under Settings → API keys. Keys are shown once at creation and stored only as a hash — copy the key immediately and keep it secret. Revoke a key at any time; revoked keys stop working instantly.

Keys are prefixed aem_.

Never expose an aem_ key in client-side code or commit it to source control. Keys send real email on your behalf. Load them from an environment variable.

Scopes

Scopes are ranked, not orthogonal: a key satisfies any requirement at or below its own tier, so an admin key can do everything a send key can.

Prop

Type

Requests that need a capability the key doesn't have return 401, and the message names the tier required and the tier your key has.

Give each application the lowest tier that works. A send key that leaks can send mail; an admin key that leaks can repoint your sending domains.

What API keys can never do

Two things are deliberately out of reach of every key, at every scope:

  • Setting provider credentials. Your Resend or SendGrid API key only ever enters through the dashboard. GET /api/v1/connection returns the settings URL for a human to visit — there is no endpoint that accepts a provider secret, so a leaked aem_ key can't redirect your mail through someone else's provider account.
  • Creating projects or minting keys. An aem_ key is bound to exactly one project, so there is no principal it could act as to create another one or issue new credentials. Both stay in the dashboard.

On this page