| name | qr-api |
| description | REST API integration for qr-code-generator. TypeScript request helpers, batch pipeline patterns, and server-side code examples for embedding QR generation into other applications. |
| triggers | ["qr api","generate qr programmatically","qr in my app","integrate qr generation","qr pipeline"] |
qr-api Skill
When to use
Use this skill when you need to call the qr-code-generator API from another service, script, or CI pipeline. This skill covers the TypeScript client, Node.js usage, and piping output.
Prerequisites
qr-code-generator server running. The QR_API_URL environment variable should point to it (e.g., http://localhost:3000).
TypeScript API client
import { z } from 'zod';
const QR_API = process.env.QR_API_URL ?? 'http://localhost:3000';
export type QRType = 'url' | 'text' | 'wifi' | 'vcard';
export type ErrorCorrection = 'L' | 'M' | 'Q' | 'H';
export type QRFormat = 'svg' | 'png';
export interface QRStyle {
fgColor?: string;
bgColor?: string;
errorCorrection?: ErrorCorrection;
margin?: number;
width?: number;
}
export interface QRRequest {
type: QRType;
data: Record<string, string | boolean | number>;
style?: QRStyle;
logo?: string | null;
format?: QRFormat;
}
export interface QRResponse {
svg: string;
dataUrl: string;
size: number;
}
export async function generateQR(req: QRRequest): Promise<QRResponse> {
const res = await fetch(`${QR_API}/api/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(req),
});
if (!res.ok) {
const body = await res.text();
throw new Error(`QR generation failed ${res.status}: ${body}`);
}
return res.json() as Promise<QRResponse>;
}
URL QR code
import { generateQR } from './lib/qr-client.ts';
import { writeFile } from 'node:fs/promises';
const result = await generateQR({
type: 'url',
data: { url: 'https://example.com' },
style: { width: 512, errorCorrection: 'M' },
format: 'svg',
});
await writeFile('qrcode.svg', result.svg, 'utf8');
WiFi QR code
const result = await generateQR({
type: 'wifi',
data: {
ssid: 'OfficeNetwork',
password: 'supersecret',
security: 'WPA',
hidden: false,
},
format: 'svg',
});
vCard QR code
const result = await generateQR({
type: 'vcard',
data: {
firstName: 'Jane',
lastName: 'Smith',
org: 'Acme Corp',
title: 'Product Manager',
phone: '+1-555-0100',
email: 'jane@acme.com',
url: 'https://acme.com',
},
style: { errorCorrection: 'Q' },
format: 'svg',
});
PNG output to buffer
import { generateQR } from './lib/qr-client.ts';
import { writeFile } from 'node:fs/promises';
const result = await generateQR({
type: 'url',
data: { url: 'https://example.com' },
style: { width: 1024 },
format: 'png',
});
const base64 = result.dataUrl.split(',')[1];
const buffer = Buffer.from(base64, 'base64');
await writeFile('qrcode.png', buffer);
Bulk generation from JSON
import FormData from 'form-data';
import { createReadStream } from 'node:fs';
import { writeFile } from 'node:fs/promises';
const QR_API = process.env.QR_API_URL ?? 'http://localhost:3000';
async function bulkFromJSON(codes: Array<{ data: string; filename: string; fgColor?: string }>) {
const res = await fetch(`${QR_API}/api/bulk`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ codes, format: 'svg' }),
});
if (!res.ok) throw new Error(`Bulk failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
await writeFile('qrcodes.zip', buffer);
}
Bulk generation from CSV file
import { readFile, writeFile } from 'node:fs/promises';
async function bulkFromCSV(csvPath: string) {
const csvBuffer = await readFile(csvPath);
const form = new FormData();
form.append('csv', csvBuffer, { filename: 'codes.csv', contentType: 'text/csv' });
const res = await fetch(`${QR_API}/api/bulk`, {
method: 'POST',
headers: form.getHeaders(),
body: form.getBuffer(),
});
if (!res.ok) throw new Error(`Bulk failed: ${res.status}`);
await writeFile('qrcodes.zip', Buffer.from(await res.arrayBuffer()));
}
Express middleware: generate QR on the fly
import { Router } from 'express';
import { generateQR } from './lib/qr-client.ts';
const router = Router();
router.get('/qr', async (req, res) => {
const url = String(req.query.url ?? '');
const format = req.query.format === 'png' ? 'png' : 'svg';
if (!url.startsWith('http')) {
return res.status(400).json({ error: 'Invalid url parameter' });
}
const result = await generateQR({ type: 'url', data: { url }, format });
if (format === 'png') {
const base64 = result.dataUrl.split(',')[1];
res.setHeader('Content-Type', 'image/png');
return res.send(Buffer.from(base64, 'base64'));
}
res.setHeader('Content-Type', 'image/svg+xml');
res.send(result.svg);
});
export { router };
CI pipeline: generate QR codes for releases
#!/usr/bin/env bash
set -euo pipefail
VERSION="${1:-latest}"
BASE_URL="https://releases.example.com/$VERSION"
QR_API="${QR_API_URL:-http://localhost:3000}"
for PLATFORM in linux macos windows; do
URL="$BASE_URL/download/$PLATFORM"
FILENAME="release-${VERSION}-${PLATFORM}"
curl -s -X POST "$QR_API/api/generate" \
-H 'Content-Type: application/json' \
-d "{\"type\":\"url\",\"data\":{\"url\":\"$URL\"},\"style\":{\"width\":512},\"format\":\"svg\"}" \
| jq -r '.svg' > "dist/qr/${FILENAME}.svg"
echo "Generated $FILENAME.svg"
done
Environment variables
Error handling
import { generateQR } from './lib/qr-client.ts';
async function safeGenerate(url: string) {
try {
const result = await generateQR({
type: 'url',
data: { url },
format: 'svg',
});
return result.svg;
} catch (err) {
if (err instanceof Error && err.message.includes('400')) {
console.error('Invalid request:', err.message);
} else if (err instanceof Error && err.message.includes('429')) {
console.error('Rate limited. Retry after 60 seconds.');
} else {
throw err;
}
return null;
}
}
Rate limits
The server enforces RATE_LIMIT_RPM requests per minute per IP (default 60). For bulk jobs, the single /api/bulk call counts as one request regardless of how many codes are generated.