Skip to content

Advanced Examples

Complex use cases and patterns for QR Code API.

Dynamic QR Codes with Analytics

Track how many people scan your QR codes:

javascript
class QRTracker {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://www.qrcodeapi.io/api';
  }

  async createTrackedQR(name, targetUrl, options = {}) {
    // 1. Create a dynamic link
    const linkRes = await fetch(`${this.baseUrl}/links`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ name, targetUrl })
    });
    
    const link = await linkRes.json();
    
    // 2. Generate QR code for the short URL
    const params = new URLSearchParams({
      data: `https://www.qrcodeapi.io/r/${link.shortCode}`,
      size: options.size || 400,
      color: options.color || '000000',
      background: options.background || 'ffffff',
      errorCorrection: options.logo ? 'H' : 'M'
    });
    
    if (options.logo) {
      params.append('logo', options.logo);
    }
    
    const qrRes = await fetch(`${this.baseUrl}/generate?${params}`, {
      headers: { 'Authorization': `Bearer ${this.apiKey}` }
    });
    
    return {
      link,
      qrBlob: await qrRes.blob(),
      shortUrl: `https://www.qrcodeapi.io/r/${link.shortCode}`
    };
  }

  async getStats(linkId) {
    const res = await fetch(
      `${this.baseUrl}/analytics?linkId=${linkId}`,
      { headers: { 'Authorization': `Bearer ${this.apiKey}` } }
    );
    return res.json();
  }
}

// Usage
const tracker = new QRTracker(process.env.API_KEY);

const campaign = await tracker.createTrackedQR(
  'Summer Sale 2024',
  'https://shop.com/summer-sale',
  { size: 500, color: '22c55e' }
);

// Save the QR code
const buffer = Buffer.from(await campaign.qrBlob.arrayBuffer());
fs.writeFileSync('summer-sale-qr.png', buffer);

// Later: check stats
const stats = await tracker.getStats(campaign.link.id);
console.log(`Total scans: ${stats.analytics.totalScans}`);

Batch Generation with Progress

Generate multiple QR codes with progress tracking:

javascript
async function batchGenerateWithProgress(items, options = {}) {
  const results = [];
  const total = items.length;
  let completed = 0;

  // Process in parallel batches of 5
  const batchSize = 5;
  
  for (let i = 0; i < total; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    
    const promises = batch.map(async (item) => {
      const params = new URLSearchParams({
        data: item.data,
        size: options.size || 300,
        color: options.color || '000000'
      });
      
      const response = await fetch(
        `https://www.qrcodeapi.io/api/generate?${params}`,
        { headers: { 'Authorization': `Bearer ${API_KEY}` } }
      );
      
      completed++;
      console.log(`Progress: ${completed}/${total} (${Math.round(completed/total*100)}%)`);
      
      return {
        ...item,
        blob: await response.blob()
      };
    });
    
    results.push(...await Promise.all(promises));
  }
  
  return results;
}

// Usage
const products = [
  { id: 1, data: 'https://shop.com/product/1' },
  { id: 2, data: 'https://shop.com/product/2' },
  // ... more products
];

const qrCodes = await batchGenerateWithProgress(products, {
  size: 400,
  color: '1e40af'
});

QR Code with Retry Logic

Handle rate limits and errors gracefully:

javascript
class ResilientQRGenerator {
  constructor(apiKey, maxRetries = 3) {
    this.apiKey = apiKey;
    this.maxRetries = maxRetries;
  }

  async generate(data, options = {}, attempt = 1) {
    try {
      const params = new URLSearchParams({ data, ...options });
      const response = await fetch(
        `https://www.qrcodeapi.io/api/generate?${params}`,
        { headers: { 'Authorization': `Bearer ${this.apiKey}` } }
      );

      if (response.status === 429) {
        const error = await response.json();
        const waitTime = error.retryAfter || Math.pow(2, attempt);
        
        if (attempt < this.maxRetries) {
          console.log(`Rate limited. Waiting ${waitTime}s...`);
          await this.sleep(waitTime * 1000);
          return this.generate(data, options, attempt + 1);
        }
        
        throw new Error('Max retries exceeded');
      }

      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.message);
      }

      return response.blob();
    } catch (error) {
      if (attempt < this.maxRetries && this.isRetryable(error)) {
        const waitTime = Math.pow(2, attempt);
        console.log(`Error: ${error.message}. Retrying in ${waitTime}s...`);
        await this.sleep(waitTime * 1000);
        return this.generate(data, options, attempt + 1);
      }
      throw error;
    }
  }

  isRetryable(error) {
    return error.message.includes('network') || 
           error.message.includes('timeout');
  }

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Usage
const generator = new ResilientQRGenerator(API_KEY);
const qr = await generator.generate('https://example.com', { size: 500 });

Real-time QR Code Generator (React)

jsx
import { useState, useCallback, useEffect } from 'react';
import debounce from 'lodash/debounce';

