Email API Key Management: Key per App, Rotation, Revoking Leaks
Manage email API keys properly: one key per app and environment, storing keys in env vars or a secrets manager, zero-downtime rotation, and revoking leaks fast.
An email API key is a password that can send mail as your domain. Leaked, it lets someone send phishing under your name until you notice, and the reputation damage lands on your domain, not theirs. Managing keys well is not complicated: know which key belongs to what, keep them out of code, rotate on a schedule, and have a revoke-first plan for leaks. Here is that plan.
Quick answer
Create a separate key for every combination of application and environment, name each key for its purpose, store keys only in environment variables or a secrets manager, never in git, rotate them on a schedule by creating the new key before revoking the old one, and when a key leaks revoke it first and investigate second.
One key per app and environment
- web-app production, web-app staging, worker production, monitoring, github-actions: each gets its own key.
- Name keys exactly that way in the dashboard so the list reads like an inventory.
- Revoking one key then affects one thing. A shared key means revoking it to stop a leak also stops production.
- Sends made with each key can be traced back to the app that made them, which is how you find the leak.
- Give contractors and integrations their own keys and revoke them when the engagement ends.
Creating a key in OquMail
- Open the API page in your workspace and go to the Configurations and keys tab.
- Create a key for the mailbox that will send (the from address belongs to that mailbox's domain). Name it for the app and environment.
- Copy the oqm_live_ value immediately. It is shown once; after that only a masked version is visible.
- Put it in the destination secret store (below) and confirm the app sends with a test message that appears in the delivery log.
- Repeat for each environment. Do not reuse.
Where to store keys
Environment variables are the baseline: OQUMAIL_API_KEY read at startup, set by your process manager, container runtime or platform (Heroku config vars, Fly secrets, Vercel environment variables, systemd EnvironmentFile with 600 permissions). A secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, Doppler, 1Password) adds audit logs and rotation hooks and is worth it once more than a couple of people deploy. In CI use the platform's encrypted secrets (GitHub Actions secrets, GitLab CI variables marked masked and protected). What never works: a .env file committed to git, a key pasted into a Slack channel, a key in client-side JavaScript or a mobile app binary, a key in a Dockerfile layer.
Using the key without leaking it
// Read once at startup; fail fast if missing.
const KEY = process.env.OQUMAIL_API_KEY;
if (!KEY || !KEY.startsWith("oqm_live_")) throw new Error("OQUMAIL_API_KEY is not set");
export async function send({ from, to, subject, html, text }) {
const res = await fetch("https://api.oqumail.com/api/v1/emails", {
method: "POST",
headers: { "Authorization": "Bearer " + KEY, "Content-Type": "application/json" },
body: JSON.stringify({ from, to, subject, html, text })
});
if (res.status === 401) throw new Error("API key rejected: revoked or wrong environment");
if (!res.ok) throw new Error("send failed: " + res.status);
return res.json();
}
// Never log the headers object, and redact Authorization in any HTTP client debug output.Rotation without downtime
- Create the new key with the same name plus a date suffix.
- Deploy the new key to the app's secret store and restart or roll the app so it picks it up.
- Confirm sends appear in the delivery log from the new key for a few minutes.
- Revoke the old key. Any 401 that appears now points at a forgotten consumer still using it, which is useful to know.
- Do this every 90 days or so for production keys, and immediately when someone with access leaves.
When a key leaks
A key is leaked when it is committed to a public repository, pasted into a ticket, printed in a log that others can read, or embedded in a client app. Do not investigate first. Revoke the key in the dashboard; OquMail stops accepting it immediately and emails your login address to confirm. Then create a replacement and deploy it. Then check the delivery log for sends you do not recognise during the exposure window, and if there were any, check who received them and whether your domain's reputation took a hit. Finally, remove the key from wherever it leaked; note that a key in a public git history stays public even after a force push, which is why revocation, not deletion, is the fix. Add a pre-commit secret scanner (gitleaks, or GitHub's push protection) so it does not happen again.
Common questions
Can I see which key sent a message?
Keys are created from a mailbox, and messages appear in the delivery log under the sending address, so keeping one key per mailbox-and-app makes attribution straightforward. Naming keys carefully does the rest.
Should local development use a real key?
Yes, a dedicated development key with a test from address and a recipient guard, so that revoking it costs nothing. Alternatively use a local fake SMTP server and no key at all.
Is a key in a mobile app really a problem?
Yes. Anything shipped to a user's device can be extracted. Mobile and browser apps should call your backend, which holds the key and sends on their behalf.
Free business email on your own domain
OquMail gives you up to 15 mailboxes on your domain — free — with guided SPF/DKIM/DMARC, webmail, IMAP/SMTP for any mail app, and a send API. Most teams are live in under fifteen minutes. Start at oqumail.com.
Get started free