Skip to content

Dynamic QR Codes Guide

Create QR codes with editable destination URLs and scan tracking.

What Are Dynamic QR Codes?

Dynamic QR codes point to a short URL that redirects to your target URL. Unlike static QR codes, you can change where they point without reprinting.

Static QR Code:

QR → https://restaurant.com/menu-2024.pdf

If you update the menu, you need new QR codes.

Dynamic QR Code:

QR → https://www.qrcodeapi.io/r/abc123 → https://restaurant.com/menu.pdf

Update the destination anytime—the QR code stays the same.

Creating Dynamic QR Codes

bash
curl -X POST "https://www.qrcodeapi.io/api/links" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Restaurant Menu",
    "targetUrl": "https://restaurant.com/menu.pdf"
  }'

Response:

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Restaurant Menu",
  "shortCode": "abc123",
  "targetUrl": "https://restaurant.com/menu.pdf",
  "scanCount": 0,
  "createdAt": "2024-01-15T10:30:00Z"
}

Step 2: Generate the QR Code

bash
curl "https://www.qrcodeapi.io/api/generate" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -G \
  --data-urlencode "data=https://www.qrcodeapi.io/r/abc123" \
  --data "size=500" \
  -o menu-qr.png

Step 3: Update When Needed

bash
curl -X PUT "https://www.qrcodeapi.io/api/links?id=550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "targetUrl": "https://restaurant.com/summer-menu.pdf"
  }'

The same QR code now points to the summer menu!

Complete JavaScript Example

javascript
const API_KEY = process.env.QRCODE_API_KEY;

class DynamicQR {
  // Create a dynamic link
  async createLink(name, targetUrl) {
    const response = await fetch('https://www.qrcodeapi.io/api/links', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ name, targetUrl })
    });
    
    if (!response.ok) {
      throw new Error((await response.json()).message);
    }
    
    return response.json();
  }

  // Generate QR code for a link
  async generateQR(shortCode, options = {}) {
    const params = new URLSearchParams({
      data: `https://www.qrcodeapi.io/r/${shortCode}`,
      size: options.size || 300,
      color: options.color || '000000',
      background: options.background || 'ffffff'
    });

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

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

    return response.blob();
  }

  // Update a link's target URL
  async updateLink(linkId, updates) {
    const response = await fetch(
      `https://www.qrcodeapi.io/api/links?id=${linkId}`,
      {
        method: 'PUT',
        headers: {
          'Authorization': `Bearer ${API_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(updates)
      }
    );

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

    return response.json();
  }

  // Get analytics for a link
  async getAnalytics(linkId) {
    const response = await fetch(
      `https://www.qrcodeapi.io/api/analytics?linkId=${linkId}`,
      { headers: { 'Authorization': `Bearer ${API_KEY}` } }
    );

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

    return response.json();
  }

  // Full workflow: create link + generate QR
  async create(name, targetUrl, qrOptions = {}) {
    const link = await this.createLink(name, targetUrl);
    const qrBlob = await this.generateQR(link.shortCode, qrOptions);
    
    return {
      link,
      qrBlob,
      shortUrl: `https://www.qrcodeapi.io/r/${link.shortCode}`
    };
  }
}

// Usage
const dynamicQR = new DynamicQR();

// Create a dynamic QR code
const { link, qrBlob, shortUrl } = await dynamicQR.create(
  'Product Launch',
  'https://company.com/launch',
  { size: 500, color: '4f46e5' }
);

console.log(`Short URL: ${shortUrl}`);
console.log(`Link ID: ${link.id}`);

// Later: update the destination
await dynamicQR.updateLink(link.id, {
  targetUrl: 'https://company.com/launch-v2'
});

// Check analytics
const analytics = await dynamicQR.getAnalytics(link.id);
console.log(`Total scans: ${analytics.analytics.totalScans}`);

Use Cases

Restaurant Menus

javascript
// Create menu QR codes for each table
const tables = [1, 2, 3, 4, 5];

for (const table of tables) {
  const { link } = await dynamicQR.create(
    `Table ${table} Menu`,
    'https://restaurant.com/menu',
    { size: 300 }
  );
  
  console.log(`Table ${table}: ${link.shortCode}`);
}

// Update all menus to seasonal menu
for (const linkId of menuLinkIds) {
  await dynamicQR.updateLink(linkId, {
    targetUrl: 'https://restaurant.com/winter-menu'
  });
}

Marketing Campaigns

javascript
// A/B test landing pages
const campaign = await dynamicQR.create(
  'Summer Sale',
  'https://shop.com/sale-a',  // Start with variant A
  { size: 500, color: '22c55e' }
);

// Print and distribute the QR codes...

// After 1 week, switch to variant B
await dynamicQR.updateLink(campaign.link.id, {
  targetUrl: 'https://shop.com/sale-b'
});

// Compare analytics
const analytics = await dynamicQR.getAnalytics(campaign.link.id);

Event Materials

javascript
// Event schedule QR code
const event = await dynamicQR.create(
  'Conference 2024',
  'https://conference.com/schedule',
  { size: 400 }
);

// Update in real-time during the event
await dynamicQR.updateLink(event.link.id, {
  targetUrl: 'https://conference.com/schedule?room=changed'
});

Product Packaging

javascript
// Product info QR code
const product = await dynamicQR.create(
  'Widget Pro',
  'https://company.com/products/widget-pro',
  { size: 200, errorCorrection: 'H' }
);

// Update when product page changes
await dynamicQR.updateLink(product.link.id, {
  targetUrl: 'https://company.com/products/widget-pro-v2'
});

// Redirect discontinued products
await dynamicQR.updateLink(oldProductId, {
  targetUrl: 'https://company.com/products/widget-pro-replacement'
});

Analytics

Track every scan with detailed analytics:

javascript
const analytics = await dynamicQR.getAnalytics(linkId);

// Total scans
console.log(`Total: ${analytics.analytics.totalScans}`);
console.log(`Unique: ${analytics.analytics.uniqueScans}`);

// Scans by day
for (const day of analytics.analytics.scansByDay) {
  console.log(`${day.date}: ${day.scans} scans`);
}

// Top countries
for (const country of analytics.analytics.scansByCountry.slice(0, 5)) {
  console.log(`${country.country}: ${country.scans} scans`);
}

// Device breakdown
for (const device of analytics.analytics.scansByDevice) {
  console.log(`${device.device}: ${device.scans} scans`);
}

Limits by Plan

PlanDynamic LinksAnalytics Retention
Free530 days
Starter5090 days
Pro5001 year
EnterpriseUnlimitedUnlimited

Best Practices

1. Descriptive Names

Use clear, descriptive names for your links:

  • ✅ "Summer 2024 Menu - Downtown Location"
  • ❌ "menu1"

2. Organize by Category

Group related links by naming convention:

  • "Campaign: Summer Sale"
  • "Campaign: Black Friday"
  • "Product: Widget Pro"

3. Regular Maintenance

  • Review analytics monthly
  • Delete unused links
  • Update broken target URLs

4. Test Before Print

Always test scan the QR code before printing:

  • Verify it redirects correctly
  • Test on multiple devices
  • Check from various distances

5. Keep Target URLs Live

Never delete or change URL structure of target pages without updating the dynamic link first.