API Reference
Error Codes

Error Handling

All API errors return a consistent JSON format with appropriate HTTP status codes.

Error Response Format

{
  "error": "error_code",
  "message": "Human-readable description of what went wrong"
}

HTTP Status Codes

CodeDescription
200Success
201Created
204No Content (successful delete)
400Bad Request - Invalid input
401Unauthorized - Missing or invalid API key
403Forbidden - Insufficient permissions
404Not Found - Resource doesn't exist
422Unprocessable Entity - Validation failed
429Too Many Requests - Rate limited
500Internal Server Error

Error Codes

Authentication Errors

CodeStatusDescription
missing_api_key401No API key provided in request
invalid_api_key401API key not found or revoked
expired_api_key401API key has expired
{
  "error": "missing_api_key",
  "message": "API key is required. Include it in the Authorization header."
}

Authorization Errors

CodeStatusDescription
forbidden403Operation not allowed
insufficient_scope403API key lacks required scope
plan_limit_exceeded403Plan quota exceeded
{
  "error": "insufficient_scope",
  "message": "This operation requires 'monitors:write' scope."
}

Validation Errors

CodeStatusDescription
invalid_request400Malformed request body
validation_failed422Field validation failed
invalid_url422URL format is invalid
{
  "error": "validation_failed",
  "message": "Validation failed",
  "details": [
    { "field": "url", "message": "Must be a valid HTTPS URL" },
    { "field": "frequency", "message": "Must be between 60 and 3600" }
  ]
}

Resource Errors

CodeStatusDescription
not_found404Resource doesn't exist
already_exists409Resource already exists
deleted410Resource was deleted
{
  "error": "not_found",
  "message": "Monitor with ID 'mon_abc123' not found"
}

Rate Limit Errors

CodeStatusDescription
rate_limited429Too many requests
{
  "error": "rate_limited",
  "message": "Rate limit exceeded. Try again in 42 seconds.",
  "retryAfter": 42
}

Server Errors

CodeStatusDescription
internal_error500Unexpected server error
service_unavailable503Service temporarily unavailable
{
  "error": "internal_error",
  "message": "An unexpected error occurred. Please try again."
}

Handling Errors

JavaScript/TypeScript

async function fetchMonitors() {
  const response = await fetch('https://statly.live/api/v1/monitors', {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });
 
  if (!response.ok) {
    const error = await response.json();
 
    switch (response.status) {
      case 401:
        throw new Error('Invalid API key');
      case 403:
        throw new Error(`Permission denied: ${error.message}`);
      case 429:
        // Wait and retry
        await sleep(error.retryAfter * 1000);
        return fetchMonitors();
      default:
        throw new Error(error.message);
    }
  }
 
  return response.json();
}

Python

import requests
import time
 
def fetch_monitors():
    response = requests.get(
        'https://statly.live/api/v1/monitors',
        headers={'Authorization': f'Bearer {api_key}'}
    )
 
    if response.status_code == 429:
        retry_after = response.json().get('retryAfter', 60)
        time.sleep(retry_after)
        return fetch_monitors()
 
    response.raise_for_status()
    return response.json()

Go

func fetchMonitors() ([]Monitor, error) {
    resp, err := http.Get("https://statly.live/api/v1/monitors")
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
 
    if resp.StatusCode == 429 {
        var apiErr APIError
        json.NewDecoder(resp.Body).Decode(&apiErr)
        time.Sleep(time.Duration(apiErr.RetryAfter) * time.Second)
        return fetchMonitors()
    }
 
    if resp.StatusCode != 200 {
        var apiErr APIError
        json.NewDecoder(resp.Body).Decode(&apiErr)
        return nil, fmt.Errorf("%s: %s", apiErr.Error, apiErr.Message)
    }
 
    var monitors []Monitor
    json.NewDecoder(resp.Body).Decode(&monitors)
    return monitors, nil
}

Best Practices

  1. Always check status codes before parsing response body
  2. Log error codes for debugging and monitoring
  3. Implement retry logic for 429 and 5xx errors
  4. Use exponential backoff to avoid overwhelming the API
  5. Handle specific errors differently (auth vs validation vs rate limit)