Skip to main content

Overview

This guide covers how to handle errors and edge cases when using the Gather API. Proper error handling ensures your integration is robust and provides a good user experience.

Error Response Format

All errors follow a consistent format:
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": {
      // Additional error details
    }
  },
  "meta": {
    "requestId": "uuid",
    "timestamp": "2024-01-01T00:00:00Z"
  }
}

HTTP Status Codes

400 Bad Request

Invalid request parameters or malformed request body.
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request parameters",
    "details": {
      "field": "email",
      "reason": "Invalid email format"
    }
  }
}
Action: Review the error details and fix the request parameters.

401 Unauthorized

Invalid or missing authentication credentials.
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing authentication credentials"
  }
}
Action: Verify your API credentials are correct and properly formatted.

404 Not Found

Resource not found.
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Resource not found",
    "details": {
      "resource": "interview",
      "id": "uuid"
    }
  }
}
Action: Verify the resource ID exists and you have access to it.

429 Too Many Requests

Rate limit exceeded.
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please try again later.",
    "details": {
      "limit": 1000,
      "remaining": 0,
      "resetAt": "2024-01-01T01:00:00Z"
    }
  }
}
Action: Implement exponential backoff and retry after the reset time.

500 Internal Server Error

Server error.
{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An internal error occurred"
  }
}
Action: Retry the request with exponential backoff. If the error persists, contact support.

Error Handling Patterns

Retry Logic

Implement retry logic for transient errors (429, 500):
async function makeRequestWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 429) {
        const resetTime = parseInt(response.headers.get('X-RateLimit-Reset'));
        const waitTime = Math.max((resetTime * 1000) - Date.now(), 0);
        
        if (i < maxRetries - 1) {
          await new Promise(resolve => setTimeout(resolve, waitTime));
          continue;
        }
      }
      
      if (!response.ok && response.status >= 500 && i < maxRetries - 1) {
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
        continue;
      }
      
      return response;
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
    }
  }
}

Validation Error Handling

Handle validation errors gracefully:
async function createQuestion(questionData) {
  try {
    const response = await fetch('https://api.prod.qualifi.hr/qsi/gather/questions', {
      method: 'POST',
      headers: {
        'x-api-key': apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(questionData)
    });
    
    if (!response.ok) {
      const error = await response.json();
      
      if (response.status === 400) {
        // Handle validation errors
        console.error('Validation error:', error.error.details);
        // Show user-friendly error messages
        return { error: error.error.message };
      }
      
      throw new Error(error.error.message);
    }
    
    return await response.json();
  } catch (error) {
    console.error('Request failed:', error);
    throw error;
  }
}

Common Error Scenarios

Invalid Credentials

Symptom: 401 Unauthorized Solution:
  • Verify credentials are correct
  • Check that your API key is correctly formatted and prefixed with qapi_
  • Ensure using organizationId:apiKey (not reversed)

Resource Not Found

Symptom: 404 Not Found Solution:
  • Verify resource ID exists
  • Check you have access to the resource
  • Ensure using correct endpoint path

Rate Limit Exceeded

Symptom: 429 Too Many Requests Solution:
  • Implement exponential backoff
  • Monitor rate limit headers
  • Cache responses when possible
  • Reduce request frequency

Network Errors

Symptom: Connection timeout or network errors Solution:
  • Implement retry logic
  • Use connection pooling
  • Set appropriate timeouts
  • Handle network failures gracefully

Best Practices

  1. Always Check Status Codes: Don’t assume requests succeed
  2. Log Errors: Log errors with request IDs for debugging
  3. User-Friendly Messages: Translate technical errors to user-friendly messages
  4. Retry Strategically: Retry transient errors, not client errors
  5. Handle Edge Cases: Plan for network failures, timeouts, and partial failures
  6. Monitor Error Rates: Track error rates and types to identify issues