Reference
Authentication
Authenticate API requests with a Bearer API key or OAuth access token, choose full or sending scope, restrict keys to a domain and handle auth errors.
Every request to the Emailit API must carry a credential in the Authorization header. This page covers the two kinds of credentials (API keys and OAuth access tokens), what each scope can do, and every authentication error you can get back.
API keys
An API key belongs to one workspace, and every request made with it acts on that workspace. Keys look like this:
secret_Xq7pL2mN9vB4kR8tW1yZ6cH3jF5dS0aGThat’s secret_ followed by 32 letters and digits. Keys created before the secret_ format have no prefix, and they keep working.
Create keys in the dashboard under Email APIAPI Keys, or with Create an API key. The secret is shown only once, when you create or regenerate the key, so store it right away. See API keys for managing them.
The same keys work as the SMTP password for the SMTP relay.
Send the key with each request
Use the Bearer scheme in the Authorization header. The API doesn’t accept keys in the query string or request body.
curl https://api.emailit.com/v2/domains \
-H "Authorization: Bearer $EMAILIT_API_KEY"const response = await fetch('https://api.emailit.com/v2/domains', {
headers: { Authorization: `Bearer ${process.env.EMAILIT_API_KEY}` },
});
const domains = await response.json();import os
import requests
response = requests.get(
"https://api.emailit.com/v2/domains",
headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
)
domains = response.json()The SDKs set this header for you when you pass the key to the client.
Scopes
Each key has one of two scopes. You choose it when you create the key, and you can’t change it later.
| Scope | Can call | Use it for |
|---|---|---|
full |
Every endpoint in the API. This is the default. | Back-office tools, scripts and integrations that manage domains, contacts, templates or webhooks. |
sending |
Only the send endpoints listed below. | Application servers that only send email. |
A sending key can call these endpoints and nothing else:
| Endpoint | Description |
|---|---|
POST /emails |
Send an email |
POST /emails/{id} |
Update a scheduled email |
POST /emails/{id}/cancel |
Cancel an email |
POST /emails/{id}/retry |
Retry an email |
POST /emails/{id}/forward |
Forward an email |
Reading emails (list, retrieve, raw, body, metadata, attachments and status) needs a full key. When a sending key calls any other endpoint, the API returns 403 with Permission denied: full (or Permission denied: read for the email read endpoints).
All endpoints lists the scope of every endpoint.
Restrict a key to one domain
A sending key can also be locked to one sending domain. Pass the domain’s ID as sending_domain_id when you create the key. A restricted key can only send from addresses on that domain. Any other from domain returns 403:
{
"error": "Domain not authorized",
"message": "API key is not authorized to send from this domain"
}Domain restrictions apply to sending keys only. A full key always has access to every domain in the workspace.
OAuth access tokens
Apps that act on behalf of an Emailit user, such as MCP clients and third-party integrations, don’t ask for an API key. They use OAuth 2.1 instead: the user signs in to Emailit, chooses the workspaces the app can use (all of them or only selected ones) and approves the sending or full scope, and the app receives an access token. The user can change or revoke that access under Connected apps.
Send access tokens in the same header as API keys:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…An access token is valid for 15 minutes and acts on the grant’s default workspace, with the granted scope and the user’s role in that workspace. Apps refresh it with the refresh token. See OAuth apps to build one.
Authentication errors
Authentication runs before anything else, so these errors can come back from any endpoint.
| Status | message or error |
Cause | Fix |
|---|---|---|---|
401 |
API key required |
The Authorization header is missing or doesn’t start with Bearer . |
Send Authorization: Bearer <key>. |
401 |
Valid API key required |
The header has the Bearer prefix but no token. |
Check that the variable holding your key isn’t empty. |
401 |
Invalid API key |
The key doesn’t exist, was deleted, or was regenerated (the old secret stops working), or an OAuth token expired. | Use a current key, or refresh the OAuth token. |
403 |
Workspace is suspended |
The workspace is suspended. | Contact support. |
403 |
Permission denied: full |
A sending key called an endpoint that needs full. |
Use a full key. |
403 |
Domain not authorized |
A domain-restricted key sent from another domain. | Send from the key’s domain or use another key. |
403 |
unverified_workspace_recipient |
The workspace isn’t verified yet and a recipient isn’t a workspace member. | See Unverified workspaces. |
503 |
Authentication service unavailable |
A temporary problem on our side. | Retry with backoff. |
{
"statusCode": 401,
"error": "Unauthorized",
"message": "Invalid API key"
}{
"statusCode": 403,
"error": "Forbidden",
"message": "Permission denied: full"
}{
"statusCode": 403,
"error": "Forbidden",
"message": "Workspace is suspended"
}{
"code": "unverified_workspace_recipient",
"error": "Workspace not verified",
"message": "Unverified workspaces can only send to workspace members' account emails. Blocked recipient: ada@example.com.",
"blocked_recipients": ["ada@example.com"]
}Unverified workspaces
New workspaces start unverified. Until Emailit approves production access, the API only sends to the account email addresses of the workspace’s members. Sending, retrying or forwarding to anyone else returns 403 with the code unverified_workspace_recipient and the list of blocked_recipients, and campaigns can’t be sent at all. Your API keys work normally for everything else.
Keep your keys secret
An API key gives access to your workspace, so treat it like a password.
- Call the API from your server only. Never put a key in browser JavaScript, a mobile app or any other code that runs on someone else’s device.
- Keep keys out of source control. Load them from environment variables or a secret manager.
- Create one key per application and environment, and name it after where it’s used, so you can revoke one without breaking the others.
- Give each key the least access it needs: a
sendingkey, restricted to one domain, is enough for most applications. - Check
last_used_atin List API keys and delete keys you no longer use. - If a key leaks, regenerate it or delete it right away. The old secret stops working immediately.