Error Handling
Error Response Format
All errors follow a consistent JSON structure:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": {
"field": "Additional context"
}
}
}HTTP Status Codes
| Status Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request parameters or body |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Resource conflict (varies by endpoint) |
| 422 | Unprocessable Entity | Validation errors |
| 429 | Too Many Requests | Rate limit or quota exceeded |
| 500 | Internal Server Error | Server error |
| 503 | Service Unavailable | Service temporarily unavailable |
Error Codes
Authentication Errors
UNAUTHORIZED (401)
Invalid or missing API key.
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key",
"details": {}
}
}Resolution:
- Verify the
x-api-keyheader is present - Check the API key format is correct
- Ensure the key has not been revoked
Validation Errors
VALIDATION_ERROR (400)
Request validation failed.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {
"eventName": "eventName is required",
"customer.email": "Invalid email format"
}
}
}Resolution:
- Review the
detailsobject for specific field errors - Ensure all required fields are present
- Verify field formats match the API specification
UNPROCESSABLE_ENTITY (422)
Used when payload is structurally valid JSON but fails domain validation.
Common examples:
POST /api/v1/websdk/signalswithsentAtoutside the allowed +/-5 minute windowPOST /api/v1/websdk/signalswheresdkSessionIddoes not match the authenticated SDK token
Not Found Errors
NOT_FOUND (404)
Requested resource does not exist.
{
"error": {
"code": "NOT_FOUND",
"message": "Decision with ID evt_123 not found",
"details": {}
}
}Resolution:
- Verify the resource ID is correct
- Check the resource belongs to your tenant
- Ensure the resource has not been deleted
Rate Limiting Errors
QUOTA_EXCEEDED (429)
Quota limit reached.
{
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Quota exceeded",
"details": {
"limit": 10000,
"window": "1 hour",
"retryAfter": 3600
}
}
}Resolution:
- Wait for the quota window to reset
- Upgrade your plan for higher limits
- Implement request throttling in your application
See for details.
Conflict Errors
CONFLICT (409)
Resource conflict. Some endpoints may return 409 when a write cannot be applied due to a conflicting state.
{
"error": {
"code": "CONFLICT",
"message": "Conflict",
"details": {
"reason": "example"
}
}
}Resolution:
- Inspect
detailsfor the specific conflict reason - Adjust the request or resolve the conflicting state, then retry
Server Errors
INTERNAL_SERVER_ERROR (500)
Unexpected server error.
{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "An unexpected error occurred",
"details": {
"requestId": "req_abc123"
}
}
}Resolution:
- Retry the request after a short delay
- If the error persists, contact support with the
requestId
SERVICE_UNAVAILABLE (503)
Service temporarily unavailable.
{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Service temporarily unavailable",
"details": {
"retryAfter": 60
}
}
}Resolution:
- Wait for the specified
retryAfterseconds - Implement exponential backoff retry logic
Error Handling Best Practices
1. Always Check Status Codes
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
// Handle error based on error.code
}2. Implement Retry Logic
async function makeRequestWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) return response;
const errorData = await response.json();
// Don't retry client errors (4xx) - they won't succeed on retry
if (response.status >= 400 && response.status < 500) {
const error = new Error(errorData.message || 'Client error');
error.status = response.status;
error.data = errorData;
throw error;
}
// Retry server errors (5xx) with exponential backoff
if (response.status >= 500) {
await sleep(Math.pow(2, i) * 1000);
continue;
}
} catch (error) {
// Don't retry client errors (4xx) - they won't succeed on retry
if (error.status >= 400 && error.status < 500) {
throw error;
}
// Only retry network errors (no status) and server errors (5xx)
// Network errors don't have a status property, so they'll be retried
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}3. Handle Rate Limits
async function handleRateLimit(response) {
if (response.status === 429) {
const error = await response.json();
const retryAfter = error.error.details.retryAfter || 60;
console.log(`Rate limited. Retrying after ${retryAfter} seconds`);
await sleep(retryAfter * 1000);
return true; // Indicate retry should happen
}
return false;
}4. Log Errors for Debugging
async function logError(error, context) {
console.error('API Error:', {
code: error.error.code,
message: error.error.message,
details: error.error.details,
context,
timestamp: new Date().toISOString(),
});
}Troubleshooting
Common Issues
"Invalid API key"
- Verify the key format:
naiza_api_sk_live_<32-chars> - Check for extra spaces or newlines
- Ensure the key hasn't been revoked
"Validation failed"
- Review the API documentation for required fields
- Check field types and formats
- Ensure JSON is properly formatted
"sdkSessionId does not match token"
- Ensure your backend mints the token and passes the same sdkSessionId to the browser
- Do not reuse a token across unrelated browser sessions
"Quota exceeded"
- Check your current usage in the dashboard
- Wait for the quota window to reset
- Consider upgrading your plan
"Service unavailable"
- Check Naiza status page
- Wait a few minutes and retry
- Contact support if the issue persists
Getting Help
If you encounter errors not covered here:
- Check the for endpoint-specific errors
- Review your request format and parameters
- Contact support with:
- Error code and message
- Request details (sanitized)
- Request ID (if available)
- Timestamp of the error