Skip to content
Last updated

API Errors

Understand error responses and handle them properly in your integration.

Error Response Format

All errors follow a consistent format:

{
  "success": false,
  "error": {
    "message": "Human-readable error message",
    "details": {}
  }
}

Error Fields

FieldTypeDescription
successbooleanAlways false for errors
error.messagestringHuman-readable error description
error.detailsobjectAdditional error information (optional)

HTTP Status Codes

The following table describes all the possible HTTP error codes:

CodeNameDescription
200OKRequest succeeded
201CreatedResource created successfully
400Bad RequestInvalid request parameters or validation error
401UnauthorizedMissing or invalid API key
404Not FoundResource not found
5XXServer ErrorAn error occurred on the NovaMed API

Common Error Scenarios

400 Bad Request

Returned when request validation fails:

{
  "success": false,
  "error": {
    "message": "Clinic ID must be a valid UUID."
  }
}

Common causes:

  • Missing required fields
  • Invalid field formats (UUID, email, etc.)
  • Invalid clinic ID
  • Invalid practitioner or patient ID

Example - Clinic not found:

{
  "success": false,
  "error": {
    "message": "Clinic not found"
  }
}

401 Unauthorized

Returned when authentication fails:

{
  "success": false,
  "error": {
    "message": "Unauthorized. This can happen if the access token is invalid, expired or has been revoked"
  }
}

Solutions:

  • Verify the x-api-key header is present
  • Check that the API key is valid
  • Ensure you're using the correct environment

404 Not Found

Returned when a resource doesn't exist:

{
  "success": false,
  "error": {
    "message": "Resource not found"
  }
}

Common causes:

  • Invalid resource ID
  • Resource was deleted
  • Wrong environment

Refill-Specific Errors

{
  "success": false,
  "error": {
    "message": "Medication request not found"
  }
}
{
  "success": false,
  "error": {
    "message": "Refills are not possible for pending medication requests"
  }
}
{
  "success": false,
  "error": {
    "message": "Refill request already exists"
  }
}

Error Handling Best Practices

1. Check Response Status

Always check the success field in responses:

import requests

response = requests.post(url, headers=headers, json=data)
result = response.json()

if result.get('success'):
    # Handle success
    data = result.get('data')
else:
    # Handle error
    error_message = result.get('error', {}).get('message')
    print(f"Error: {error_message}")

2. Handle Different Error Types

def handle_api_error(response):
    result = response.json()
    
    if response.status_code == 400:
        # Validation error - check your request
        raise ValidationError(result['error']['message'])
    
    elif response.status_code == 401:
        # Authentication error - check API key
        raise AuthenticationError("Invalid API key")
    
    elif response.status_code == 404:
        # Resource not found
        raise NotFoundError(result['error']['message'])
    
    elif response.status_code >= 500:
        # Server error - retry with backoff
        raise ServerError("NovaMed API error, please retry")

3. Implement Retry Logic

For server errors (5XX), implement retry with exponential backoff:

import time

def retry_with_backoff(func, max_retries=3):
    for attempt in range(max_retries):
        try:
            return func()
        except ServerError as e:
            if attempt == max_retries - 1:
                raise
            
            wait_time = 2 ** attempt  # 1s, 2s, 4s
            print(f"Retrying in {wait_time}s...")
            time.sleep(wait_time)

4. Log Errors for Debugging

import logging

logger = logging.getLogger(__name__)

def make_api_request(endpoint, data):
    try:
        response = requests.post(endpoint, json=data, headers=headers)
        result = response.json()
        
        if not result.get('success'):
            logger.error(f"API Error: {result.get('error')}")
            logger.error(f"Request Data: {data}")
        
        return result
    
    except Exception as e:
        logger.exception(f"Request failed: {e}")
        raise

Idempotency

For operations that create resources, ensure idempotency by:

  1. Using unique identifiers: Generate unique IDs on your side before creating resources
  2. Checking for existing resources: Before creating, check if a resource already exists
  3. Handling duplicates gracefully: If a resource already exists, return the existing one

Example: Preventing Duplicate Refill Requests

def request_refill(medication_request_id):
    """
    Request a refill, handling the case where one already exists.
    """
    response = requests.post(
        f"{BASE_URL}/api/external/refill-request",
        headers=headers,
        json={"medication_request_id": medication_request_id}
    )
    
    result = response.json()
    
    if result.get('success'):
        return result['data']
    
    # Check if refill already exists
    if "already exists" in result.get('error', {}).get('message', ''):
        # Refill was already requested - this is OK
        return {"status": "already_requested"}
    
    # Other error
    raise RefillError(result['error']['message'])

Error Handling Examples

Python

import requests

BASE_URL = "https://novamed-feapidev.stackmod.info"

def create_practitioner(practitioner_data):
    """Create a practitioner with proper error handling."""
    
    response = requests.post(
        f"{BASE_URL}/api/external/practitioner",
        headers={
            "x-api-key": API_KEY,
            "Content-Type": "application/json",
            "Accept": "application/json"
        },
        json=practitioner_data
    )
    
    result = response.json()
    
    if result.get('success'):
        return result['data']
    
    error_message = result.get('error', {}).get('message', 'Unknown error')
    
    if response.status_code == 400:
        raise ValueError(f"Validation error: {error_message}")
    elif response.status_code == 401:
        raise PermissionError("Invalid API key")
    elif response.status_code == 404:
        raise LookupError(error_message)
    else:
        raise Exception(f"API error: {error_message}")

Node.js

const axios = require('axios');

const BASE_URL = 'https://novamed-feapidev.stackmod.info';

async function createPractitioner(practitionerData) {
  try {
    const response = await axios.post(
      `${BASE_URL}/api/external/practitioner`,
      practitionerData,
      {
        headers: {
          'x-api-key': process.env.NOVAMED_API_KEY,
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      }
    );
    
    if (response.data.success) {
      return response.data.data;
    }
    
    throw new Error(response.data.error?.message || 'Unknown error');
    
  } catch (error) {
    if (error.response) {
      const status = error.response.status;
      const message = error.response.data?.error?.message;
      
      if (status === 400) {
        throw new Error(`Validation error: ${message}`);
      } else if (status === 401) {
        throw new Error('Invalid API key');
      } else if (status === 404) {
        throw new Error(`Not found: ${message}`);
      }
    }
    
    throw error;
  }
}

Next Steps