Error Handling
API error codes and troubleshooting
Error Handling
The ProsodyAI API uses standard HTTP status codes and returns detailed error information in JSON format.
Error Response Format
{
"error": {
"code": "error_code",
"message": "Human-readable error message",
"details": {
// Additional context (optional)
},
"request_id": "req_abc123"
}
}HTTP Status Codes
| Status | Description |
|---|---|
200 | Success |
400 | Bad Request - Invalid parameters |
401 | Unauthorized - Invalid or missing API key |
403 | Forbidden - Insufficient permissions |
404 | Not Found - Resource doesn't exist |
413 | Payload Too Large - File exceeds limit |
415 | Unsupported Media Type - Invalid audio format |
422 | Unprocessable Entity - Valid format but can't process |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error |
503 | Service Unavailable - Temporary outage |
Common Error Codes
Authentication Errors
unauthorized
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key"
}
}Solution: Check your API key is correct and included in the Authorization header.
api_key_expired
{
"error": {
"code": "api_key_expired",
"message": "API key has expired",
"details": {
"expired_at": "2025-01-01T00:00:00Z"
}
}
}Solution: Generate a new API key in the dashboard.
Validation Errors
validation_error
{
"error": {
"code": "validation_error",
"message": "Invalid request parameters",
"details": {
"audio_url": ["Invalid URL format"],
"vertical": ["Must be one of: contact_center, healthcare, sales, ..."]
}
}
}Solution: Check request parameters match the API specification.
missing_audio
{
"error": {
"code": "missing_audio",
"message": "No audio provided. Include audio, audio_url, or audio_base64"
}
}Solution: Provide audio via file upload, URL, or base64 encoding.
Audio Errors
unsupported_audio_format
{
"error": {
"code": "unsupported_audio_format",
"message": "Unsupported audio format: video/mp4",
"details": {
"detected_format": "video/mp4",
"supported_formats": ["audio/wav", "audio/mpeg", "audio/ogg", "audio/webm", "audio/flac"]
}
}
}Solution: Convert audio to a supported format (WAV recommended).
audio_too_short
{
"error": {
"code": "audio_too_short",
"message": "Audio duration too short for analysis",
"details": {
"minimum_duration": 0.5,
"actual_duration": 0.2
}
}
}Solution: Provide audio at least 0.5 seconds long.
audio_too_long
{
"error": {
"code": "audio_too_long",
"message": "Audio duration exceeds maximum for single analysis",
"details": {
"maximum_duration": 300,
"actual_duration": 450
}
}
}Solution: Use streaming API for long audio, or split into segments.
audio_fetch_failed
{
"error": {
"code": "audio_fetch_failed",
"message": "Failed to fetch audio from URL",
"details": {
"url": "https://example.com/audio.wav",
"status": 404
}
}
}Solution: Verify the audio URL is accessible and returns valid audio.
Rate Limiting
rate_limit_exceeded
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded",
"details": {
"limit": 1000,
"window": "1m",
"retry_after": 45
}
}
}Solution: Wait for retry_after seconds, or upgrade your plan.
Rate limit info is also in response headers:
X-RateLimit-Limit: Requests per minuteX-RateLimit-Remaining: Remaining requestsX-RateLimit-Reset: Reset timestamp
Resource Errors
session_not_found
{
"error": {
"code": "session_not_found",
"message": "Session not found",
"details": {
"session_id": "call-12345"
}
}
}Solution: Verify the session ID is correct and hasn't expired.
fine_tune_not_found
{
"error": {
"code": "fine_tune_not_found",
"message": "Fine-tuning job not found",
"details": {
"job_id": "ft-abc123"
}
}
}Processing Errors
audio_processing_failed
{
"error": {
"code": "audio_processing_failed",
"message": "Failed to process audio",
"details": {
"reason": "Corrupted audio file"
}
}
}Solution: Verify the audio file is valid and not corrupted.
model_unavailable
{
"error": {
"code": "model_unavailable",
"message": "Requested model is temporarily unavailable",
"details": {
"model": "ft-model-xyz"
}
}
}Solution: Retry the request, or use a different model.
Error Handling Best Practices
Retry Logic
Implement exponential backoff for transient errors:
async function analyzeWithRetry(request: AnalyzeRequest, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.analyze(request);
} catch (error) {
if (error instanceof RateLimitError) {
await sleep(error.retryAfter * 1000);
continue;
}
if (error.status >= 500 && attempt < maxRetries - 1) {
await sleep(Math.pow(2, attempt) * 1000);
continue;
}
throw error;
}
}
}Error Logging
Include request_id in logs for debugging:
try {
const result = await client.analyze({ audio });
} catch (error) {
console.error('Analysis failed', {
code: error.code,
message: error.message,
requestId: error.requestId,
});
}User-Friendly Messages
Map error codes to user-friendly messages:
const errorMessages: Record<string, string> = {
'unauthorized': 'Please check your API key configuration.',
'rate_limit_exceeded': 'Too many requests. Please try again in a moment.',
'unsupported_audio_format': 'Please upload a WAV, MP3, or OGG file.',
'audio_too_short': 'Audio must be at least half a second long.',
};
function getUserMessage(error: ProsodyError): string {
return errorMessages[error.code] || 'An unexpected error occurred.';
}