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

# Integration Patterns

> Reusable integration patterns and best practices for Vantio

## Overview

This guide provides reusable integration patterns and code snippets you can use across your Vantio integration. These patterns follow best practices and handle common scenarios.

## Referral Flow Pattern

Complete pattern for handling the referral flow from QR scan to earning:

```javascript theme={null}
// patterns/referral-flow.js
class ReferralFlowHandler {
  constructor(vantioClient) {
    this.client = vantioClient;
  }
  
  async handleQRScan(qrCodeData) {
    // QR scan creates an impression
    // This is typically handled automatically by Vantio
    // You receive the impression_id from the QR scan
    return qrCodeData.impression_id;
  }
  
  async handleSignup(impressionId, userData) {
    // Create referral when user signs up
    const referral = await this.client.createReferral({
      impression_id: impressionId,
      first_name: userData.firstName,
      last_name: userData.lastName,
      email: userData.email,
      idempotency_key: `ref_${userData.userId}_${Date.now()}`
    });
    
    return referral;
  }
  
  async handlePurchase(referralId, orderData) {
    // Create earning when referred customer makes purchase
    const commissionRate = 0.10; // 10%
    const amountInCents = Math.round(orderData.total * commissionRate * 100);
    
    const earning = await this.client.createEarning({
      referral_id: referralId,
      amount: amountInCents,
      currency: 'USD',
      type: 'purchase',
      description: `Commission from order #${orderData.orderId}`,
      metadata: {
        order_id: orderData.orderId,
        commission_rate: `${commissionRate * 100}%`
      },
      idempotency_key: `earn_${orderData.orderId}_${Date.now()}`
    });
    
    // Update referral status to converted
    await this.client.updateReferral(referralId, {
      status: 'converted'
    });
    
    return earning;
  }
}

// Usage
const flowHandler = new ReferralFlowHandler(vantioClient);

// 1. User scans QR code (impression created automatically)
const impressionId = await flowHandler.handleQRScan(qrCodeData);

// 2. User signs up
const referral = await flowHandler.handleSignup(impressionId, {
  userId: 'user_123',
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com'
});

// 3. User makes purchase
const earning = await flowHandler.handlePurchase(referral.id, {
  orderId: 'order_456',
  total: 100.00
});
```

## Idempotency Pattern

Ensure requests are idempotent to prevent duplicates:

```javascript theme={null}
// patterns/idempotency.js
class IdempotentRequest {
  constructor() {
    this.processedKeys = new Set();
  }
  
  generateKey(prefix, identifier) {
    return `${prefix}_${identifier}_${Date.now()}`;
  }
  
  async execute(key, requestFn) {
    if (this.processedKeys.has(key)) {
      console.log(`Request ${key} already processed, skipping`);
      return null;
    }
    
    try {
      const result = await requestFn();
      this.processedKeys.add(key);
      return result;
    } catch (error) {
      // Remove key on error so it can be retried
      this.processedKeys.delete(key);
      throw error;
    }
  }
}

// Usage
const idempotent = new IdempotentRequest();

const key = idempotent.generateKey('earn', orderId);
await idempotent.execute(key, async () => {
  return await vantioClient.createEarning({
    ...earningData,
    idempotency_key: key
  });
});
```

## Error Handling Pattern

Comprehensive error handling for API requests:

```javascript theme={null}
// patterns/error-handling.js
class VantioError extends Error {
  constructor(message, status, code) {
    super(message);
    this.status = status;
    this.code = code;
    this.name = 'VantioError';
  }
}

async function handleAPIRequest(requestFn) {
  try {
    return await requestFn();
  } catch (error) {
    if (error.response) {
      const { status, data } = error.response;
      
      switch (status) {
        case 400:
          throw new VantioError(
            data.message || 'Bad request',
            status,
            'BAD_REQUEST'
          );
        case 401:
          throw new VantioError(
            'Invalid or missing API key',
            status,
            'UNAUTHORIZED'
          );
        case 404:
          throw new VantioError(
            'Resource not found',
            status,
            'NOT_FOUND'
          );
        case 429:
          throw new VantioError(
            'Rate limit exceeded',
            status,
            'RATE_LIMIT'
          );
        default:
          throw new VantioError(
            data.message || 'API request failed',
            status,
            'UNKNOWN_ERROR'
          );
      }
    }
    
    throw error;
  }
}

