Skip to main content

Error Handling

HITL.sh APIs use conventional HTTP status codes and provide detailed error messages to help you debug issues quickly. All errors follow a consistent format for easy parsing and handling.

Error Response Format

All API errors return a JSON response with the following structure:
{
  "error": true,
  "msg": "Human-readable error description",
  "data": {
    // Additional error details (optional)
  }
}

Error Response Fields

error
boolean
Always true for error responses
msg
string
Human-readable error message describing what went wrong
data
object
Additional error context, validation details, or debugging information (optional)

HTTP Status Codes

2xx Success

Request succeeded. Response contains the requested data.
{
  "error": false,
  "msg": "Operation completed successfully",
  "data": { /* response data */ }
}
Resource was created successfully.
{
  "error": false,
  "msg": "Loop created successfully",
  "data": { /* created resource */ }
}

4xx Client Errors

Request data is invalid or malformed.Common causes:
  • Missing required fields
  • Invalid field values
  • Malformed JSON
  • Validation failures
{
  "error": true,
  "msg": "Validation failed",
  "data": "timeout_seconds is required for time-sensitive requests"
}
Example - Missing required field:
{
  "error": true,
  "msg": "Invalid request body",
  "data": {
    "field": "name",
    "issue": "Field is required"
  }
}
Authentication is missing or invalid.Common causes:
  • Missing API key
  • Invalid API key
  • Malformed authorization header
{
  "error": true,
  "msg": "Invalid API key"
}
Authentication is valid but access is denied.Common causes:
  • Insufficient permissions
  • Not the resource owner
  • Account limitations
{
  "error": true,
  "msg": "Access denied to this loop"
}
Permission-specific error:
{
  "error": true,
  "msg": "Only loop creators can create requests"
}
The requested resource doesn’t exist.Common causes:
  • Invalid resource ID
  • Resource was deleted
  • Typo in endpoint URL
{
  "error": true,
  "msg": "Loop not found"
}
Request not found:
{
  "error": true,
  "msg": "Request not found"
}
Rate limit has been exceeded.API key rate limit:
{
  "error": true,
  "msg": "API key request limit exceeded",
  "data": {
    "usage_count": 100,
    "usage_limit": 100,
    "remaining": 0,
    "reset_at": "2024-03-15T11:00:00Z"
  }
}

5xx Server Errors

An unexpected error occurred on our servers.
{
  "error": true,
  "msg": "Internal server error"
}
What to do:
  • Retry the request after a short delay
  • Check our status page at status.hitl.sh
  • Contact support if the issue persists
Gateway or proxy error, usually temporary.
{
  "error": true,
  "msg": "Service temporarily unavailable"
}
Service is temporarily unavailable, usually due to maintenance.
{
  "error": true,
  "msg": "Service temporarily unavailable"
}

Common Error Scenarios

Validation Errors

Request Text Too Long:
{
  "error": true,
  "msg": "Validation failed",
  "data": "request_text must be between 1 and 2000 characters"
}
Invalid Response Configuration:
{
  "error": true,
  "msg": "Invalid response configuration",
  "data": "options array required for select response type"
}
Invalid Enum Value:
{
  "error": true,
  "msg": "Validation failed",
  "data": "priority must be one of: low, medium, high, critical"
}

Resource Access Errors

Loop Not Found:
{
  "error": true,
  "msg": "Loop not found"
}
Request Already Cancelled:
{
  "error": true,
  "msg": "Request cannot be cancelled in current state"
}
No Active Members:
{
  "error": true,
  "msg": "No active members found in the loop"
}

Authentication Errors

Missing API Key:
{
  "error": true,
  "msg": "API key required"
}
Invalid API Key Format:
{
  "error": true,
  "msg": "Invalid API key format"
}
Expired Session:
{
  "error": true,
  "msg": "Session has expired. Please log in again."
}

Error Handling Best Practices

1. Implement Retry Logic

Use exponential backoff for transient errors:
import time
import random
import requests

def make_request_with_retry(url, headers, data=None, max_retries=3):
    retryable_status_codes = [429, 500, 502, 503, 504]
    
    for attempt in range(max_retries):
        try:
            if data:
                response = requests.post(url, headers=headers, json=data)
            else:
                response = requests.get(url, headers=headers)
            
            if response.status_code not in retryable_status_codes:
                return response
            
            if attempt < max_retries - 1:  # Don't delay on last attempt
                # Exponential backoff with jitter
                delay = (2 ** attempt) + random.uniform(0, 1)
                time.sleep(delay)
                
        except requests.exceptions.RequestException as e:
            if attempt == max_retries - 1:
                raise e
            time.sleep(2 ** attempt)
    
    return response

2. Handle Rate Limits Gracefully

import time
import requests

class HITLAPIClient:
    def __init__(self, api_key):
        self.api_key = api_key
        self.base_url = "https://api.hitl.sh/v1"
        
    def make_request(self, method, endpoint, data=None):
        url = f"{self.base_url}{endpoint}"
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        response = requests.request(method, url, headers=headers, json=data)
        
        if response.status_code == 429:
            # Extract reset time from response
            reset_time = response.headers.get('X-RateLimit-Reset')
            if reset_time:
                wait_time = int(reset_time) - int(time.time())
                if wait_time > 0:
                    print(f"Rate limited. Waiting {wait_time} seconds...")
                    time.sleep(wait_time)
                    # Retry the request
                    return self.make_request(method, endpoint, data)
        
        return response

