Errors, limits, and conventions
Error format, limits per plan, idempotency, pagination, versioning, and usage.
Error format
Every error returns an HTTP status code and a body in this format:
{
"error": {
"type": "invalid_request",
"code": "missing_param",
"message": "The 'agent_id' field is required.",
"param": "agent_id",
"request_id": "req_8q1m2z"
}
}Send the request_id to support when you need help. It's also returned in the Nevox-Request-Id header of every response.
| HTTP | type | When |
|---|---|---|
| 400 | invalid_request | Missing parameter, wrong format, or invalid value |
| 401 | authentication_error | Key missing, invalid, or revoked |
| 403 | permission_error | Missing scope, plan doesn't include the API, or domain not allowed |
| 404 | not_found | The resource doesn't exist or belongs to another account |
| 409 | conflict | State conflict (e.g. sending a message in a closed conversation) or an idempotency key reused with a different body |
| 413 | invalid_request | Body or file too large |
| 422 | invalid_request | Data is well-formed but rejected by a rule (e.g. a private action URL) |
| 429 | rate_limit_error | Request limit or monthly quota reached |
| 500, 502, 503 | api_error | A problem on our side. Retry with exponential backoff. |
Most common codes
code | Meaning |
|---|---|
missing_param, invalid_param | A problem with a field, indicated in param |
invalid_api_key, revoked_api_key | Invalid or revoked key |
insufficient_scope | The key doesn't have the required scope |
plan_required | The API requires the Pro - 3 Agents or Ultimate - 5 Agents plan, with an active subscription |
feature_not_in_plan | Feature available only on Ultimate - 5 Agents (e.g. export) |
origin_not_allowed | Publishable key used on a domain that isn't on the list |
session_token_expired | The widget session token has expired |
conversation_closed | The conversation has already been closed |
idempotency_key_reused | The same idempotency key with a different body |
rate_limited | Too many requests per minute |
monthly_quota_exceeded | Monthly quota reached (conversations, /ask, or events) |
Rate limits
| Pro - 3 Agents | Ultimate - 5 Agents | Test keys | |
|---|---|---|---|
| Requests per minute, per account | 60 | 300 | 20 |
| Messages per minute, per conversation | 20 | 20 | 20 |
| Browser tracking events | No practical limit | No practical limit | — |
Every response includes:
RateLimit-Limit: 60
RateLimit-Remaining: 57
RateLimit-Reset: 41RateLimit-Reset is the number of seconds until the limit resets. When you get a 429, wait for the time given in the Retry-After header.
Monthly quotas
Conversations through the API and the widget count toward the plan's same conversation quota (Pro - 3 Agents: 900; Ultimate - 5 Agents: 1,600). /ask and server events have their own quotas. See the plans table.
You get an email when you reach 80% and 100% of any quota.
Usage
GET /v1/usage (any valid key)
{
"plan": "pro",
"period": { "start": "2026-11-01", "end": "2026-11-30" },
"conversations": { "used": 812, "limit": 2000 },
"ask": { "used": 112, "limit": 1000 },
"server_events": { "used": 2310, "limit": 10000 },
"api_keys": { "used": 2, "limit": 3 },
"webhook_endpoints": { "used": 1, "limit": 3 }
}Idempotency
To safely retry a POST (e.g. after a timeout), send the Idempotency-Key header with a unique value, such as a UUID:
Idempotency-Key: 6c1f0e2a-1b8e-4f0e-9d0a-1d2c3b4a5e6fFor 24 hours, the same key returns the same response without repeating the operation. Using the same key with a different body returns 409 idempotency_key_reused.
Pagination
Lists use a cursor:
curl "https://api.nevox.ai/v1/conversations?limit=50&cursor=eyJpZCI6..." \
-H "Authorization: Bearer $NEVOX_API_KEY"{
"data": [ ... ],
"has_more": true,
"next_cursor": "eyJpZCI6ImNvbnZfN..."
}limit ranges from 1 to 100 (default 20). When has_more is false, you've reached the end.
Versioning
The major version is in the path (/v1). Changes that could break integrations only ship in a new major version, with at least 6 months' notice.
Within /v1 we may, without notice: add endpoints, add fields to responses, add new values to list fields (such as new event types), and add optional parameters. Build your integration to ignore fields it doesn't recognize.
All changes are listed in the changelog.
IDs
| Prefix | Resource |
|---|---|
agt_ | Agent |
conv_ | Conversation |
msg_ | Message |
ctc_ | Contact |
kn_ | Knowledge item |
svc_ | Service |
act_ / inv_ | Action / action invocation |
whk_ / evt_ | Webhook / webhook event |
fb_ / sug_ | Feedback / learning suggestion |
vis_ / ses_ | Visitor / session |
exp_ | Export |
req_ | Request |