Skip to main content
The HopX API uses conventional HTTP status codes and returns detailed error responses to help you troubleshoot issues.

Error Response Format

All errors return a JSON response with this structure:
{
  "error": "Error message describing what went wrong",
  "code": "ERROR_CODE",
  "request_id": "req_abc123"
}
FieldTypeDescription
errorstringHuman-readable error message
codestringMachine-readable error code
request_idstringRequest ID for support/debugging

HTTP Status Codes

CodeMeaningDescription
200OKRequest succeeded
202AcceptedRequest accepted (async operation)
204No ContentRequest succeeded, no response body
400Bad RequestInvalid request parameters
401UnauthorizedAuthentication failed or missing
403ForbiddenAccess denied
404Not FoundResource not found
408Request TimeoutRequest exceeded timeout
409ConflictResource conflict (e.g., already exists)
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error
503Service UnavailableService temporarily unavailable

Error Codes

Authentication Errors

AUTHENTICATION_REQUIRED (401)

{
  "error": "Authentication required",
  "code": "AUTHENTICATION_REQUIRED",
  "request_id": "req_abc123"
}
Cause: No API key or JWT token provided. Fix: Include Authorization: Bearer $HOPX_API_KEY header.

INVALID_TOKEN (401)

{
  "error": "Invalid or expired token",
  "code": "INVALID_TOKEN",
  "request_id": "req_abc123"
}
Cause: JWT token is invalid or expired. Fix: Refresh the JWT token using the Control Plane API.

Request Errors

INVALID_REQUEST (400)

{
  "error": "Invalid request: missing required field 'code'",
  "code": "INVALID_REQUEST",
  "request_id": "req_abc123"
}
Cause: Missing required parameters or invalid request format. Fix: Check the request body and ensure all required fields are present.

RESOURCE_NOT_FOUND (404)

{
  "error": "Sandbox not found",
  "code": "RESOURCE_NOT_FOUND",
  "request_id": "req_abc123"
}
Cause: The requested resource doesn’t exist. Fix: Verify the resource ID is correct.

CONFLICT (409)

{
  "error": "Template already exists. Set update=true to update it.",
  "code": "CONFLICT",
  "request_id": "req_abc123"
}
Cause: Resource already exists. Fix: Use a different name or set update=true.

Execution Errors

EXECUTION_TIMEOUT (408)

{
  "error": "Execution timeout after 60 seconds",
  "code": "EXECUTION_TIMEOUT",
  "request_id": "req_abc123"
}
Cause: Code execution exceeded the timeout limit. Fix: Increase the timeout or optimize your code.

CODE_EXECUTION_ERROR (500)

{
  "success": false,
  "stdout": "",
  "stderr": "NameError: name 'x' is not defined\n",
  "exit_code": 1,
  "execution_time": 0.05
}
Cause: Code execution failed (syntax error, runtime error, etc.). Fix: Check the stderr field for error details and fix your code.

Resource Errors

PAYMENT_REQUIRED (402)

{
  "error": "Payment required: credit limit exceeded",
  "code": "PAYMENT_REQUIRED",
  "request_id": "req_abc123"
}
Cause: Account credit limit reached or payment method required. Fix: Add payment method or increase credit limit.

RESOURCE_LIMIT_ERROR (429)

{
  "error": "Sandbox limit reached (10/10)",
  "code": "RESOURCE_LIMIT_ERROR",
  "request_id": "req_abc123"
}
Cause: Account resource limit reached. Fix: Delete unused sandboxes or upgrade your plan.

FORBIDDEN (403)

{
  "error": "Path not allowed: /etc/passwd",
  "code": "FORBIDDEN",
  "request_id": "req_abc123"
}
Cause: Access to resource or path is forbidden. Fix: Only access allowed paths (e.g., /workspace, /tmp).

Rate Limiting

RATE_LIMIT_EXCEEDED (429)

{
  "error": "Rate limit exceeded: 100 requests per minute",
  "code": "RATE_LIMIT_EXCEEDED",
  "request_id": "req_abc123",
  "retry_after": 30
}
Cause: Too many requests in a short time. Fix: Wait and retry. Use exponential backoff. See Rate Limits for details.

Service Errors

SERVICE_UNAVAILABLE (503)

{
  "error": "Service temporarily unavailable",
  "code": "SERVICE_UNAVAILABLE",
  "request_id": "req_abc123"
}
Cause: Service is temporarily down or overloaded. Fix: Retry with exponential backoff.

INTERNAL_ERROR (500)

{
  "error": "Internal server error",
  "code": "INTERNAL_ERROR",
  "request_id": "req_abc123"
}
Cause: Unexpected server error. Fix: Retry the request. Contact support with request_id if issue persists.

Error Handling Best Practices

1. Check Status Codes

RESPONSE=$(curl -s -w "\n%{http_code}" https://api.hopx.dev/v1/sandboxes \
  -H "Authorization: Bearer $HOPX_API_KEY")

HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | sed '$d')

if [ "$HTTP_CODE" -ge 400 ]; then
  echo "Error: $BODY"
  exit 1
fi

2. Parse Error Responses

import requests

response = requests.post(
    "https://api.hopx.dev/v1/sandboxes",
    headers={"Authorization": "Bearer $HOPX_API_KEY"},
    json={"template_id": "code-interpreter"}
)

if response.status_code >= 400:
    error = response.json()
    print(f"Error: {error['error']}")
    print(f"Code: {error['code']}")
    print(f"Request ID: {error['request_id']}")
    exit(1)

3. Implement Retry Logic

import time
import requests

def create_sandbox_with_retry(max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.post(
                "https://api.hopx.dev/v1/sandboxes",
                headers={"Authorization": "Bearer $HOPX_API_KEY"},
                json={"template_id": "code-interpreter"},
                timeout=30
            )
            
            if response.status_code == 200:
                return response.json()
            
            # Retry on 5xx errors or rate limits
            if response.status_code >= 500 or response.status_code == 429:
                wait_time = 2 ** attempt  # Exponential backoff
                print(f"Retry {attempt + 1}/{max_retries} after {wait_time}s")
                time.sleep(wait_time)
                continue
            
            # Don't retry on 4xx errors (except 429)
            response.raise_for_status()
            
        except requests.exceptions.RequestException as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)
    
    raise Exception("Max retries exceeded")

4. Handle Specific Errors

response = requests.post(url, headers=headers, json=payload)

if response.status_code == 401:
    # Refresh token and retry
    refresh_token()
    response = requests.post(url, headers=headers, json=payload)
elif response.status_code == 404:
    # Resource not found - create it
    create_resource()
elif response.status_code == 429:
    # Rate limited - wait and retry
    time.sleep(60)
    response = requests.post(url, headers=headers, json=payload)

Getting Support

When contacting support, always include:
  1. Request ID - From the error response
  2. Timestamp - When the error occurred
  3. API endpoint - The URL you called
  4. HTTP status code - The response status
  5. Error message - The full error response
Example support request:
Request ID: req_abc123
Timestamp: 2025-01-28T00:00:00Z
Endpoint: POST /v1/sandboxes
Status: 500
Error: Internal server error

Next Steps