Developer Platform
Docs chevron_right Developer Platform chevron_right Auth & API keys

Auth & API keys

Authenticate with scoped, named API keys — create as many as your plan allows, grant each one only the permissions it needs, and revoke any one of them without disturbing the others. The original account-wide token keeps working for existing integrations.

Scoped API keys

An API key is a credential of the form efa_ followed by 40 random characters. Create keys under Account → API: give each one a name (so you can tell integrations apart), pick its scopes, and optionally set an expiry date. The plaintext key is shown exactly once, at creation — only a hash is stored, so copy it immediately and keep it in your secrets manager. The number of active keys is a plan quota.

emailflow.ai/rui/account/api
The Account API page showing the API keys table: each key with its name, scopes, masked prefix, last-used time, expiry, and a revoke action, plus a New API key button
Account → API — named keys with scopes, last-used tracking, and one-click revocation.

Pass the key on every request in one of two headers — Authorization: Bearer is preferred:

# Preferred: bearer header
curl https://emailflow.ai/api/v1/me \
  -H "Authorization: Bearer efa_YOUR_KEY"

# Alternative: X-API-Key header
curl https://emailflow.ai/api/v1/me \
  -H "X-API-Key: efa_YOUR_KEY"

A revoked or expired key returns 401 with an INVALID_API_KEY error envelope. Each key records last_used_at (updated at most once a minute) so you can spot abandoned integrations before revoking them.

emailflow.ai/rui/account/api
The create API key modal with a name field, a checkbox grid of permission scopes such as contacts, emails, automations and webhooks, and an optional expiry date picker
Creating a key — name it, grant only the scopes the integration needs, optionally set an expiry.

Scopes

Scopes follow the principle of least privilege: grant only what an integration needs. Broad scopes include their narrower scopes — the “Includes” column below — while granular scopes grant only themselves. A key that lacks the required scope receives 403 INSUFFICIENT_PERMISSIONS, and the envelope names the missing scope so the fix is obvious.

ScopeGrantsIncludes
all Everything, including admin endpoints every scope
contacts Lists and subscribers; includes Audiences audiences
audiences Read audience segments ,
emails Email content; includes Domains, Sends and Templates domains, sends, templates
domains Sending domains ,
sends Campaigns and sending ,
templates Email templates ,
automations Automation workflows; includes Triggers triggers
triggers Trigger automation runs ,
webhooks Webhook subscriptions ,
analytics Event analytics feed ,
usage Usage and quota meters ,
brand Brand profile ,
key
API access is included with your subscription. Use a separate key per integration so you can revoke one without disrupting the others, and prefer granular scopes over all.

The legacy account token

Before scoped keys, every account had a single token (visible under Account → API → Legacy token) with full access. It continues to work exactly as before — including the ?api_token= query parameter — and keeps its original response shapes, so nothing you built against it breaks. New integrations should use scoped efa_ keys instead: they are individually revocable, permission-scoped, and receive the canonical error envelope.

# Legacy token - header or query parameter
curl https://emailflow.ai/api/v1/me \
  -H "Authorization: Bearer YOUR_LEGACY_TOKEN"

curl "https://emailflow.ai/api/v1/me?api_token=YOUR_LEGACY_TOKEN"

If you only have an email and password (for example from a programmatic client), exchange them for the legacy token with POST /user/login:

# Get the legacy token from email + password
curl -X POST https://emailflow.ai/api/v1/user/login \
  -d email=you@example.com \
  -d password=YOUR_PASSWORD

# Response
{ "api_token": "9f2c1ab4e5..." }

Identity endpoints

Endpoints for verifying a credential and reading the current account. GET /me is the canonical “is this key valid?” probe.

MethodEndpointDescription
POST/user/loginExchange email and password for the legacy API token. Public — no credential required.
GET/meReturn the authenticated user record. Use it to verify a key or token.
GET/user/infoReturn the user profile: email, first and last name, and profile image URL.
GET/dashboardReturn account summary counts: campaigns, lists, and subscriber usage against quota.
POST/login-tokenGenerate a one-time URL that logs the user in when visited.

Keeping credentials safe

Treat API keys like passwords: store them as secrets, never commit them to code or ship them in client-side bundles, use a separate key per integration, and revoke any key that is ever exposed from Account → API. Prefer the Authorization header over the legacy query parameter — query strings can end up in proxy and server logs. Setting an expiry on keys for short-lived projects means forgotten credentials shut themselves off.