REST API
The REST API add-on exposes a workspace's calling data — calls, contacts, campaigns, agents, credits, analytics, and webhooks — over an authenticated, scoped, rate-limited HTTP API under /api/v1.
It is plan-gated by the api_enabled feature; the customer-facing key management screen and routes are protected by plan.feature:api. Plans also expose api_keys_limit (how many keys a workspace may hold) and api_rate_limit_per_min (the default per-key rate limit). See Billing & credits for plan features.
Creating an API key
Generate keys in the customer panel at /app/api-keys. When creating a key you set:
- a name (label),
- the scopes it may use,
- an optional IP whitelist (requests from other IPs are rejected),
- a per-key rate limit (requests per minute; defaults to 100).
A key is issued as prefix.secret, where the prefix looks like cmk_XXXXXXXX. The full token is shown once at creation and only the bcrypt hash of the secret is stored.
Copy the token now
The secret is displayed a single time immediately after creation and can never be retrieved again. If lost, revoke the key and issue a new one.
Keys can be revoked (disabled but retained for audit) or deleted. A workspace cannot create more keys than its plan's api_keys_limit.
Authentication
Send the full token as a Bearer credential:
curl https://your-app.example.com/api/v1/calls \
-H "Authorization: Bearer cmk_ab12cd34.PLAINTEXT_SECRET_SHOWN_ONCE"
The key is resolved by prefix and the secret verified against its hash; revoked, expired, or IP-mismatched keys are rejected with 401.
Scopes
Each route requires a scope. A key with the admin scope satisfies every scope check (wildcard).
| Scope | Grants |
|---|---|
calls:read | List and read calls |
calls:write | Trigger and hang up calls |
campaigns:read | List and read campaigns |
campaigns:write | Create, launch, and pause campaigns |
agents:read | List and read agents |
agents:write | Reserved for agent writes |
contacts:read | List and read contacts |
contacts:write | Create, bulk-import, and delete contacts |
credits:read | Read the credit balance |
analytics:read | Read analytics |
webhooks:read | List webhooks |
webhooks:write | Create and delete webhooks |
admin | Wildcard — satisfies all scopes |
A request with a valid key but a missing scope returns 403.
Rate limiting
Every key is throttled at its own rate_limit_per_min. Responses carry the standard headers, and an exceeded limit returns 429 with a Retry-After header.
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute |
X-RateLimit-Remaining | Requests left in the current window |
Retry-After | Seconds to wait after a 429 |
Endpoints
All endpoints live under /api/v1 and are scoped to the calling key's workspace.
| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /api/v1/calls | calls:read | List calls |
| POST | /api/v1/calls | calls:write | Trigger a call (queues it) |
| GET | /api/v1/calls/{call} | calls:read | Get one call |
| POST | /api/v1/calls/{call}/hangup | calls:write | Hang up a call |
| GET | /api/v1/campaigns | campaigns:read | List campaigns |
| POST | /api/v1/campaigns | campaigns:write | Create a campaign |
| GET | /api/v1/campaigns/{campaign} | campaigns:read | Get one campaign |
| POST | /api/v1/campaigns/{campaign}/launch | campaigns:write | Launch a campaign |
| POST | /api/v1/campaigns/{campaign}/pause | campaigns:write | Pause a campaign |
| GET | /api/v1/agents | agents:read | List agents |
| GET | /api/v1/agents/{agent} | agents:read | Get one agent |
| GET | /api/v1/contacts | contacts:read | List contacts |
| POST | /api/v1/contacts | contacts:write | Create a contact |
| POST | /api/v1/contacts/bulk | contacts:write | Bulk import contacts (deduped) |
| GET | /api/v1/contacts/{contact} | contacts:read | Get one contact |
| DELETE | /api/v1/contacts/{contact} | contacts:write | Delete a contact |
| GET | /api/v1/credits | credits:read | Current credit balance |
| GET | /api/v1/analytics | analytics:read | Calling analytics |
| GET | /api/v1/webhooks | webhooks:read | List webhooks |
| POST | /api/v1/webhooks | webhooks:write | Create a webhook |
| DELETE | /api/v1/webhooks/{webhook} | webhooks:write | Delete a webhook |
Example: trigger a call
curl -X POST https://your-app.example.com/api/v1/calls \
-H "Authorization: Bearer cmk_ab12cd34.PLAINTEXT_SECRET_SHOWN_ONCE" \
-H "Content-Type: application/json" \
-d '{"agent_id": 1, "contact_id": 42}'
Audit logging
Every /api/v1 request is recorded to an audit log (method, path, key, status, and a per-request X-Request-Id), giving a full trail of API activity per key.
Interactive docs
The OpenAPI spec and a Swagger playground are public (no key required to view):
GET /api/docs # OpenAPI 3 JSON spec
GET /api/docs/playground # Swagger UI — try requests in the browser
Paste a Bearer token into the playground's authorize dialog to exercise the endpoints live against your own workspace.