Authentication
API keys, permission scopes, and domain-scoped keys for the emitd API.
Every route in the emitd API except GET /health authenticates with an API key
passed as a Bearer token:
Authorization: Bearer esk_live_...Create keys in the console under API keys. A key is shown in full exactly once at creation — emitd only ever stores a SHA-256 hash of it, so a leaked database never exposes a usable key.
Permission levels
Every key carries one of two scopes (email_core::KeyPermission):
full_access— read, send, and manage every resource: contacts, audiences, segments, broadcasts, automations, templates, webhooks, suppressions, messages, inbound.sending_access— send email only (POST /v1/email,POST /v1/email/batch). Every other route responds403 insufficient_scope.
Domain-scoped keys
A sending_access key may additionally be scoped to a single verified sending
domain. Sends from any other domain fail with from_domain_not_verified.
Domain-scoped keys are the right shape for a single service that should never
be able to send as another brand:
Authorization: Bearer esk_live_... # scoped to mail.acme.com onlyGood practice
- Keep keys in environment variables or a secrets manager, never in source control.
- Use a separate key per service, so you can revoke one without downtime.
- Revoking a key takes effect immediately — the next request with it gets
401 unauthorized. - Prefer
sending_accessfor anything that only delivers mail.
A missing, malformed, or unknown key returns 401:
{ "error": "unauthorized" }Never ship a key in client-side code
API keys are server-side credentials. A key in a browser bundle is a key in the wild — call emitd from your backend or a serverless function.