// Usage
try {
  const referral = await handleAPIRequest(() =>
    vantioClient.createReferral(referralData)
  );
} catch (error) {
  if (error instanceof VantioError) {
    console.error(`Vantio Error [${error.code}]: ${error.message}`);
  } else {
    console.error('Unexpected error:', error);
  }
}
```

## Retry Pattern

Retry failed requests with exponential backoff:

```javascript theme={null}
// patterns/retry.js
async function retryWithBackoff(fn, maxRetries = 3, baseDelay = 1000) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
      
      // Don't retry on client errors (4xx)
      if (error.status >= 400 && error.status < 500) {
        throw error;
      }
      
      // Exponential backoff
      const delay = baseDelay * Math.pow(2, attempt);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// Usage
const referral = await retryWithBackoff(() =>
  vantioClient.createReferral(referralData)
);
```

## Batch Processing Pattern

Process multiple items efficiently:

```javascript theme={null}
// patterns/batch-processing.js
async function processBatch(items, processor, concurrency = 5) {
  const results = [];
  const errors = [];
  
  for (let i = 0; i < items.length; i += concurrency) {
    const batch = items.slice(i, i + concurrency);
    
    const batchResults = await Promise.allSettled(
      batch.map(item => processor(item))
    );
    
    batchResults.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        results.push(result.value);
      } else {
        errors.push({
          item: batch[index],
          error: result.reason
        });
      }
    });
  }
  
  return { results, errors };
}

// Usage: Create multiple referrals
const signups = [
  { impressionId: 'imp_1', firstName: 'John', ... },
  { impressionId: 'imp_2', firstName: 'Jane', ... },
  // ... more signups
];

const { results, errors } = await processBatch(
  signups,
  async (signup) => {
    return await vantioClient.createReferral({
      impression_id: signup.impressionId,
      first_name: signup.firstName,
      last_name: signup.lastName,
      email: signup.email
    });
  },
  5 // Process 5 at a time
);
```

## Webhook Validation Pattern

Validate and process webhooks securely:

```javascript theme={null}
// patterns/webhook-validation.js
const crypto = require('crypto');

function validateWebhook(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const digest = hmac.update(JSON.stringify(payload)).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(digest)
  );
}

// Express.js webhook handler
app.post('/webhooks/vantio', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-vantio-signature'];
  const secret = process.env.VANTIO_WEBHOOK_SECRET;
  
  if (!validateWebhook(req.body, signature, secret)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  const event = JSON.parse(req.body);
  // Process event...
  
  res.json({ received: true });
});
```

## Caching Pattern

Cache API responses to reduce calls:

```javascript theme={null}
// patterns/caching.js
class Cache {
  constructor(ttl = 300000) { // 5 minutes default
    this.cache = new Map();
    this.ttl = ttl;
  }
  
  get(key) {
    const item = this.cache.get(key);
    if (!item) return null;
    
    if (Date.now() > item.expires) {
      this.cache.delete(key);
      return null;
    }
    
    return item.value;
  }
  
  set(key, value) {
    this.cache.set(key, {
      value,
      expires: Date.now() + this.ttl
    });
  }
}

// Usage with API client
const cache = new Cache(300000); // 5 minutes

async function getCachedUser(userId) {
  const cacheKey = `user_${userId}`;
  let user = cache.get(cacheKey);
  
  if (!user) {
    user = await vantioClient.getUser(userId);
    cache.set(cacheKey, user);
  }
  
  return user;
}
```

## Best Practices

1. **Always use idempotency keys** for POST requests
2. **Implement retry logic** for transient failures
3. **Cache frequently accessed data** to reduce API calls
4. **Validate webhooks** to ensure security
5. **Handle errors gracefully** with proper error types
6. **Use batch processing** for multiple items
7. **Monitor rate limits** and implement backoff

## Next Steps

* Review [Code Examples](/essentials/code) for more integration code
* Check [API Reference](/api-reference/introduction) for endpoint details
* Explore [Configuration Guide](/essentials/settings) for setup options
