Skip to content

Error Handling

This guide explains how to handle errors returned by the TopTickets API.

Error Response Format

All errors return a JSON object with a detail field:

{
  "detail": "Error message describing what went wrong"
}

For validation errors, additional details may be included:

{
  "detail": [
    {
      "loc": ["body", "email"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

HTTP Status Codes

400 Bad Request

The request body or parameters are invalid.

Common causes:

  • Missing required fields
  • Invalid field values
  • Malformed JSON

Example:

{
  "detail": [
    {
      "loc": ["body", "priority"],
      "msg": "value is not a valid enumeration member; permitted: 'low', 'medium', 'high', 'urgent'",
      "type": "type_error.enum"
    }
  ]
}

Solution: Check your request body matches the expected schema.


401 Unauthorized

Authentication failed.

Common causes:

  • Missing Authorization header
  • Invalid API key
  • Expired API key
  • Revoked API key

Example:

{
  "detail": "Invalid API key"
}

Solution:

  1. Verify your API key is correct
  2. Check if the key has expired
  3. Ensure the key hasn't been revoked
  4. Confirm the Authorization header format: Bearer YOUR_API_KEY

403 Forbidden

Authentication succeeded, but you lack permission.

Common causes:

  • API key missing required scope
  • User role doesn't permit this action
  • IP address not in allowlist

Example:

{
  "detail": "Insufficient permissions. Required scope: tickets:write"
}

Solution:

  1. Check the endpoint's required scope in the API Reference
  2. Create a new API key with the required scope
  3. If using IP restrictions, verify your IP is allowed

404 Not Found

The requested resource doesn't exist.

Common causes:

  • Invalid resource ID
  • Resource was deleted
  • Typo in the URL path

Example:

{
  "detail": "Ticket not found"
}

Solution:

  1. Verify the resource ID is correct
  2. Check if the resource still exists
  3. Ensure you're using the correct endpoint path

422 Unprocessable Entity

The request was well-formed but contains invalid data.

Common causes:

  • Validation constraint violated
  • Business rule violation
  • Invalid enum value

Example:

{
  "detail": [
    {
      "loc": ["body", "subject"],
      "msg": "ensure this value has at least 1 characters",
      "type": "value_error.any_str.min_length"
    }
  ]
}

Solution: Review the validation error details and fix the invalid fields.


429 Too Many Requests

You've exceeded the rate limit.

Example:

{
  "detail": "Rate limit exceeded. Try again in 30 seconds."
}

Solution:

  1. Wait before retrying (see Rate Limits)
  2. Implement exponential backoff
  3. Cache responses where possible
  4. Consider upgrading to a higher-limit API key

500 Internal Server Error

An unexpected server error occurred.

Example:

{
  "detail": "Internal server error"
}

Solution:

  1. Retry the request after a brief delay
  2. If persistent, contact support with request details

Handling Errors in Code

Python Example

import requests

def make_api_request(method, endpoint, **kwargs):
    """Make an API request with error handling."""
    base_url = "https://api.toptickets.app/v1"
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    }

    response = requests.request(
        method,
        f"{base_url}{endpoint}",
        headers=headers,
        **kwargs
    )

    # Handle specific error codes
    if response.status_code == 401:
        raise AuthenticationError("Invalid or expired API key")
    elif response.status_code == 403:
        raise PermissionError("Insufficient permissions for this operation")
    elif response.status_code == 404:
        raise NotFoundError("Resource not found")
    elif response.status_code == 429:
        retry_after = response.headers.get("Retry-After", 60)
        raise RateLimitError(f"Rate limited. Retry after {retry_after} seconds")
    elif response.status_code >= 400:
        detail = response.json().get("detail", "Unknown error")
        raise APIError(f"API error: {detail}")

    return response.json()


# Usage
try:
    tickets = make_api_request("GET", "/tickets")
except AuthenticationError:
    print("Check your API key")
except RateLimitError as e:
    print(f"Slow down: {e}")
except APIError as e:
    print(f"Request failed: {e}")

Retry with Exponential Backoff

import time
import requests

def request_with_retry(method, url, max_retries=3, **kwargs):
    """Make request with exponential backoff on rate limits."""
    for attempt in range(max_retries):
        response = requests.request(method, url, **kwargs)

        if response.status_code == 429:
            # Exponential backoff: 1s, 2s, 4s
            wait_time = 2 ** attempt
            print(f"Rate limited. Waiting {wait_time}s before retry...")
            time.sleep(wait_time)
            continue

        return response

    raise Exception("Max retries exceeded")

Best Practices

1. Always Check Status Codes

Never assume a request succeeded. Check the HTTP status code before processing the response.

2. Log Error Details

Log the full error response for debugging:

if not response.ok:
    print(f"Error {response.status_code}: {response.text}")

3. Handle Network Errors

Wrap requests in try/except to catch network issues:

try:
    response = requests.get(url, timeout=30)
except requests.exceptions.Timeout:
    print("Request timed out")
except requests.exceptions.ConnectionError:
    print("Connection failed")

4. Use Idempotency for Retries

When retrying POST requests, be aware that you might create duplicate resources. Design your logic to handle this.

5. Graceful Degradation

If the API is unavailable, have fallback behavior in your application rather than crashing.

Common Error Scenarios

Creating a Ticket with Invalid Priority

Request:

{
  "customer_name": "John Doe",
  "customer_email": "john@example.com",
  "subject": "Help needed",
  "description": "Issue description",
  "priority": "critical"
}

Response (422):

{
  "detail": [
    {
      "loc": ["body", "priority"],
      "msg": "value is not a valid enumeration member; permitted: 'low', 'medium', 'high', 'urgent'",
      "type": "type_error.enum"
    }
  ]
}

Fix: Use urgent instead of critical.


Missing Required Scope

Request:

curl -X POST "https://api.toptickets.app/v1/tickets" \
  -H "Authorization: Bearer tt_ro_readonly_key..."

Response (403):

{
  "detail": "Insufficient permissions. Required scope: tickets:write"
}

Fix: Use an API key with tickets:write scope.


Accessing Deleted Resource

Request:

curl "https://api.toptickets.app/v1/tickets/deleted-uuid"

Response (404):

{
  "detail": "Ticket not found"
}

Fix: The ticket was deleted or doesn't exist. Check your application's cache.