Error Handling

This guide explains how Caret API reports errors and the best practices for handling them in your applications.

Error Response Format

When an error occurs, the Caret API returns:

  1. An appropriate HTTP status code
  2. A JSON response body with error details

All error responses have the following structure:

{
  "error": {
    "code": "error_code",
    "message": "A human-readable error message",
    "param": "The parameter that caused the error (if applicable)",
    "type": "error_type"
  }
}

Error Properties

PropertyDescription
codeA string identifier for the error
messageA human-readable description of the error
paramThe parameter that caused the error (if applicable)
typeThe type of error that occurred

Common HTTP Status Codes

Status CodeDescription
400Bad Request - The request contains invalid parameters
401Unauthorized - No valid API key provided
403Forbidden - The API key doesn’t have permission to perform the request
404Not Found - The requested resource doesn’t exist
409Conflict - The request conflicts with another request or the resource’s state
422Unprocessable Entity - The request was well-formed but contains semantic errors
429Too Many Requests - Rate limit exceeded
500Internal Server Error - Something went wrong on Caret’s end

Error Types

Authentication Errors

{
  "error": {
    "code": "invalid_api_key",
    "message": "The API key provided is invalid",
    "type": "authentication_error"
  }
}

Validation Errors

{
  "error": {
    "code": "invalid_parameter",
    "message": "The 'title' parameter must be a string",
    "param": "title",
    "type": "validation_error"
  }
}

Rate Limit Errors

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Please retry after 35 seconds.",
    "retry_after": 35,
    "type": "rate_limit_error"
  }
}

Resource Errors

{
  "error": {
    "code": "resource_not_found",
    "message": "The requested note could not be found",
    "param": "note_id",
    "type": "resource_error"
  }
}

Best Practices for Error Handling

1. Check HTTP Status Codes

Always check the HTTP status code of the response before attempting to process it. Different status codes indicate different types of errors that may require different handling strategies.

2. Parse the Error Object

Extract and log the detailed error information from the response body to help with debugging.

3. Handle Rate Limits Properly

When you receive a 429 Too Many Requests error, use the retry_after value to determine when to retry the request.

4. Implement Exponential Backoff

For transient errors (like 500 errors), implement an exponential backoff strategy to retry the request after increasing intervals.

5. Display User-Friendly Messages

Don’t expose raw API error messages to end users. Instead, translate them into more user-friendly messages for your application’s UI.

Code Examples

JavaScript

async function makeApiRequest(url, options) {
  try {
    const response = await fetch(url, options);

    if (!response.ok) {
      const errorData = await response.json();

      // Handle specific error types
      switch (response.status) {
        case 401:
          // Handle authentication errors
          console.error('Authentication failed:', errorData.error.message);
          // Redirect to login or refresh token
          break;

        case 404:
          // Handle not found errors
          console.error('Resource not found:', errorData.error.message);
          break;

        case 429:
          // Handle rate limit errors
          const retryAfter = errorData.error.retry_after || 60;
          console.error(`Rate limited. Retry after ${retryAfter} seconds`);
          // Implement retry logic
          break;

        default:
          // Handle other errors
          console.error('API error:', errorData.error.message);
      }

      throw new Error(errorData.error.message);
    }

    return await response.json();
  } catch (error) {
    // Handle network errors
    console.error('Request failed:', error.message);
    throw error;
  }
}

Python

import requests
import time

def make_api_request(url, options, max_retries=3):
    retries = 0

    while retries < max_retries:
        try:
            response = requests.request(options.get('method', 'GET'), url, **options)

            if response.ok:
                return response.json()

            error_data = response.json()
            error = error_data.get('error', {})

            # Handle specific error types
            if response.status_code == 429:
                retry_after = error.get('retry_after', 2 ** retries)
                print(f"Rate limited. Retrying after {retry_after} seconds...")
                time.sleep(retry_after)
                retries += 1
                continue

            if response.status_code >= 500:
                # Server error, retry with backoff
                backoff_time = 2 ** retries
                print(f"Server error. Retrying after {backoff_time} seconds...")
                time.sleep(backoff_time)
                retries += 1
                continue

            # Client error, don't retry
            print(f"API error: {error.get('message')}")
            raise Exception(error.get('message'))

        except requests.exceptions.RequestException as e:
            # Network error, retry with backoff
            if retries == max_retries - 1:
                raise e

            backoff_time = 2 ** retries
            print(f"Request failed: {str(e)}. Retrying after {backoff_time} seconds...")
            time.sleep(backoff_time)
            retries += 1

    raise Exception("Maximum retries reached")

Next Steps