> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instaview.sk/llms.txt
> Use this file to discover all available pages before exploring further.

# Best Practices

> Production-ready patterns for InstaView API integration

## Authentication & Security

<AccordionGroup>
  <Accordion title="Environment Variables" icon="lock">
    ```javascript theme={null}
    // ✅ Good
    const apiKey = process.env.INSTAVIEW_API_KEY;

    // ❌ Bad
    const apiKey = 'sk_live_abc123'; // Hardcoded!
    ```
  </Accordion>

  <Accordion title="Separate Keys per Environment" icon="layer-group">
    * **Production**: `sk_live_xxx`
    * **Staging**: `sk_test_xxx`
    * **Development**: `sk_test_yyy`
  </Accordion>

  <Accordion title="Minimal Scopes" icon="shield">
    ```javascript theme={null}
    // ✅ Good: Only what's needed
    scopes: ['read:jobs', 'read:candidates']

    // ❌ Bad: Unnecessary permissions
    scopes: ['read:*', 'write:*', 'delete:*']
    ```
  </Accordion>

  <Accordion title="Regular Key Rotation" icon="rotate">
    * Rotate high-privilege keys every 90 days
    * Implement graceful key rotation with fallback
    * Monitor key usage after rotation
  </Accordion>
</AccordionGroup>

## Error Handling

### Comprehensive Error Handler

```javascript theme={null}
class InstaViewAPI {
  async request(method, path, data) {
    try {
      const response = await fetch(`${this.baseURL}${path}`, {
        method,
        headers: this.headers,
        body: data ? JSON.stringify(data) : null
      });
      
      const result = await response.json();
      
      if (!result.success) {
        throw this.createError(result.error, response.status);
      }
      
      return result.data;
      
    } catch (error) {
      if (error.name === 'FetchError') {
        // Network error - retry
        return this.retryRequest(method, path, data);
      }
      throw error;
    }
  }
  
  createError(errorData, statusCode) {
    const error = new Error(errorData.message);
    error.code = errorData.code;
    error.details = errorData.details;
    error.statusCode = statusCode;
    return error;
  }
}
```

## Rate Limiting

### Request Queue

```javascript theme={null}
class RateLimitedQueue {
  constructor(requestsPerSecond = 5) {
    this.queue = [];
    this.processing = false;
    this.interval = 1000 / requestsPerSecond;
  }
  
  async add(fn) {
    return new Promise((resolve, reject) => {
      this.queue.push({ fn, resolve, reject });
      if (!this.processing) {
        this.process();
      }
    });
  }
  
  async process() {
    this.processing = true;
    
    while (this.queue.length > 0) {
      const { fn, resolve, reject } = this.queue.shift();
      
      try {
        const result = await fn();
        resolve(result);
      } catch (error) {
        reject(error);
      }
      
      if (this.queue.length > 0) {
        await this.sleep(this.interval);
      }
    }
    
    this.processing = false;
  }
  
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Usage
const queue = new RateLimitedQueue(5); // 5 requests/second

await queue.add(() => createJob(jobData));
await queue.add(() => createCandidate(candidateData));
```

## Pagination

### Efficient Iteration

```javascript theme={null}
async function* paginateAll(endpoint) {
  let page = 1;
  let hasMore = true;
  
  while (hasMore) {
    const response = await fetch(
      `${endpoint}?page=${page}&limit=100`,
      { headers: { 'Authorization': `Bearer ${apiKey}` } }
    );
    
    const result = await response.json();
    yield* result.data.items;
    
    hasMore = result.data.pagination.hasNextPage;
    page++;
  }
}

// Process items as they arrive
for await (const candidate of paginateAll('/candidates')) {
  await processCandidate(candidate);
}
```

## Data Validation

### Pre-Request Validation

```javascript theme={null}
function validateCandidateData(data) {
  const errors = [];
  
  if (!data.firstName || data.firstName.length < 1) {
    errors.push('firstName is required');
  }
  
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) {
    errors.push('Invalid email format');
  }
  
  if (!/^\+\d{10,15}$/.test(data.phoneNumber)) {
    errors.push('Phone must be in E.164 format (+1234567890)');
  }
  
  if (errors.length > 0) {
    throw new ValidationError(errors);
  }
}

// Use before API call
try {
  validateCandidateData(candidateData);
  await createCandidate(candidateData);
} catch (error) {
  if (error instanceof ValidationError) {
    showUserErrors(error.errors);
  }
}
```

