Back to Blog

Dynamic QR Code API: Generate Trackable Codes Programmatically

QRStar Team6 min read

Need to generate thousands of QR codes with tracking? An API is the answer.

This guide covers how to use a dynamic QR code API, integration patterns, and best practices for production use.

Why Use a QR Code API?

Manual QR code generation doesn't scale. An API lets you:

  • Generate codes programmatically
  • Create thousands of codes in seconds
  • Integrate QR generation into your workflows
  • Track scans with analytics
  • Update destinations without regenerating

Static vs Dynamic API Endpoints

Most QR code APIs offer two generation modes:

Static Generation

POST /v1/generate/static
{
  "data": "https://example.com",
  "size": 512,
  "format": "png"
}

Returns: QR code image URL

The data is encoded directly. No tracking, no editability.

Dynamic Generation

POST /v1/generate/dynamic
{
  "redirect_url": "https://example.com/landing",
  "name": "Summer Campaign 2026"
}

Returns: QR code image URL + analytics ID + short URL

The code points to a redirect. Full tracking, editable destination.

Basic API Integration

Here's how to integrate a QR code API in your application:

Node.js Example

const response = await fetch('https://api.qrstar.app/v1/generate/dynamic', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': process.env.QRSTAR_API_KEY
  },
  body: JSON.stringify({
    redirect_url: 'https://example.com/promo',
    name: 'Product Launch Campaign'
  })
});

const { qr_code_url, short_url, analytics_id } = await response.json();

Python Example

import requests

response = requests.post(
    'https://api.qrstar.app/v1/generate/dynamic',
    headers={
        'Content-Type': 'application/json',
        'X-API-Key': os.environ['QRSTAR_API_KEY']
    },
    json={
        'redirect_url': 'https://example.com/promo',
        'name': 'Product Launch Campaign'
    }
)

data = response.json()
qr_code_url = data['qr_code_url']
analytics_id = data['analytics_id']

cURL Example

curl -X POST https://api.qrstar.app/v1/generate/dynamic \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_api_key" \
  -d '{
    "redirect_url": "https://example.com/promo",
    "name": "Product Launch Campaign"
  }'

Retrieving Analytics

Dynamic codes track every scan. Query the analytics endpoint to retrieve data:

GET /v1/analytics/{analytics_id}

Response:

{
  "total_scans": 1234,
  "unique_scanners": 892,
  "scans_today": 45,
  "top_countries": [
    { "country": "US", "count": 823 },
    { "country": "UK", "count": 201 },
    { "country": "CA", "count": 156 }
  ],
  "devices": {
    "ios": 512,
    "android": 456,
    "other": 266
  },
  "scans_by_day": [
    { "date": "2025-12-29", "count": 45 },
    { "date": "2025-12-28", "count": 52 }
  ]
}

Customization Options

Most APIs support these customization parameters:

ParameterDescriptionExample
sizeOutput dimensions in pixels512
formatImage format"png" or "svg"
dark_colorForeground color"#000000"
light_colorBackground color"#FFFFFF"
error_correctionRedundancy level"L", "M", "Q", or "H"
marginQuiet zone size4

Example with customization:

{
  "redirect_url": "https://example.com",
  "size": 1024,
  "format": "svg",
  "dark_color": "#1a1a2e",
  "light_color": "#ffffff",
  "error_correction": "M"
}

Batch Generation

For high-volume use cases, batch endpoints process multiple codes in one request:

POST /v1/generate/batch
{
  "codes": [
    { "redirect_url": "https://example.com/product-1", "name": "Product 1" },
    { "redirect_url": "https://example.com/product-2", "name": "Product 2" },
    { "redirect_url": "https://example.com/product-3", "name": "Product 3" }
  ]
}

Batch requests reduce latency and API calls for bulk generation.

Integration Patterns

E-commerce: Unique Codes Per Order

Generate a tracking code for each order:

async function createOrderQRCode(orderId, trackingUrl) {
  const response = await qrApi.generate({
    redirect_url: trackingUrl,
    name: `Order ${orderId}`,
    metadata: { order_id: orderId }
  });

  // Store analytics_id with order for later reporting
  await db.orders.update(orderId, {
    qr_analytics_id: response.analytics_id
  });

  return response.qr_code_url;
}

Marketing: Campaign Tracking

Create codes for each campaign channel:

const channels = ['flyers', 'billboards', 'email', 'social'];

const campaignCodes = await Promise.all(
  channels.map(channel =>
    qrApi.generate({
      redirect_url: `https://example.com/landing?utm_source=${channel}`,
      name: `Summer 2026 - ${channel}`
    })
  )
);

Product Packaging: Serial Number Codes

Generate unique codes per product unit:

async function generateProductCodes(productId, quantity) {
  const codes = [];

  for (let i = 0; i < quantity; i++) {
    const serialNumber = `${productId}-${Date.now()}-${i}`;
    const code = await qrApi.generate({
      redirect_url: `https://example.com/verify/${serialNumber}`,
      name: `Product ${serialNumber}`,
      metadata: { serial: serialNumber, product_id: productId }
    });
    codes.push(code);
  }

  return codes;
}

Error Handling

Handle API errors gracefully:

async function generateQRCode(url) {
  try {
    const response = await fetch(API_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': API_KEY
      },
      body: JSON.stringify({ redirect_url: url })
    });

    if (!response.ok) {
      const error = await response.json();

      if (response.status === 429) {
        // Rate limited - wait and retry
        await sleep(error.retry_after * 1000);
        return generateQRCode(url);
      }

      throw new Error(error.message);
    }

    return response.json();
  } catch (error) {
    console.error('QR generation failed:', error);
    throw error;
  }
}

Security Best Practices

Protect Your API Key

  • Store in environment variables, not code
  • Use different keys for dev/staging/production
  • Rotate keys periodically
  • Monitor usage for anomalies

Validate Input URLs

function isValidUrl(string) {
  try {
    const url = new URL(string);
    return url.protocol === 'http:' || url.protocol === 'https:';
  } catch {
    return false;
  }
}

Rate Limiting

Implement client-side rate limiting to avoid hitting API limits:

const rateLimiter = new RateLimiter({
  tokensPerInterval: 100,
  interval: 'minute'
});

async function generateWithRateLimit(data) {
  await rateLimiter.removeTokens(1);
  return qrApi.generate(data);
}

Pricing Considerations

QR code APIs typically charge per code or per scan:

ModelBest For
Per-code pricingHigh-volume generation, low scan rates
Per-scan pricingLow-volume generation, high scan rates
SubscriptionPredictable, steady usage
HybridFlexible usage patterns

Calculate your expected costs before committing to a provider.

Choosing an API Provider

Look for:

  • Reliability: High uptime SLA (99.9%+)
  • Speed: Low latency generation
  • Documentation: Clear, complete API docs
  • Support: Responsive technical support
  • Flexibility: Pay-per-use or subscription options

Avoid providers that:

  • Lock you into annual contracts
  • Charge hidden fees
  • Have unclear rate limits
  • Lack proper API documentation

Summary

A dynamic QR code API enables:

  1. Programmatic generation at scale
  2. Full scan tracking and analytics
  3. Editable destinations after creation
  4. Integration into any workflow

For developers building applications that need QR codes, an API is the most flexible and scalable approach.


Ready to integrate? Check out our API documentation and start generating codes in minutes.

Ready to get started?

Create your free account and start generating QR codes in minutes.