All Yotel API errors return a consistent JSON shape. This page catalogs
every error type, including domain-specific errors from voice agents and
AI sessions.
{
"detail": "Human-readable error description"
}
For validation errors (422), Pydantic returns a list:
{
"detail": [
{
"loc": ["body", "predictive_target_abandon"],
"msg": "ensure this value is less than or equal to 0.03",
"type": "value_error.number.not_le"
}
]
}
Standard HTTP status codes
| Status | Meaning | When |
|---|
200 | OK | Successful read or update |
201 | Created | Resource created (campaigns, leads, voice agents, keys, webhooks) |
204 | No Content | Successful delete |
400 | Bad Request | Malformed request or query param out of range |
401 | Unauthorized | Missing, malformed, or expired auth token |
403 | Forbidden | Valid token but insufficient scope or permission |
404 | Not Found | Resource doesn’t exist or belongs to another tenant |
409 | Conflict | State-based conflict (see domain-specific errors below) |
422 | Validation Error | Request body fails Pydantic validation |
429 | Too Many Requests | Rate limit exceeded — check Retry-After header |
500 | Internal Server Error | Unexpected server error |
Cross-tenant access always returns 404, never 403. This prevents
attackers from confirming whether a resource exists in another tenant.
Authentication errors
| Error | Status | detail | Cause |
|---|
| Malformed key | 401 | "API key must start with yt_live_ or yt_test_" | Key doesn’t match expected format |
| Invalid key | 401 | "Invalid API key" | Key not found or revoked |
| Scope denied | 403 | "Scope 'X' required" | Key lacks the required scope for this endpoint |
| Rate limited | 429 | "Rate limit exceeded" | Per-key request budget exhausted |
Campaign errors
| Error | Status | Cause |
|---|
InvalidCampaignState | 409 | Invalid state transition (e.g., starting a completed campaign) |
| Abandon rate validation | 422 | predictive_target_abandon exceeds 0.03 (TRAI hard cap) |
| Predictive ratio range | 422 | predictive_max_ratio < predictive_min_ratio |
| Delete while running | 409 | Cannot delete a running campaign — pause or stop first |
Voice agent errors
| Error | Status | detail | Cause |
|---|
NoVoiceAgentConfigured | 424 | "No voice agent resolved" | The override hierarchy (flow → campaign → tenant default) resolved no agent. Set a tenant default or pin one per campaign. |
VoiceAgentInUse | 409 | "Voice agent has active sessions" | Cannot hard-delete a voice agent with in-progress calls. Use archive instead. |
MaxConcurrentExceeded | 429 | "Max concurrent sessions reached" | The voice agent’s max_concurrent limit is hit. Wait for active sessions to end or increase the limit. |
AI session errors
| Error | Status | detail | Cause |
|---|
AISessionTerminated | 410 | "AI session already ended" | Sending a control verb to a call that has already hung up. |
ConferenceMembershipRequired | 403 | "Whisper requires conference membership" | whisper, barge, or monitor verbs require the call to be in an active conference. Call conference_start first. |
| Token mismatch | 403 | "Token call_id mismatch" | The callback token’s embedded call_id doesn’t match the URL path. |
| Cross-tenant | 404 | "Call not found" | The call belongs to a different tenant than the auth context. |
Recording errors
| Error | Status | Cause |
|---|
| Not yet available | 409 | Recording upload pipeline still processing. Wait for the call.recording_ready webhook. |
| Call not found | 404 | Call doesn’t exist or belongs to another tenant. |
Webhook management errors
| Error | Status | Cause |
|---|
| URL not HTTPS | 422 | Webhook URL must use https:// |
| Test tenant URL | 422 | Test tenants can only register localhost, 127.0.0.1, *.ngrok.io, or *.test.yotel.in |
Validation patterns
Common validation rules enforced across the API:
| Rule | Endpoints | detail |
|---|
| Indian phone format | Leads | 10 digits, optional 0/91 prefix; 5–20 chars raw |
| WebSocket URL format | Voice agents | Must start with ws:// or wss:// |
| TRAI abandon cap | Campaigns | predictive_target_abandon ≤ 0.03 |
| Rate limit range | API keys | rate_limit_per_min must be 1–100,000 |
| Stats window range | Agents | window_hours must be 1–720 |
| Bulk lead limit | Leads | Max 500 leads per :bulk request |
Successful responses include:
| Header | Description |
|---|
X-RateLimit-Limit | Per-minute budget |
X-RateLimit-Remaining | Remaining requests this window |
On 429 responses:
| Header | Description |
|---|
Retry-After | Seconds until the next minute boundary |
Both SDKs auto-retry on 429 with exponential backoff (configurable).