## Caching

### Smart Caching Strategy

```javascript theme={null}
class CachedAPI {
  constructor(apiKey) {
    this.cache = new Map();
    this.ttl = {
      jobs: 300000,      // 5 minutes
      candidates: 60000,  // 1 minute
      interviews: 30000   // 30 seconds
    };
  }
  
  async get(resource, id) {
    const cacheKey = `${resource}:${id}`;
    const cached = this.cache.get(cacheKey);
    
    if (cached && Date.now() - cached.timestamp < this.ttl[resource]) {
      return cached.data;
    }
    
    const data = await this.fetchFromAPI(resource, id);
    this.cache.set(cacheKey, {
      data,
      timestamp: Date.now()
    });
    
    return data;
  }
  
  invalidate(resource, id) {
    this.cache.delete(`${resource}:${id}`);
  }
}
```

## Monitoring & Logging

### Structured Logging

```javascript theme={null}
class APILogger {
  static log(level, message, context = {}) {
    const log = {
      timestamp: new Date().toISOString(),
      level,
      message,
      ...context,
      service: 'instaview-api'
    };
    
    console.log(JSON.stringify(log));
    
    // Send to monitoring service
    if (process.env.NODE_ENV === 'production') {
      monitoring.track(log);
    }
  }
  
  static info(message, context) {
    this.log('info', message, context);
  }
  
  static error(message, error, context) {
    this.log('error', message, {
      ...context,
      error: {
        message: error.message,
        code: error.code,
        stack: error.stack
      }
    });
  }
}

// Usage
APILogger.info('Creating candidate', {
  jobId: 'job-uuid',
  candidateEmail: 'jane@example.com'
});
```

## Testing

### Integration Tests

```javascript theme={null}
describe('InstaView API Integration', () => {
  let testJobId;
  let testCandidateId;
  
  beforeAll(async () => {
    // Create test job
    const job = await createJob({
      title: 'Test Job',
      status: 'OPEN'
    });
    testJobId = job.id;
  });
  
  afterAll(async () => {
    // Cleanup
    await deleteJob(testJobId);
  });
  
  test('should create and retrieve candidate', async () => {
    // Create candidate
    const candidate = await createCandidate({
      jobId: testJobId,
      firstName: 'Test',
      lastName: 'User',
      email: 'test@example.com',
      phoneNumber: '+1234567890'
    });
    
    testCandidateId = candidate.id;
    expect(candidate.firstName).toBe('Test');
    
    // Retrieve candidate
    const retrieved = await getCandidate(testCandidateId);
    expect(retrieved.id).toBe(testCandidateId);
    expect(retrieved.email).toBe('test@example.com');
  });
});
```

## Performance

<CardGroup cols={2}>
  <Card title="Batch Operations" icon="layer-group">
    Group related API calls together
  </Card>

  <Card title="Parallel Requests" icon="arrows-split-up-and-left">
    Use Promise.all() for independent calls
  </Card>

  <Card title="Connection Pooling" icon="plug">
    Reuse HTTP connections
  </Card>

  <Card title="Compression" icon="file-zipper">
    Enable gzip compression
  </Card>
</CardGroup>

## Deployment Checklist

<Steps>
  <Step title="Environment Variables">
    ✓ API keys in environment variables\
    ✓ Different keys for each environment\
    ✓ Secrets not in version control
  </Step>

  <Step title="Error Handling">
    ✓ Comprehensive error handling\
    ✓ Retry logic with exponential backoff\
    ✓ Circuit breakers for failures
  </Step>

  <Step title="Monitoring">
    ✓ Logging for all API calls\
    ✓ Error tracking (Sentry, etc.)\
    ✓ Performance monitoring\
    ✓ Alert on rate limit hits
  </Step>

  <Step title="Security">
    ✓ API key rotation schedule\
    ✓ IP allowlists configured\
    ✓ HTTPS only\
    ✓ Webhook signature verification
  </Step>
</Steps>

## Next Steps

<CardGroup cols={2}>
  <Card title="Error Handling" icon="triangle-exclamation" href="/guides/error-handling">
    Handle errors gracefully
  </Card>

  <Card title="Rate Limiting" icon="gauge" href="/guides/rate-limiting">
    Optimize API usage
  </Card>

  <Card title="Webhooks" icon="webhook" href="/guides/webhooks">
    Real-time event notifications
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference">
    Complete API documentation
  </Card>
</CardGroup>
