API keys & permissions
Copy page
API keys are the primary way to authenticate. Each key is scoped by permissions and bound to one workspace, so you can issue separate keys per application, per environment, or per team — and revoke them independently.
Create a key
Section titled “Create a key”-
Log in to the customer portal.
-
Go to Settings → API Keys and click Create API Key.
-
General keys start with
sms.send,sms.read,balance.read, andpricing.read. Select only the permissions the integration needs (see the table below), then optionally enable HMAC signature verification for high-security environments. You can later use Edit permissions on the key row; team members can grant only permissions they hold themselves. -
Copy the key (
sk_prod_…). It is shown only once — store it in your secrets manager right away.
Permissions
Section titled “Permissions”Keys follow a deny-by-default model: a key can only call endpoints its permissions allow.
| Permission | Grants |
|---|---|
* |
Full access |
sms.send |
Send SMS (POST /sms/send, POST /sms/send-individual, and self-service POST /integrations/sms/send) |
sms.read |
Status, stats, messages, unified view (GET /sms/*) |
balance.read |
Balance (GET /user/balance) |
pricing.read |
Pricing (GET/POST /user/pricing) |
payments.read |
Payment history and adjustments (GET /user/payments) |
webhooks.read |
Webhook settings and logs (GET /user/webhooks, GET /user/webhooks/logs) |
webhooks.write |
Update webhooks and send tests (PUT /user/webhooks, POST /user/webhooks/test) |
Recommended configurations
Section titled “Recommended configurations”| Use case | Permissions |
|---|---|
| Send + track delivery | sms.send, sms.read |
| Send only (fire & forget) | sms.send |
| Dashboard / monitoring | sms.read, balance.read |
| Billing reconciliation | balance.read, pricing.read, payments.read |
| Webhook management | webhooks.read, webhooks.write |
| Full API access | sms.send, sms.read, balance.read, pricing.read, payments.read, webhooks.read, webhooks.write |
Calling an endpoint outside the key’s permissions returns 403 FORBIDDEN with
required_permission. Enable that permission in Portal → API Keys → Edit
permissions, or create a replacement key with the required permission.
Key security best practices
Section titled “Key security best practices”- One key per application and environment. Separate keys for staging and production let you rotate or revoke one without touching the other.
- Grant the minimum permissions. A background sender rarely needs account-level read permissions beyond balance checks.
- Store keys in environment variables or a secrets manager. Never commit them to version control or embed them in client-side code.
- Rotate on staff changes and on any suspicion of exposure — create a new key, switch traffic, then delete the old one.
- Enable HMAC signing for environments where transport interception is a concern — see authentication.
Errors you may see
Section titled “Errors you may see”| HTTP | Code | Meaning | Headers or details |
|---|---|---|---|
| 400 | AMBIGUOUS_AUTHENTICATION |
Key and session cookie supplied together | Remove one credential |
| 401 | INVALID_API_KEY |
Key not found or malformed | — |
| 401 | API_KEY_OWNER_INACTIVE |
Key owner is inactive | — |
| 401 | API_KEY_INACTIVE |
Key is disabled | — |
| 401 | API_KEY_EXPIRED |
Key expired | — |
| 401 | CROSS_TENANT_WORKSPACE |
The key’s workspace is missing or deleted; create a key in a live workspace | Description invalid_api_key |
| 429 | TOO_MANY_ATTEMPTS |
Too many key authentication failures | Retry-After |
| 503 | AUTH_PROTECTION_UNAVAILABLE |
Authentication protection store unavailable (login, 2FA or API-key failure budget); the request was refused, not bypassed | Retry-After: 1 |
| 503 | API_KEY_VALIDATION_UNAVAILABLE |
Key validation unavailable | Retry-After: 1 |
| 503 | REPLAY_PROTECTION_UNAVAILABLE |
Replay store unavailable for a write | Retry-After: 1 |
| 401 | SIGNATURE_REQUIRED |
Signature headers missing | — |
| 401 | INVALID_SIGNATURE |
Signature, timestamp or replay check failed | — |
| 403 | FORBIDDEN |
Route or permission denied | required_permission when a permission is missing |
| 403 | API_KEY_CREATOR_INACTIVE |
Key creator is inactive | — |
| 403 | SECTION_ACCESS_DENIED |
Creator lacks section access | — |
| 503 | SECTION_ACCESS_UNAVAILABLE |
Section access could not be checked | — |
| 429 | RATE_LIMIT_EXCEEDED |
Account rate limit exceeded | Retry-After, X-RateLimit-* |
| 503 | RATE_LIMIT_UNAVAILABLE |
Account rate limiter unavailable | — |
API keys have no IP allowlist. X-Workspace-ID is ignored on API-key requests; the key selects its workspace. Server error bodies are generic; provide X-Request-ID to support.
Full list: error reference.
