DEV Community

Cover image for I built a QR Code API and here's what I learned
Malachi Stark
Malachi Stark

Posted on

I built a QR Code API and here's what I learned

Last month I needed to generate QR codes server-side for a client project. I tried a few existing APIs and... wasn't thrilled. One charged $49/mo for basic features. Another had a 100-request limit before demanding a credit card. Most had SDKs that felt like they were written in 2012.

So I built my own. And then productized it.

The API

Dead simple. One endpoint:

curl "https://api.qrcodeapi.io/generate?data=https://dev.to&size=300"Returns a QR code. That's it.

Options:

  • format - png, svg, or base64
  • size - 100-1000px
  • color - hex color for the QR code
  • bgColor - hex color for background
  • errorCorrection - L, M, Q, or H

Purple QR code on transparent background

curl "https://api.qrcodeapi.io/generate?data=hello&color=8b5cf6&bgColor=transparent&format=svg"## The interesting parts

Dynamic QR Codes

This was the feature I actually needed. Print a QR code on 10,000 flyers, realize the URL has a typo? With static QR codes, you're reprinting.

With dynamic QR codes, the QR points to a redirect URL that you control. Change the destination anytime without reprinting anything.

// Create a dynamic link
const response = await fetch('https://api.qrcodeapi.io/links', {
method: 'POST',
headers: { 'X-API-Key': 'your-key' },
body: JSON.stringify({ url: 'https://example.com/campaign-v1' })
});

// Returns a short code like "abc123"
// QR code points to: https://qr.qrcodeapi.io/abc123

// Later, update the destination:
await fetch('https://api.qrcodeapi.io/links/abc123', {
method: 'PUT',
headers: { 'X-API-Key': 'your-key' },
body: JSON.stringify({ url: 'https://example.com/campaign-v2' })
});### Scan Analytics

Every scan through a dynamic link gets tracked:

  • Device type (mobile/tablet/desktop)
  • Country & city (via IP geolocation)
  • Referrer
  • Timestamp

No cookies, no fingerprinting - just basic HTTP request data. Privacy-respecting analytics.

const stats = await fetch('https://api.qrcodeapi.io/analytics/abc123', {
headers: { 'X-API-Key': 'your-key' }
});

// Returns:
// {
// totalScans: 1247,
// uniqueScans: 892,
// byDevice: { mobile: 743, desktop: 401, tablet: 103 },
// byCountry: { US: 521, UK: 234, DE: 189, ... },
// byDay: [{ date: '2025-12-15', scans: 87 }, ...]
// }## Tech Stack

For the curious:

  • Runtime: Vercel Serverless Functions
  • Database: Supabase (PostgreSQL)
  • QR Generation: qrcode npm package
  • Image Processing: sharp for logo overlays
  • Geo-IP: geoip-lite
  • Payments: Stripe

The whole thing is ~15 API endpoints consolidated into 9 serverless functions (Vercel Hobby plan has a 12-function limit πŸ˜…).

TypeScript SDK

Also published an npm package:

npm install qrcode-api-sdk
import { QRCodeAPI } from 'qrcode-api-sdk';

const client = new QRCodeAPI({ apiKey: 'your-key' });

// Generate QR code
const qr = await client.generate({
data: 'https://dev.to',
format: 'svg',
color: '#000000'
});

// Create dynamic link
const link = await client.links.create({
url: 'https://example.com'
});

// Get analytics
const stats = await client.analytics.get(link.shortCode);Full TypeScript types included.

Pricing

  • Free: 100 QR/month (no credit card)
  • Starter: $9/mo - 5,000 QR/month
  • Pro: $29/mo - 50,000 QR/month + analytics + dynamic links

I tried to price it where indie devs can actually afford it. The free tier is enough for most side projects.

What I'd do differently

  1. Start with dynamic QR codes first - That's what people actually pay for. Static QR generation is basically a commodity.

  2. Build the SDK earlier - Having a proper TypeScript SDK with types makes the DX so much better. Should've done this from day one.

  3. Don't underestimate SEO - Half my traffic comes from people googling "QR code API Node.js" or "dynamic QR code API". I spent a weekend building SEO landing pages and it was worth it.

Try it out

Would love feedback, especially on pricing and what features you'd want to see next. Thinking about adding:

  • Bulk generation endpoint (ZIP file with multiple QR codes)
  • QR code templates/styles
  • Webhook notifications for scan events

Let me know what would be useful! πŸ™

Top comments (0)