Authentication and API keys
Every API request carries a bearer key:
Authorization: Bearer cfx_<prefix>_<secret>
The clear-text secret is returned once, on creation or rotation. Store it in a secret manager and never put it in a URL or query string.
Scopes
| Scope | Allows |
|---|---|
send |
Submit mail; compose, reply, forward, draft, file, label and mark-read inside inboxes |
read |
Read messages, deliveries, events, inboxes, threads, usage and dashboards |
feedback |
Add suppressions and report complaints |
suspend |
Pause and resume delivery (tenants, domains, senders, keys, tags…) |
admin |
Everything, including creating tenants, keys, inboxes and webhooks. Account-wide keys only. |
admin implies all other scopes. suspend and admin operations require an account-wide key.
Three levels of key
| Key | Created with | Reach |
|---|---|---|
| Account-wide | no tenant_id |
Any tenant in the account, subject to its scopes. Must pass tenant_id when sending. |
| Tenant-bound | tenant_id |
Only that tenant. Cannot pause, administer or even see another tenant (404). |
| Inbox-scoped | inbox_id |
Only that inbox (and implicitly its tenant). The server pins every request to it; the key never needs to send inbox_id. |
Use tenant-bound keys for each customer integration and inbox-scoped keys for each agent. If a key leaks, the blast radius is one tenant or one inbox.
Creating a key
curl -X POST "$API/v1/api-keys" \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "billing-agent",
"inbox_id": "INBOX_ID",
"scopes": ["read", "send"],
"allowed_cidrs": ["203.0.113.0/24"],
"expires_in_days": 90
}'
| Field | Effect |
|---|---|
scopes |
Subset of the scopes above |
tenant_id |
Bind the key to one tenant |
inbox_id |
Pin the key to one inbox |
allowed_cidrs |
Reject requests from other source addresses |
expires_in_days |
Hard expiry; expired keys return 401 |
Managing keys
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/api-keys |
List keys (no secrets) |
POST |
/v1/api-keys/{id}/rotate |
Replace the secret in place; the old one stops working immediately |
DELETE |
/v1/api-keys/{id} |
Revoke |
Key creation, rotation and revocation are recorded in the audit log.
Other credentials
- SMTP credentials are per tenant (
POST /v1/tenants/{id}/smtp-credentials); the password is shown once and can be rotated or revoked. See IMAP and SMTP. - IMAP logs in with the inbox address as username and an API key with
readscope as password. - WebSocket clients that cannot set headers pass the key as a subprotocol:
Sec-WebSocket-Protocol: cyfox.<token>. See Webhooks and events. - Console users sign in with email and password (and optional SSO on Enterprise). A tenant admin user can manage resources for their own tenant without an API key.
Rate and quota enforcement
Limits are counted per tenant in recipients, not requests: quota_daily, quota_monthly, rate_per_minute, rate_per_hour and max_recipients_per_message. Exceeding one returns 429 with a Retry-After header. Account admins set them on POST/PATCH /v1/tenants.