Skip to main content

Error Response Format

All API errors follow a consistent format:
{
  "error": "Brief error description",
  "details": [
    {
      "code": "specific_error_code",
      "message": "Detailed error message",
      "field": "field_name" // Optional, for validation errors
    }
  ]
}

HTTP Status Codes

Status CodeDescription
200Success
201Created successfully
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API key
402Payment Required - Insufficient credits
403Forbidden - Enterprise plan required or unauthorized access
404Not Found - Resource doesn’t exist
409Conflict - Resource already exists
429Too Many Requests - Rate limit exceeded
500Internal Server Error

Common Error Codes

Authentication Errors

Status: 401
Cause: API key is invalid, expired, or malformed
Solution: Check your API key format and regenerate if necessary
Status: 403
Cause: Enterprise plan required for API access
Solution: Upgrade to Enterprise plan

Rate Limiting Errors

Status: 429
Cause: Too many requests in a short period
Solution: Implement exponential backoff and respect rate limits

Validation Errors

Status: 400
Cause: No prompt, script, voice_url, or avatar_url provided
Solution: Provide at least one content parameter
Status: 400
Cause: Script provided but no voice specified
Solution: Add voice_id or voice_url when using script
Status: 400
Cause: Specified voice_id not found
Solution: Use GET /resources/voices to get valid voice IDs
Status: 400
Cause: Specified avatar_id not found
Solution: Use GET /resources/avatars to get valid avatar IDs
Status: 400
Cause: Invalid video format specified
Solution: Use ‘vertical’, ‘square’, or ‘ads’

Resource Errors

Status: 402
Cause: Not enough credits for the operation
Solution: Purchase more credits or reduce resource usage
Status: 404
Cause: Job ID doesn’t exist
Solution: Verify the job_id is correct
Status: 403
Cause: Job doesn’t belong to your workspace
Solution: Only access jobs created by your API key
Status: 404
Cause: Video ID doesn’t exist
Solution: Verify the video_id is correct

Error Handling Best Practices

1. Always Check Status Codes

const response = await fetch('https://app.hoox.video/api/public/v1/generation/start', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer hx_live_your_api_key_here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(requestData)
});

if (!response.ok) {
  const error = await response.json();
  console.error('API Error:', error);
  
  // Handle specific error codes
  if (error.details?.[0]?.code === 'insufficient_credits') {
    // Redirect to billing page
  } else if (error.details?.[0]?.code === 'rate_limit_exceeded') {
    // Implement retry with backoff
  }
  
  throw new Error(`API Error: ${error.error}`);
}

2. Implement Retry Logic

async function callApiWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 429) {
        // Rate limited - wait before retry
        const resetTime = response.headers.get('X-RateLimit-Reset');
        const waitTime = resetTime ? (parseInt(resetTime) * 1000) - Date.now() : 1000 * attempt;
        
        if (attempt < maxRetries) {
          await new Promise(resolve => setTimeout(resolve, Math.max(waitTime, 0)));
          continue;
        }
      }
      
      if (!response.ok) {
        const error = await response.json();
        throw new Error(`API Error: ${error.error}`);
      }
      
      return response;
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      // Exponential backoff for other errors
      await new Promise(resolve => 
        setTimeout(resolve, 1000 * Math.pow(2, attempt - 1))
      );
    }
  }
}

3. Handle Validation Errors

function handleValidationErrors(errorResponse) {
  const errors = errorResponse.details || [];
  const fieldErrors = {};
  
  errors.forEach(error => {
    if (error.field) {
      fieldErrors[error.field] = error.message;
    }
  });
  
  return fieldErrors;
}

// Usage
try {
  const response = await fetch(apiUrl, options);
  if (!response.ok) {
    const error = await response.json();
    
    if (response.status === 400) {
      const fieldErrors = handleValidationErrors(error);
      // Update UI to show field-specific errors
      console.log('Validation errors:', fieldErrors);
    }
  }
} catch (error) {
  console.error('Request failed:', error);
}

4. Monitor Rate Limits

function checkRateLimits(response) {
  const limit = response.headers.get('X-RateLimit-Limit');
  const remaining = response.headers.get('X-RateLimit-Remaining');
  const reset = response.headers.get('X-RateLimit-Reset');
  
  console.log(`Rate limit: ${remaining}/${limit}, resets at ${new Date(reset * 1000)}`);
  
  // Warn when approaching limit
  if (parseInt(remaining) < 10) {
    console.warn('Approaching rate limit!');
  }
}

Webhook Error Handling

When using webhooks, you may receive error notifications:
{
  "job_id": "run_01234567890abcdef",
  "status": "failed",
  "error": {
    "code": "generation_failed",
    "message": "Video generation failed due to insufficient credits"
  }
}
Handle webhook errors in your endpoint:
app.post('/webhook/hoox', (req, res) => {
  const { job_id, status, error, result } = req.body;
  
  if (status === 'failed') {
    console.error(`Job ${job_id} failed:`, error);
    
    // Handle specific error codes
    switch (error.code) {
      case 'insufficient_credits':
        // Notify user about credit shortage
        break;
      case 'generation_failed':
        // Log for investigation
        break;
      default:
        // Generic error handling
    }
  } else if (status === 'completed') {
    // Handle successful completion
    console.log(`Job ${job_id} completed:`, result);
  }
  
  res.status(200).send('OK');
});
Always implement proper error handling and logging in production applications to diagnose issues quickly.
I