API Overview
The VOCALS REST API lets you manage agents, initiate calls, configure providers, and retrieve analytics programmatically. All endpoints are served under a single base URL and require authentication.
Base URL
https://api.usevocals.com/api/v1
All paths in this documentation are relative to the base URL. For example, GET /agents means GET https://api.usevocals.com/api/v1/agents.
Authentication
VOCALS supports two authentication methods. Every request must include one of them.
Bearer JWT (Supabase Auth)
Authenticate with a Supabase JWT obtained through the standard Supabase Auth flow (email/password, OAuth, etc.). Pass it in the Authorization header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
The JWT contains the user's identity and is resolved to a tenant automatically. This method is used by the dashboard frontend and is suitable for user-facing integrations.
API Key (X-API-Key)
For server-to-server and automation use cases (n8n, Make, custom scripts), generate an API key from the dashboard or via the /api-keys endpoint, then pass it in the X-API-Key header:
X-API-Key: voc_a1b2c3d4e5f6...
API keys are tied to a tenant and carry their own rate limits. The full key is shown only once at creation time.
When both headers are present, the API key takes precedence.
Rate Limiting
Rate limits are enforced per API key using Redis counters. Each key has two thresholds:
| Limit | Default | Description |
|---|---|---|
rate_limit_rpm | 60 | Maximum requests per minute |
rate_limit_rpd | 10,000 | Maximum requests per day |
When a limit is exceeded the API returns 429 Too Many Requests with a JSON error body. You can view and adjust rate limits through the /rate-limits endpoint.
Requests authenticated via Bearer JWT are not subject to API key rate limits.
Common Headers
| Header | Required | Description |
|---|---|---|
Authorization | Conditional | Bearer <jwt> for Supabase Auth |
X-API-Key | Conditional | API key string (alternative to Bearer) |
Content-Type | Yes (for POST/PUT) | Always application/json |
Error Response Format
All errors follow a consistent JSON structure:
{
"detail": "Human-readable error message"
}
For validation errors (422), FastAPI returns the standard format:
{
"detail": [
{
"loc": ["body", "name"],
"msg": "Field required",
"type": "missing"
}
]
}
HTTP Status Codes
| Code | Meaning |
|---|---|
200 | Success |
201 | Resource created |
202 | Accepted (async operations like outbound calls) |
204 | Deleted successfully (no body) |
400 | Bad request (invalid input, missing config) |
401 | Unauthorized (missing or invalid auth) |
404 | Resource not found |
422 | Validation error (malformed request body) |
429 | Rate limit exceeded |
500 | Internal server error |
Pagination
Endpoints that return lists support pagination with these query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-indexed) |
page_size | integer | 20 | Items per page (max 100) |
Paginated responses include metadata:
{
"items": [...],
"total": 142,
"page": 1,
"page_size": 20
}
Multi-Tenancy
VOCALS is multi-tenant. All data is scoped to the tenant associated with your authentication credentials. You cannot access resources belonging to other tenants. The tenant is resolved automatically from your JWT or API key -- there is no tenant ID header to set.
Quick Example
# List all agents
curl -H "X-API-Key: voc_your_key_here" \
https://api.usevocals.com/api/v1/agents
# Initiate an outbound call
curl -X POST \
-H "X-API-Key: voc_your_key_here" \
-H "Content-Type: application/json" \
-d '{"to_number": "+15551234567", "agent_id": "uuid-here"}' \
https://api.usevocals.com/api/v1/calls