3. Validate Requests Client-Side

Implement client-side validation to catch errors early:
def validate_create_request_payload(payload):
    """Validate request payload before sending to API"""
    errors = []
    
    # Required fields
    required_fields = ['processing_type', 'type', 'priority', 'request_text', 
                      'response_type', 'response_config', 'default_response', 'platform']
    
    for field in required_fields:
        if field not in payload or not payload[field]:
            errors.append(f"{field} is required")
    
    # Enum validations
    if 'processing_type' in payload:
        valid_processing_types = ['time-sensitive', 'deferred']
        if payload['processing_type'] not in valid_processing_types:
            errors.append(f"processing_type must be one of: {', '.join(valid_processing_types)}")
    
    if 'priority' in payload:
        valid_priorities = ['low', 'medium', 'high', 'critical']
        if payload['priority'] not in valid_priorities:
            errors.append(f"priority must be one of: {', '.join(valid_priorities)}")
    
    # Custom validations
    if payload.get('processing_type') == 'time-sensitive' and 'timeout_seconds' not in payload:
        errors.append("timeout_seconds is required for time-sensitive requests")
    
    if 'timeout_seconds' in payload:
        timeout = payload['timeout_seconds']
        if not isinstance(timeout, int) or timeout < 60 or timeout > 86400:
            errors.append("timeout_seconds must be between 60 and 86400")
    
    return errors

4. Log Errors for Debugging

Implement comprehensive error logging:
import logging
import json

logger = logging.getLogger(__name__)

def log_api_error(response, endpoint, payload=None):
    """Log API errors with context for debugging"""
    try:
        error_data = response.json()
    except:
        error_data = {"msg": "Failed to parse error response"}
    
    log_entry = {
        "endpoint": endpoint,
        "status_code": response.status_code,
        "error_message": error_data.get("msg", "Unknown error"),
        "error_data": error_data.get("data"),
        "request_payload": payload,
        "response_headers": dict(response.headers)
    }
    
    logger.error(f"API Error: {json.dumps(log_entry, indent=2)}")
    
    return log_entry

# Usage
response = make_api_request(url, payload)
if response.status_code >= 400:
    log_api_error(response, endpoint, payload)

Debugging Guide

Common Issues and Solutions

Symptoms: Getting 401 Unauthorized errorsDebugging steps:
  1. Verify API key is correct (no extra spaces)
  2. Check header format: Authorization: Bearer your_key_here
  3. Ensure key hasn’t been revoked in dashboard
  4. Try generating a new API key
# Test API key
curl -v -H "Authorization: Bearer your_api_key" https://api.hitl.sh/v1/api/loops
Symptoms: Getting 400 Bad Request with validation errorsDebugging steps:
  1. Check required fields are present
  2. Verify enum values are correct
  3. Validate field types and formats
  4. Check field length constraints
# Debug validation
import json

payload = {
    "name": "Test Loop",
    "icon": "test"
}

print("Payload:", json.dumps(payload, indent=2))

# Check against API requirements
required_fields = ["name", "icon"]
for field in required_fields:
    if field not in payload:
        print(f"Missing required field: {field}")
Symptoms: Getting 429 Too Many RequestsDebugging steps:
  1. Check rate limit headers in response
  2. Implement exponential backoff
  3. Consider upgrading API tier
  4. Cache responses where possible
# Check rate limit status
curl -I -H "Authorization: Bearer your_api_key" https://api.hitl.sh/v1/api/loops

# Look for these headers:
# X-RateLimit-Limit: 100
# X-RateLimit-Remaining: 0
# X-RateLimit-Reset: 1642237200
Symptoms: Requests timing out or 504 errorsDebugging steps:
  1. Check our status page: status.hitl.sh
  2. Increase request timeout in your client
  3. Try the request again after a delay
  4. Contact support if issue persists
# Increase timeout
import requests

response = requests.get(
    url, 
    headers=headers, 
    timeout=30  # 30 second timeout
)

Request/Response Debugging

Enable verbose logging to see full HTTP requests and responses:
# Use -v flag for verbose output
curl -v -H "Authorization: Bearer your_api_key" \
     -H "Content-Type: application/json" \
     -d '{"name": "Test Loop", "icon": "test"}' \
     https://api.hitl.sh/v1/api/loops

Getting Help

Self-Service Resources

Contacting Support

When contacting support, please include:
  1. Request ID (if available from response headers)
  2. Timestamp of when the error occurred
  3. Full error response including status code and message
  4. Request details (endpoint, method, payload)
  5. Your API key ID (not the actual key)

Next Steps

Authentication Guide

Learn about API keys and security best practices.

Rate Limits

Understand API rate limits and optimization strategies.

Webhooks

Set up webhooks to avoid polling and reduce API calls.
I