Knowledge base
API keys
A key per job, limited to the scopes and senders it needs, with every call logged.
Details
- Created in Settings → API keys, by the owner of the workspace. The secret is shown once, and every key is an oe_live_ one.
- A key holds only the scopes you pick, and a new one starts with emails:send. It can also carry a role, which is a ceiling rather than a second grant: GET /ping returns the scopes the key names and the scopes the role left it, so a 403 for a scope the key plainly holds has a visible cause.
- The send scope names up to 25 whole domains and 50 single addresses. A whole domain also covers addresses added to it later, and a sender outside the list is refused with a 403.
- An optional expiry lets a key lapse on its own, up to ten years out.
- Rotating swaps only the secret: the id, the scopes, the send scope and the request history carry on, and the old secret stops working the moment the new one is created. A key holding keys:write can rotate itself over the API. Revoking is an update rather than a delete, so a later call is told revoked_api_key.
- Every authenticated call is logged with its method, path, status, error code, duration, IP and user agent, never a body or a query string. The key page shows it as Analytics, Activity and Requests, with the busiest routes, how often they fail and their median latency, and the same views cover several keys at once. The log is kept rather than pruned.
- What the owner does on the page is also on the API and the SDK: GET /keys and GET /keys/{id} read keys without their secrets, POST /keys mints one, PATCH /keys/{id} renames it, changes its scopes or send scope and switches it off and on, and rotate, revoke and delete do what they say. The request log and the activity read the same way, for one key or all of them, with the page’s filters. Reading needs keys:read and every change needs keys:manage, two scopes no key holds unless somebody gave it one, and a connected app is never given keys:manage. The MCP server lists keys and reads the log and the activity too, as listApiKeys, listApiKeyRequests and listApiKeyActivity.
- A key never makes or reaches a key wider than itself: its scopes, role, expiry, mode and send scope all have to sit inside the key making the call. Step-up verification cannot apply to a call made with a key, so keys:manage is a credential that makes credentials. Give it only to automation that provisions keys, with a role, a send scope and an expiry of its own, and watch the Activity tab, where everything it does is recorded against it.
- Members can see the keys as well when their role reaches every address and holds api-keys:read, and with api-keys:write they can rename, switch off, revoke and delete any key no wider than their role. Creating, rotating, switching a key back on and changing what it may do stay with the owner. No built-in role reaches every address until somebody ticks it, so out of the box only the owner sees the keys.
- A key can read its own request log, activity and figures with no scope at all, at GET /keys/self/requests, /keys/self/activity and /keys/self/stats, so a key that can only send can still watch itself. Its send figures are left out unless it holds emails:read. The request log also filters by exact status code and by route, on the API, in every SDK, on the command line and on the MCP server.
- A key that holds emails:send is also an SMTP password. Software that sends through an SMTP server signs in to smtp.openemail.uk on port 465 or 587 with the username nextmail and the key as the password, and each message it hands over is the same send as POST /emails made with that key, with the same scopes, send scope, quota and suppression list, and a line in the request log of the key.
Google Workspace