Errors
Every error returns a JSON body with an HTTP status code.
Error format
Every error response uses the same JSON body, regardless of endpoint:
json
{
"statusCode": 400,
"error": "ValidationError",
"message": "channel is required",
"code": "optional_code",
"field": "channel"
}statusCode— The HTTP status code, repeated in the body.error— The error class name — branch on this to handle specific error types in code.message— A human-readable description of what went wrong.code— A stable, machine-readable code, present only when the error sets one (e.g.plan_limit).field— The offending request field, present only for field-level validation errors.
Unexpected server errors (500) never leak internal details — the message is always masked:
json
{
"statusCode": 500,
"error": "InternalServerError",
"message": "Something went wrong"
}Status codes
The error field is one of the following classes:
| Status | Error | Meaning |
|---|---|---|
400 | ValidationError | The request failed validation — check message and field. |
401 | UnauthorizedError | Missing or invalid credentials. |
402 | PaymentRequiredError | A plan limit was reached; code is plan_limit. Upgrade the plan to continue. |
403 | ForbiddenError | Authenticated, but not permitted to perform this action. |
404 | NotFoundError | The requested resource does not exist. |
409 | ConflictError | The request conflicts with the current state of the resource. |
429 | Error | Too many requests — see Rate limiting below. |
500 | InternalServerError | An unexpected server error. The message is masked; check server-side logs for details. |
Rate limiting
The API allows 100 requests per minute globally, with tighter limits on some endpoints. When a request is rate-limited, the API returns 429.
A rate-limited response uses the generic Error class rather than a specific error type — its message tells you how long to wait before retrying:
json
{
"statusCode": 429,
"error": "Error",
"message": "Rate limit exceeded, retry in 1 minute"
}Back off and retry
Don't retry a 429 immediately. Wait, then retry with exponential backoff and jitter.