Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.humanly.io/llms.txt

Use this file to discover all available pages before exploring further.

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": "john@example.com",
  "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

Error Handling

Learn about error handling patterns

Rate Limits

Understand rate limits and throttling

Handling Webhooks

Best practices for webhooks