Error Handling
All Omnix API responses use standard HTTP status codes combined with a structured JSON error body. This page covers the error taxonomy, how to interpret error responses, and the recommended retry strategy.
Error Response Shape
When a request fails, the response body always contains:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "contactInfo must contain at least one identifier.",
"details": {
"field": "contactInfo",
"constraint": "min_identifiers"
}
}
}
| Field |
Type |
Description |
error.code |
string |
Machine-readable error code (see table below) |
error.message |
string |
Human-readable description |
error.details |
object |
Optional — additional context (field name, constraint violated, etc.) |
Error Code Reference
Authentication & Authorization
| Code |
HTTP |
Meaning |
Fix |
UNAUTHORIZED |
401 |
Missing or malformed x-api-key header |
Add x-api-key: YOUR_API_KEY to the request |
FORBIDDEN |
403 |
Key revoked, invalid, or subscription inactive |
Regenerate the key in Admin → API Keys |
| Code |
HTTP |
Meaning |
Fix |
VALIDATION_ERROR |
400 |
One or more parameters failed schema validation |
Check error.details.field for the offending field |
INVALID_PHONE_FORMAT |
400 |
Phone number not in E.164 format |
Use +15551234567 format, not 555-123-4567 |
TEMPLATE_NOT_FOUND |
400 |
templateName does not match any template in the workspace |
Check exact name in Admin → Templates |
Resource Errors
| Code |
HTTP |
Meaning |
Fix |
CONTACT_NOT_FOUND |
404 |
A contactId was passed but doesn't exist in this subscription |
Use findOrCreateContact instead of passing a raw ID |
CONVERSATION_NOT_FOUND |
404 |
conversationId doesn't exist or belongs to another subscription |
Verify the ID from a previous API response |
EXTENSION_NOT_AVAILABLE |
409 |
Requested extension is already assigned |
Use getAvailableExtensions first |
Channel Errors
| Code |
HTTP |
Meaning |
Fix |
CHANNEL_NOT_CONFIGURED |
422 |
The requested channelType has no active channel setup |
Connect the channel in Admin → Channels |
WHATSAPP_TEMPLATE_REQUIRED |
422 |
WhatsApp messages to new contacts require an approved template |
Use templateName with an approved WA template |
Rate Limiting
| Code |
HTTP |
Meaning |
Fix |
RATE_LIMITED |
429 |
Too many requests |
Back off and retry — see strategy below |
Server Errors
| Code |
HTTP |
Meaning |
Fix |
INTERNAL_ERROR |
500 |
Unexpected server error |
Retry with backoff; contact support if persistent |
SERVICE_UNAVAILABLE |
503 |
Omnix or a downstream service is temporarily unavailable |
Retry with exponential backoff |
Retry Strategy
Only retry on 429, 500, and 503 responses. Do not retry 400, 401, 403, 404, or 422 errors — these indicate a problem with the request itself and retrying will produce the same failure.
Recommended exponential backoff:
attempt 1 → wait 1s
attempt 2 → wait 2s
attempt 3 → wait 4s
attempt 4 → wait 8s (give up after this)
For 429 responses, check the Retry-After header if present and wait that duration before retrying.
Example in JavaScript:
async function callOmnixWithRetry(method, params, maxAttempts = 4) {
const RETRYABLE = [429, 500, 503];
let delay = 1000;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const res = await fetch(`${OMNIX_URL}/api/rpc`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': OMNIX_KEY,
},
body: JSON.stringify({ method, params }),
});
if (res.ok) return res.json();
const { error } = await res.json();
if (!RETRYABLE.includes(res.status) || attempt === maxAttempts) {
throw new Error(`Omnix API error [${error.code}]: ${error.message}`);
}
const retryAfter = res.headers.get('Retry-After');
await new Promise(r => setTimeout(r, retryAfter ? retryAfter * 1000 : delay));
delay *= 2;
}
}
Debugging Tips
- Start with
ping — If ping fails, the issue is authentication or network, not your request body.
- Check
error.details — Validation errors always include the offending field name.
- E.164 phone format — Always
+ followed by country code then number, no spaces or dashes.
- Template names are case-sensitive —
welcome_message ≠ Welcome_Message.
- WhatsApp restrictions — Unstructured messages to contacts who haven't messaged you in 24h require an approved template. Always use
sendTemplatedMessage for cold outbound on WhatsApp.