I built a QR Code API and here's what I learned
Source: Dev.to

The API
Dead simple. One endpoint:
GET https://api.qrcodeapi.io/generate?data=&size=
It returns a QR code image.
Options
| Parameter | Values |
|---|---|
format | png, svg, or base64 |
size | 100‑1000 px |
color | Hex color for the QR code (e.g. #8b5cf6) |
bgColor | Hex color for background (or transparent) |
errorCorrection | L, M, Q, or H |
Example (purple QR code on transparent background)
curl "https://api.qrcodeapi.io/generate?data=hello&color=8b5cf6&bgColor=transparent&format=svg"
Dynamic QR Codes
Static QR codes are fine until you need to change the destination URL—then you have to reprint everything. Dynamic QR codes point to a redirect URL you control, so you can change the target anytime without touching the printed QR.
Create a dynamic link
// 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
Update the destination later
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 of a dynamic link is tracked:
- Device type (mobile/tablet/desktop)
- Country & city (via IP geolocation)
- Referrer
- Timestamp
No cookies, no fingerprinting—just basic HTTP request data, respecting privacy.
const stats = await fetch('https://api.qrcodeapi.io/analytics/abc123', {
headers: { 'X-API-Key': 'your-key' }
});
// Example response:
{
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
- Runtime: Vercel Serverless Functions
- Database: Supabase (PostgreSQL)
- QR Generation:
qrcodenpm 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
An npm package is also published:
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 are included.
Pricing
| Plan | Price | QR codes / month | Features |
|---|---|---|---|
| Free | $0 | 100 (no credit card) | Basic generation |
| Starter | $9/mo | 5,000 | Dynamic links |
| Pro | $29/mo | 50,000 | Analytics + dynamic links |
The free tier is enough for most side projects; the paid tiers are priced for indie developers.
What I’d Do Differently
- Start with dynamic QR codes first – that’s what people actually pay for. Static generation is a commodity.
- Build the SDK earlier – a proper TypeScript SDK with types dramatically improves developer experience.
- Don’t underestimate SEO – half my traffic comes from searches like “QR code API Node.js” or “dynamic QR code API”. Investing a weekend in SEO landing pages paid off.
Try It Out
- 🌐 Website:
- 📚 Documentation:
- 📦 npm package:
I’d love feedback, especially on pricing and feature ideas. I’m considering:
- 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! 🙏