Skip to main content

Error Handling

The Turris Public API uses conventional HTTP response codes and returns detailed error information to help you handle issues gracefully.

HTTP Status Codes

Status CodeMeaning
200Success - Request completed successfully
201Created - Resource was created successfully
400Bad Request - Invalid request parameters
401Unauthorized - Missing or invalid authentication
403Forbidden - Valid auth but insufficient permissions
404Not Found - Resource doesn’t exist
422Unprocessable Entity - Validation failed
429Too Many Requests - Rate limit exceeded
500Internal Server Error - Something went wrong on our end

Error Response Format

All error responses follow a consistent format:
{
  "statusCode": 400,
  "requestId": "dev-63c50377-1cfa-4d51-bce7-d187507853db",
  "errorType": "invalid_input",
  "errorMessage": ["Field 'npn' is required"],
  "timestamp": "2025-01-30T09:58:12.488Z"
}

Response Fields

FieldTypeDescription
statusCodenumberHTTP status code
requestIdstringUnique identifier for this request (useful for support)
errorTypestringCategory of the error
errorMessagestring[]Array of human-readable error messages
timestampstringISO 8601 timestamp of when the error occurred

Error Types

unauthorized

Authentication failed or was not provided.
{
  "statusCode": 401,
  "errorType": "unauthorized",
  "errorMessage": ["Authentication token not provided"]
}
Common causes:
  • Missing Authorization header
  • Expired JWT token
  • Invalid token format

forbidden

Authentication succeeded but the request is not allowed.
{
  "statusCode": 403,
  "errorType": "forbidden",
  "errorMessage": ["IP address \"192.168.1.1\" not in allowed list for token \"***-a5ed\""]
}
Common causes:
  • IP not in allowlist (for Restricted Access Tokens)
  • Insufficient permissions for the requested resource

invalid_input

Request validation failed.
{
  "statusCode": 400,
  "errorType": "invalid_input",
  "errorMessage": [
    "npn must be a string",
    "stateCode must be a valid US state code"
  ]
}
Common causes:
  • Missing required fields
  • Invalid field formats
  • Mutually exclusive parameters provided together

not_found

The requested resource doesn’t exist.
{
  "statusCode": 404,
  "errorType": "not_found",
  "errorMessage": ["Agent with ID '507f1f77bcf86cd799439011' not found"]
}

internal_error

Something went wrong on our servers.
{
  "statusCode": 500,
  "errorType": "internal_error",
  "errorMessage": ["An unexpected error occurred"]
}
If you receive a 500 error, please contact support with the requestId for investigation.

Handling Errors

Example: JavaScript/TypeScript

async function fetchAgents() {
  try {
    const response = await fetch(
      'https://public.api.live.turrisfi.com/v1/agents',
      {
        headers: {
          'Authorization': `Bearer ${accessToken}`
        }
      }
    );

    if (!response.ok) {
      const error = await response.json();
      
      switch (error.statusCode) {
        case 401:
          // Token expired - refresh and retry
          await refreshToken();
          return fetchAgents();
        case 429:
          // Rate limited - wait and retry
          await sleep(60000);
          return fetchAgents();
        case 400:
          // Bad request - log and don't retry
          console.error('Validation error:', error.errorMessage);
          throw new Error(error.errorMessage.join(', '));
        default:
          throw new Error(`API error: ${error.errorMessage.join(', ')}`);
      }
    }

    return response.json();
  } catch (error) {
    console.error('Request failed:', error);
    throw error;
  }
}

Example: Python

import requests
import time

def fetch_agents(access_token: str, retry_count: int = 0):
    try:
        response = requests.get(
            'https://public.api.live.turrisfi.com/v1/agents',
            headers={'Authorization': f'Bearer {access_token}'}
        )
        
        if response.status_code == 200:
            return response.json()
        
        error = response.json()
        
        if response.status_code == 401 and retry_count < 1:
            # Token expired - refresh and retry
            new_token = refresh_token()
            return fetch_agents(new_token, retry_count + 1)
        
        if response.status_code == 429 and retry_count < 3:
            # Rate limited - wait and retry
            time.sleep(60)
            return fetch_agents(access_token, retry_count + 1)
        
        raise Exception(f"API error: {', '.join(error['errorMessage'])}")
        
    except requests.RequestException as e:
        print(f"Request failed: {e}")
        raise

Best Practices

Don’t assume requests succeed. Check the HTTP status code and handle errors appropriately.
The requestId is essential for debugging. Log it when errors occur so you can reference it when contacting support.
For transient errors (429, 500, 503), implement exponential backoff retry logic.
OAuth tokens expire after 60 minutes. Implement proactive token refresh or handle 401 errors by refreshing and retrying.