QRQR Code Agency

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.

Styling

  • 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.

Static vs dynamic

  • 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.

Bulk endpoint

  • 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.

Webhooks reference

  • 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.

Security model

  • 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.

Print quality guide


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-Remaining

For 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.png

Python

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.

Quickstart

  • Building a feature

Already have a key, need parameter docs, response shapes, error codes.

API reference

  • Learning the model

Why dynamic over static? When does the cache help? How do logos avoid breaking scans? The conceptual material lives here.

Concepts

  • 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.

Guides


Production endpoints

ServiceURLPurpose
APIhttps://api.qrstudio.agencyAll /api/v1/* endpoints
Scan redirecthttps://q.qrstudio.agency/q/<short_id>/Public dynamic QR target
Dashboardhttps://qrstudio.agencyWeb UI for keys, billing, analytics
Statushttps://status.qrstudio.agencyLive uptime and incidents
Docshttps://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.agency with your X-QR-Plan header 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.

On this page