Error Handling

Understanding and handling errors from the Text-to-Speech API.

HTTP Status Codes

CodeDescriptionCommon Cause
200SuccessRequest completed successfully
400Bad RequestInvalid parameters
401UnauthorizedInvalid or missing API key
402Payment RequiredInsufficient credits
403ForbiddenValid key but insufficient permissions
404Not FoundResource or endpoint not found
413Payload Too LargeText exceeds 5,000 characters
422UnprocessableValid request but failed validation
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer-side issue
503Service UnavailableTemporary overload

Error Response Format

{
    "success": false,
    "error": {
        "code": "INVALID_VOICE",
        "message": "Voice 'InvalidVoice' not found.",
        "category": "validation",
        "resolution": "Use /v1/voices endpoint to get valid voice names",
        "details": {
            "provided": "InvalidVoice",
            "suggestions": ["Peter", "Emma", "James"]
        }
    },
    "request_id": "req_abc123xyz",
    "timestamp": 1699820400.123
}
FieldDescription
successAlways false for error responses
error.codeMachine-readable error code for programmatic handling
error.messageHuman-readable description of the error
error.categoryError category (authentication, validation, rate_limit, etc.)
error.resolutionSuggested steps to resolve the issue
request_idUnique ID for tracking this request (useful for support)

Common Error Codes

Authentication Errors

Error CodeDescriptionSolution
MISSING_API_KEYNo API key providedAdd X-API-Key header
INVALID_API_KEYAPI key not recognizedVerify your API key
API_KEY_EXPIREDAPI key has expiredGenerate a new API key from dashboard
API_KEY_REVOKEDAPI key has been revokedContact support or generate new key
API_KEY_DISABLEDAPI key has been disabledContact support

Validation Errors

Error CodeDescriptionSolution
MISSING_TEXTNo text providedInclude text in request body
TEXT_TOO_LONGText exceeds 5,000 charactersSplit into multiple requests
INVALID_VOICEVoice not foundUse valid voice name from /v1/voices
INVALID_LANGUAGELanguage not supportedUse valid language code from /v1/languages
INVALID_MODELModel not foundUse: aura-lite, aura-prime, aura-max, rapid-flash, rapid-max
INVALID_SPEEDSpeed out of rangeUse value between 0.5 and 2.0
INVALID_PITCHPitch out of rangeUse value between 0.5 and 2.0
INVALID_FORMATOutput format not supportedUse mp3 or wav

Credit Errors

Error CodeDescriptionSolution
INSUFFICIENT_CREDITSNot enough creditsAdd credits to account
CREDIT_CHECK_FAILEDUnable to verify creditsRetry request

Rate Limit Errors

Error CodeDescriptionSolution
RATE_LIMIT_EXCEEDEDToo many requestsWait and retry with backoff
CONCURRENT_LIMITToo many concurrent requestsWait for requests to complete

Model-Specific Errors

Error CodeDescriptionSolution
LANGUAGE_NOT_SUPPORTEDLanguage not supported by modelUse different model (rapid-flash has 18 languages, rapid-max has 41)
EXPRESSION_NOT_SUPPORTEDExpression tags not supportedUse Aura model for expressions

Permission Errors

Error CodeDescriptionSolution
MODEL_ACCESS_DENIEDYour plan doesn't include this modelUpgrade to a plan with access to this model
VOICE_ACCESS_DENIEDPremium voice not available on your planUpgrade to access premium voices
FEATURE_DISABLEDFeature not enabled for your accountContact support to enable this feature

Retry Strategy

Different errors require different retry approaches:

Error TypeShould Retry?Strategy
400 Validation ❌ No Fix the request parameters
401 Auth ❌ No Check/refresh API key
402 Payment ❌ No Add credits to account
403 Permission ❌ No Upgrade plan or contact support
429 Rate Limit ✅ Yes Wait for Retry-After header duration
500 Server ✅ Yes Exponential backoff (1s, 2s, 4s...)
503 Unavailable ✅ Yes Wait and retry with backoff
💡 Exponential Backoff

For server errors, use exponential backoff: wait 1s, then 2s, then 4s, etc. Add random jitter (0-1s) to prevent thundering herd issues when many clients retry simultaneously.

Error Handling Example

import requests
import time

