Skip to main content

Overview

This guide covers best practices for using the Gather API to build robust, efficient integrations.

Authentication

Secure Credential Storage

  • Never commit API keys to version control
  • Use environment variables for credentials
  • Rotate keys regularly for security
  • Use separate keys for different environments (production, staging)

Credential Format

Always use the correct format: organizationId:apiKey
// ✅ Correct
const apiKey = 'qapi_your-api-key-here';

// ❌ Incorrect
const apiKey = 'qapi_your-api-key-here';

Request Handling

Error Handling

Always handle errors gracefully:
try {
  const response = await fetch(url, options);
  
  if (!response.ok) {
    const error = await response.json();
    // Handle specific error codes
    if (response.status === 429) {
      // Handle rate limiting
    } else if (response.status === 400) {
      // Handle validation errors
    }
    throw new Error(error.error.message);
  }
  
  return await response.json();
} catch (error) {
  // Log and handle error
  console.error('API request failed:', error);
  throw error;
}

Retry Logic

Implement retry logic for transient failures:
  • Retry on 429 (rate limit) and 5xx errors
  • Use exponential backoff
  • Don’t retry on 4xx client errors
  • Set maximum retry attempts

Timeouts

Set appropriate timeouts:
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 seconds

fetch(url, {
  ...options,
  signal: controller.signal
}).finally(() => clearTimeout(timeoutId));

Rate Limiting

Monitor Rate Limits

Check rate limit headers on every response:
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
const limit = parseInt(response.headers.get('X-RateLimit-Limit'));

if (remaining < 100) {
  // Slow down requests
}

Optimize Request Frequency

  • Cache responses when possible
  • Batch operations when available
  • Use webhooks instead of polling
  • Request only needed data

Data Management

Use External IDs

Use externalId to maintain references:
{
  "firstName": "John",
  "lastName": "Doe",
  "email": "[email protected]",
  "externalId": "your-system-id-123"
}

Phone Number Format

Always use E.164 format:
  • +1234567890
  • 123-456-7890
  • (123) 456-7890

Idempotency

Make operations idempotent when possible:
  • Use external IDs to prevent duplicates
  • Check if resource exists before creating
  • Handle duplicate creation gracefully

Webhooks

Verify Signatures

Always verify webhook signatures:
function verifySignature(payload, signature, secret) {
  // Verify signature before processing
  // ...
}

Handle Duplicates

Webhooks may be delivered multiple times:
  • Use event IDs or timestamps for deduplication
  • Make webhook handlers idempotent
  • Log all webhook events

Respond Quickly

Respond to webhooks within 5 seconds:
  • Process webhooks asynchronously
  • Queue heavy operations
  • Return 200 OK immediately

Performance

Connection Pooling

Reuse HTTP connections:
// Use a persistent HTTP client
const https = require('https');
const agent = new https.Agent({ keepAlive: true });

Parallel Requests

Make independent requests in parallel:
const [questions, interviews, candidates] = await Promise.all([
  fetchQuestions(),
  fetchInterviews(),
  fetchCandidates()
]);

Pagination

Handle pagination efficiently:
async function fetchAllPages(endpoint) {
  let page = 1;
  let allData = [];
  
  while (true) {
    const response = await fetch(`${endpoint}?page=${page}&limit=100`);
    const data = await response.json();
    
    allData.push(...data.data);
    
    if (page >= data.meta.pagination.totalPages) break;
    page++;
  }
  
  return allData;
}

Security

Input Validation

Validate input before sending to API:
function validateEmail(email) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

function validatePhone(phone) {
  return /^\+[1-9]\d{1,14}$/.test(phone);
}

HTTPS Only

Always use HTTPS:
  • https://api.prod.qualifi.hr
  • http://api.prod.qualifi.hr

Logging

Don’t log sensitive data:
// ✅ Good
console.log('Request sent to:', endpoint);

// ❌ Bad
console.log('Credentials:', credentials);

Testing

Test Error Scenarios

Test your error handling:
  • Invalid credentials
  • Rate limiting
  • Network failures
  • Invalid data

Use Staging Environment

Test in staging before production:
  • Use https://api.dev.qualifi.hr for testing
  • Verify all workflows
  • Test error scenarios

Monitoring

Track Metrics

Monitor key metrics:
  • Request success rate
  • Error rates by type
  • Response times
  • Rate limit usage

Logging

Log important events:
  • API requests and responses
  • Errors with request IDs
  • Rate limit warnings
  • Webhook events