function QRGenerator() {
  const [data, setData] = useState('');
  const [options, setOptions] = useState({
    size: 300,
    color: '000000',
    background: 'ffffff'
  });
  const [qrUrl, setQrUrl] = useState('');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const generateQR = useCallback(
    debounce(async (data, options) => {
      if (!data) {
        setQrUrl('');
        return;
      }

      setLoading(true);
      setError('');

      try {
        const params = new URLSearchParams({
          data,
          ...options
        });

        const response = await fetch(
          `https://www.qrcodeapi.io/api/generate?${params}`,
          { headers: { 'Authorization': `Bearer ${API_KEY}` } }
        );

        if (!response.ok) {
          const err = await response.json();
          throw new Error(err.message);
        }

        const blob = await response.blob();
        setQrUrl(URL.createObjectURL(blob));
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }, 300),
    []
  );

  useEffect(() => {
    generateQR(data, options);
  }, [data, options, generateQR]);

  return (
    <div className="qr-generator">
      <div className="controls">
        <input
          type="text"
          value={data}
          onChange={e => setData(e.target.value)}
          placeholder="Enter text or URL"
        />
        
        <label>
          Size:
          <input
            type="range"
            min="100"
            max="1000"
            value={options.size}
            onChange={e => setOptions({...options, size: e.target.value})}
          />
          {options.size}px
        </label>
        
        <label>
          Color:
          <input
            type="color"
            value={`#${options.color}`}
            onChange={e => setOptions({...options, color: e.target.value.slice(1)})}
          />
        </label>
        
        <label>
          Background:
          <input
            type="color"
            value={`#${options.background}`}
            onChange={e => setOptions({...options, background: e.target.value.slice(1)})}
          />
        </label>
      </div>

      <div className="preview">
        {loading && <div className="spinner">Loading...</div>}
        {error && <div className="error">{error}</div>}
        {qrUrl && !loading && (
          <img src={qrUrl} alt="QR Code" />
        )}
      </div>
    </div>
  );
}

QR Code PDF Generator

Generate a PDF with multiple QR codes:

javascript
import { PDFDocument, rgb } from 'pdf-lib';

async function generateQRPDF(items) {
  const pdfDoc = await PDFDocument.create();
  const page = pdfDoc.addPage([612, 792]); // Letter size
  
  const qrSize = 150;
  const margin = 50;
  const cols = 3;
  
  for (let i = 0; i < items.length; i++) {
    // Generate QR code
    const response = await fetch(
      `https://www.qrcodeapi.io/api/generate?data=${encodeURIComponent(items[i].data)}&size=${qrSize}`,
      { headers: { 'Authorization': `Bearer ${API_KEY}` } }
    );
    
    const imageBytes = await response.arrayBuffer();
    const image = await pdfDoc.embedPng(imageBytes);
    
    // Calculate position
    const col = i % cols;
    const row = Math.floor(i / cols);
    const x = margin + col * (qrSize + margin);
    const y = 792 - margin - (row + 1) * (qrSize + 50);
    
    // Draw QR code
    page.drawImage(image, {
      x,
      y,
      width: qrSize,
      height: qrSize
    });
    
    // Add label
    page.drawText(items[i].label, {
      x: x + qrSize / 2 - items[i].label.length * 3,
      y: y - 15,
      size: 10
    });
  }
  
  const pdfBytes = await pdfDoc.save();
  return pdfBytes;
}

// Usage
const items = [
  { data: 'https://shop.com/p/1', label: 'Product 1' },
  { data: 'https://shop.com/p/2', label: 'Product 2' },
  { data: 'https://shop.com/p/3', label: 'Product 3' },
];

const pdfBytes = await generateQRPDF(items);
fs.writeFileSync('qr-codes.pdf', pdfBytes);

QR Code Caching Layer

Implement caching to reduce API calls:

javascript
const NodeCache = require('node-cache');

class CachedQRGenerator {
  constructor(apiKey, ttlSeconds = 3600) {
    this.apiKey = apiKey;
    this.cache = new NodeCache({ stdTTL: ttlSeconds });
  }

  getCacheKey(data, options) {
    return `qr:${data}:${JSON.stringify(options)}`;
  }

  async generate(data, options = {}) {
    const cacheKey = this.getCacheKey(data, options);
    
    // Check cache
    const cached = this.cache.get(cacheKey);
    if (cached) {
      console.log('Cache hit');
      return cached;
    }
    
    console.log('Cache miss, generating...');
    
    // Generate new QR code
    const params = new URLSearchParams({ data, ...options });
    const response = await fetch(
      `https://www.qrcodeapi.io/api/generate?${params}`,
      { headers: { 'Authorization': `Bearer ${this.apiKey}` } }
    );
    
    const buffer = Buffer.from(await response.arrayBuffer());
    
    // Store in cache
    this.cache.set(cacheKey, buffer);
    
    return buffer;
  }
}

// Usage
const generator = new CachedQRGenerator(API_KEY);

// First call: cache miss, API call made
const qr1 = await generator.generate('https://example.com', { size: 300 });

// Second call: cache hit, no API call
const qr2 = await generator.generate('https://example.com', { size: 300 });

Webhook Handler (Express)

Process real-time scan notifications:

javascript
const express = require('express');
const crypto = require('crypto');

const app = express();

// Store for deduplication
const processedEvents = new Set();

app.post('/webhooks/qr', express.raw({ type: 'application/json' }), async (req, res) => {
  // Verify signature
  const signature = req.headers['x-signature'];
  const expectedSig = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');
  
  if (signature !== expectedSig) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  const event = JSON.parse(req.body);
  
  // Deduplicate
  if (processedEvents.has(event.id)) {
    return res.json({ status: 'already_processed' });
  }
  processedEvents.add(event.id);
  
  // Respond immediately
  res.json({ received: true });
  
  // Process asynchronously
  try {
    switch (event.type) {
      case 'scan.created':
        await handleScan(event.data);
        break;
      case 'link.updated':
        await handleLinkUpdate(event.data);
        break;
    }
  } catch (error) {
    console.error('Webhook processing error:', error);
  }
});

async function handleScan(data) {
  console.log(`New scan on ${data.shortCode} from ${data.scan.country}`);
  
  // Send notification, update analytics dashboard, etc.
  await sendSlackNotification(`🔔 QR scan from ${data.scan.city}, ${data.scan.country}`);
}

async function handleLinkUpdate(data) {
  console.log(`Link ${data.link.shortCode} updated to ${data.link.targetUrl}`);
}

app.listen(3000);