def generate_speech_with_retry(text, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.post(
                "https://yourvoic.com/api/v1/tts/generate",
                headers={"X-API-Key": "your_api_key"},
                json={
                    "text": text,
                    "voice": "Peter",
                    "language": "en-US"
                }
            )
            
            if response.status_code == 200:
                return response.content
            
            # Parse error response
            error = response.json().get('error', {})
            error_code = error.get('code', '')
            
            # Don't retry these errors
            non_retryable = [
                'INVALID_VOICE', 'INVALID_LANGUAGE', 'INVALID_MODEL',
                'TEXT_TOO_LONG', 'INVALID_API_KEY', 'INSUFFICIENT_CREDITS'
            ]
            
            if error_code in non_retryable:
                raise Exception(f"Non-retryable error: {error_code} - {error.get('message')}")
            
            # Retry with exponential backoff for rate limits
            if response.status_code == 429:
                wait_time = (2 ** attempt) + 1
                print(f"Rate limited. Retrying in {wait_time}s...")
                time.sleep(wait_time)
                continue
            
            # Retry server errors
            if response.status_code >= 500:
                wait_time = 2 ** attempt
                print(f"Server error. Retrying in {wait_time}s...")
                time.sleep(wait_time)
                continue
            
            raise Exception(f"Request failed: {error}")
            
        except requests.RequestException as e:
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)
                continue
            raise
    
    raise Exception("Max retries exceeded")

# Usage
try:
    audio = generate_speech_with_retry("Hello, world!")
    with open("output.mp3", "wb") as f:
        f.write(audio)
except Exception as e:
    print(f"Error: {e}")

JavaScript Example

async function generateTTSWithRetry(text, maxRetries = 3) {
    const url = 'https://yourvoic.com/api/v1/tts/generate';
    
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-API-Key': 'your_api_key'
                },
                body: JSON.stringify({
                    text: text,
                    voice: 'Peter',
                    language: 'en-US'
                })
            });
            
            if (response.ok) {
                return await response.blob();
            }
            
            const error = await response.json();
            const errorCode = error.error?.code;
            
            // Don't retry these errors
            const nonRetryable = [
                'INVALID_VOICE', 'INVALID_LANGUAGE', 'INVALID_MODEL',
                'TEXT_TOO_LONG', 'INVALID_API_KEY', 'INSUFFICIENT_CREDITS'
            ];
            
            if (nonRetryable.includes(errorCode)) {
                throw new Error(`Non-retryable: ${errorCode} - ${error.error?.message}`);
            }
            
            // Retry rate limits with backoff
            if (response.status === 429) {
                const retryAfter = response.headers.get('Retry-After') || (2 ** attempt);
                console.log(`Rate limited. Waiting ${retryAfter}s...`);
                await new Promise(r => setTimeout(r, retryAfter * 1000));
                continue;
            }
            
            // Retry server errors
            if (response.status >= 500) {
                const waitTime = Math.pow(2, attempt) * 1000;
                console.log(`Server error. Retrying in ${waitTime}ms...`);
                await new Promise(r => setTimeout(r, waitTime));
                continue;
            }
            
            throw new Error(`Request failed: ${errorCode}`);
        } catch (e) {
            if (attempt === maxRetries - 1) throw e;
        }
    }
    
    throw new Error('Max retries exceeded');
}

// Usage
generateTTSWithRetry("Hello, world!")
    .then(blob => {
        const url = URL.createObjectURL(blob);
        const audio = new Audio(url);
        audio.play();
    })
    .catch(e => console.error('Error:', e));

Debugging Tips

  • Save the request_id - Include it when contacting support for faster resolution
  • Check response headers - Rate limit headers show remaining quota
  • Validate locally - Check text length and parameters before making API calls
  • Use the health endpoint - Check /v1/health to verify API availability
  • Log full responses - The resolution field often contains the fix
# Check API health status
curl -s https://yourvoic.com/api/v1/health | jq

# Test your API key
curl -s -H "X-API-Key: your_key" \
  https://yourvoic.com/api/v1/usage | jq

Best Practices

  • Validate input - Check text length and parameters before sending
  • Handle rate limits - Implement exponential backoff
  • Monitor credits - Check balance before large batches
  • Log errors - Keep track of error codes for debugging
  • Test edge cases - Handle empty text, special characters, long content