QR Code Agency Developer Docs
Build with QR Code Agency. Generate premium static and dynamic QR codes over a paid HTTP API.
Build with QR Code Agency
The print-once, edit-forever QR platform. Render static and dynamic QR codes, deliver them as PNG or SVG, swap their destination after print, and watch the scans come in. One JSON endpoint, one API key, one bill.
Quickstart in 5 minutes See the API reference
What you can build
- Premium QR rendering
Rounded modules, square finders, gradients, eye styling, brand-colored frames, optional centered logo, transparent backgrounds. PNG up to 9000 x 9000 px or scalable SVG.
- Dynamic QRs
Print the QR once. Repoint it to any URL after print, anytime, with no reprint required. Built-in scan analytics broken down by day, country, referer, device.
- Bulk generation
Render up to 5000 QRs in a single call. Get back a ZIP archive plus a
manifest.json describing every item. All-or-nothing batches keep your
quota accounting predictable.
- Scan webhooks
Subscribe to scan.created, quota.threshold_75, and more. We POST a
HMAC-SHA256 signed payload to your URL the moment the event fires.
- Production grade
Per-key SHA-256 hashed authentication, atomic monthly quotas, content
addressed render cache, SSRF protection on every fetched URL,
Cache-Control: no-store on dynamic redirects.
- Print ready
Up to 15 inches at 600 DPI on Pro. Quiet zone preserved. ERROR_CORRECT_H keeps logos scannable. Field-tested presets for stickers, posters, business cards, and storefront windows.
How it works
sequenceDiagram
participant Client
participant API as api.qrstudio.agency
participant Cache as Render cache
participant Engine as Render engine
participant DB as Postgres
Client->>API: POST /api/v1/generate/<br/>X-Api-Key: smk_...
API->>API: Authenticate, resolve plan, check quota
API->>Cache: Look up by content hash
alt Cache hit
Cache-->>API: PNG bytes (~0 ms)
else Cache miss
API->>Engine: Render
Engine-->>API: PNG bytes
API->>Cache: Store (24 h TTL)
end
API->>DB: Atomic quota increment + audit row
API-->>Client: 200 OK + image bytes<br/>X-QR-Cache, X-QR-Quota-RemainingFor dynamic QRs the same call also creates a DynamicQr row and encodes
https://q.qrstudio.agency/q/<short_id>/. Every scan goes through that
short URL, gets logged with country and device, and is 302 redirected to
the live destination.
A 30-second example
cURL
curl -X POST https://api.qrstudio.agency/api/v1/generate/ \
-H "X-Api-Key: smk_yOuRkEyHeRe" \
-H "Content-Type: application/json" \
-d '{
"data": "https://yourbusiness.com",
"size_inches": 4,
"color": "black",
"background": "white"
}' \
--output qr.pngPython
import requests
r = requests.post(
"https://api.qrstudio.agency/api/v1/generate/",
headers={"X-Api-Key": "smk_yOuRkEyHeRe"},
json={
"data": "https://yourbusiness.com",
"size_inches": 4,
"color": "black",
"background": "white",
},
timeout=30,
)
r.raise_for_status()
open("qr.png", "wb").write(r.content)JavaScript
const r = await fetch("https://api.qrstudio.agency/api/v1/generate/", {
method: "POST",
headers: {
"X-Api-Key": "smk_yOuRkEyHeRe",
"Content-Type": "application/json",
},
body: JSON.stringify({
data: "https://yourbusiness.com",
size_inches: 4,
color: "black",
background: "white",
}),
});
if (!r.ok) throw new Error(`HTTP ${r.status}`);
const blob = await r.blob();Node.js
import fs from "node:fs";
const r = await fetch("https://api.qrstudio.agency/api/v1/generate/", {
method: "POST",
headers: {
"X-Api-Key": "smk_yOuRkEyHeRe",
"Content-Type": "application/json",
},
body: JSON.stringify({ data: "https://yourbusiness.com", size_inches: 4 }),
});
fs.writeFileSync("qr.png", Buffer.from(await r.arrayBuffer()));C#
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", "smk_yOuRkEyHeRe");
var payload = new {
data = "https://yourbusiness.com",
size_inches = 4,
color = "black",
};
var resp = await http.PostAsJsonAsync(
"https://api.qrstudio.agency/api/v1/generate/", payload);
resp.EnsureSuccessStatusCode();
await File.WriteAllBytesAsync("qr.png", await resp.Content.ReadAsByteArrayAsync());Go
body := strings.NewReader(`{"data":"https://yourbusiness.com","size_inches":4}`)
req, _ := http.NewRequest("POST", "https://api.qrstudio.agency/api/v1/generate/", body)
req.Header.Set("X-Api-Key", "smk_yOuRkEyHeRe")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
out, _ := os.Create("qr.png")
io.Copy(out, resp.Body)The response body is the binary image. Stream it to disk, push it to S3,
or pipe it straight into an <img> tag.
Pick your path
- New here
Fresh integration, no key yet, want to see something work in five minutes.
- Building a feature
Already have a key, need parameter docs, response shapes, error codes.
- Learning the model
Why dynamic over static? When does the cache help? How do logos avoid breaking scans? The conceptual material lives here.
- Walking through a use case
Step-by-step playbooks for cafe Wi-Fi posters, business cards, print campaigns with analytics, ZIP exports, and scan webhooks.
Production endpoints
| Service | URL | Purpose |
|---|---|---|
| API | https://api.qrstudio.agency | All /api/v1/* endpoints |
| Scan redirect | https://q.qrstudio.agency/q/<short_id>/ | Public dynamic QR target |
| Dashboard | https://qrstudio.agency | Web UI for keys, billing, analytics |
| Status | https://status.qrstudio.agency | Live uptime and incidents |
| Docs | https://qrstudio.agency/docs/ | This site |
All traffic is HTTPS only. HTTP is allowed on localhost for development.
What is QR Code Agency built on
- Django 5 + Django REST Framework for the API surface
- Pillow + qrcode for the render pipeline (rounded modules, gradients, eye styling, frame decorations, logo composition)
- Postgres for keys, plans, dynamic QRs, scan audit, webhook deliveries
- Redis for the 24 hour content-addressed render cache (LocMem in dev)
- Stripe for subscriptions, credit packs, and metered overage billing
You do not need to know any of this to ship. Read the quickstart and the API reference, pick a plan, and start.
tip: Stuck on something? Email
support@qrstudio.agencywith yourX-QR-Planheader value and the request payload that misbehaved. We answer within one business day on Starter, four hours on Pro, one hour on Agency, and 15 minutes on Enterprise.