QRQR Code Agency
Getting started

Quickstart

Generate your first QR code with QR Code Agency in five minutes.

Quickstart

Generate your first QR code in five minutes. By the end of this page, you will have a PNG on disk, you will know how to add a logo, and you will know how to check your remaining quota.

Before you start

You will need:

  • An API key starting with smk_ (see Authentication)
  • An HTTP client (curl, Postman, your language of choice)

info: Base URL Production: https://api.qrstudio.agency Local development: http://localhost:8000

Examples below use the production host. Swap if you are running the backend locally.

Step 1: Make your first call

Generate a 4 inch black QR on a white background pointing at https://example.com.

cURL

curl -X POST https://api.qrstudio.agency/api/v1/generate/ \
-H "X-Api-Key: smk_REPLACE_WITH_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": "https://example.com",
"size_inches": 4,
"color": "black",
"background": "white"
}' \
--output my-first-qr.png

Python

import requests

r = requests.post(
"https://api.qrstudio.agency/api/v1/generate/",
headers={"X-Api-Key": "smk_REPLACE_WITH_YOUR_KEY"},
json={
"data": "https://example.com",
"size_inches": 4,
"color": "black",
"background": "white",
},
timeout=30,
)
r.raise_for_status()
with open("my-first-qr.png", "wb") as f:
f.write(r.content)
print("Saved to my-first-qr.png")

JavaScript

const r = await fetch("https://api.qrstudio.agency/api/v1/generate/", {
method: "POST",
headers: {
"X-Api-Key": "smk_REPLACE_WITH_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
data: "https://example.com",
size_inches: 4,
color: "black",
background: "white",
}),
});
if (!r.ok) throw new Error(`HTTP ${r.status}`);

// In a browser: display it
const url = URL.createObjectURL(await r.blob());
document.querySelector("img").src = url;

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_REPLACE_WITH_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ data: "https://example.com", size_inches: 4 }),
});
fs.writeFileSync("my-first-qr.png", Buffer.from(await r.arrayBuffer()));

Open my-first-qr.png. You should see a clean QR code. Scan it with your phone, the camera opens example.com.

success: What just happened You sent a JSON payload describing the QR. We rendered it server-side at 1200 x 1200 px (4 inches x 300 DPI), embedded ERROR_CORRECT_H so it stays scannable, ran it through the render cache, and returned the PNG bytes. The headers X-QR-Cache, X-QR-Plan, and X-QR-Quota-Remaining tell you the rest.

Drop your brand logo into the center. ERROR_CORRECT_H gives you up to 30% obstruction tolerance, so a logo at the default 24% size is always scannable.

cURL

curl -X POST https://api.qrstudio.agency/api/v1/generate/ \
-H "X-Api-Key: smk_REPLACE_WITH_YOUR_KEY" \
-F "data=https://example.com" \
-F "size_inches=4" \
-F "color=black" \
-F "background=white" \
-F "logo_file=@/path/to/your/logo.png" \
--output qr-with-logo.png

Python

import requests

with open("logo.png", "rb") as logo:
r = requests.post(
"https://api.qrstudio.agency/api/v1/generate/",
headers={"X-Api-Key": "smk_REPLACE_WITH_YOUR_KEY"},
data={
"data": "https://example.com",
"size_inches": 4,
"color": "black",
"background": "white",
},
files={"logo_file": logo},
timeout=60,
)
r.raise_for_status()
open("qr-with-logo.png", "wb").write(r.content)

note: Logo limits

  • Maximum file size: 2 MB
  • Maximum dimensions: 1024 x 1024 px (auto downscaled if larger)
  • PNG with transparent background works best
  • Custom logos require Starter plan or higher

Step 3: Try a different data type

QR codes encode more than URLs. Generate a one-tap Wi-Fi join QR for your cafe:

curl -X POST https://api.qrstudio.agency/api/v1/generate/ \
 -H "X-Api-Key: smk_REPLACE_WITH_YOUR_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "data_type": "wifi",
 "payload": {
 "ssid": "Cafe WiFi",
 "password": "WelcomeGuest2026",
 "auth": "WPA"
 },
 "size_inches": 4,
 "format": "svg"
 }' \
 --output cafe-wifi.svg

When customers scan it, their phone offers to join your network with no password typing. See Data types for vCard, geo, email, SMS, and more.

Step 4: Make it dynamic

Static QRs encode a URL forever. Dynamic QRs encode a short URL we host: once printed, you can repoint the destination any time.

curl -X POST https://api.qrstudio.agency/api/v1/generate/ \
 -H "X-Api-Key: smk_REPLACE_WITH_YOUR_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "data_type": "dynamic",
 "payload": {
 "name": "Spring 2026 menu",
 "destination_url": "https://example.com/menus/spring-2026"
 },
 "size_inches": 4
 }' \
 --output menu-qr.png

The PNG you get back encodes https://q.qrstudio.agency/q/<short_id>/. Print it. Six months later, change the destination from your dashboard, no reprint required. See Static vs dynamic for the trade-offs.

Step 5: Check your usage

You have a monthly quota. Read it with:

curl https://api.qrstudio.agency/api/v1/usage/ \
 -H "X-Api-Key: smk_REPLACE_WITH_YOUR_KEY"
{
 "key_prefix": "smk_aBc1",
 "plan": "starter",
 "monthly_quota": 500,
 "used_this_month": 12,
 "remaining": 488,
 "max_size_inches": 8,
 "max_dpi": 300,
 "allow_custom_logo": true,
 "max_active_dynamic_qrs": 10,
 "max_bulk_items": 50
}

The same numbers come back as response headers on every successful /generate/ call (X-QR-Quota-Remaining, X-QR-Plan).

Common pitfalls

warning: 401 Unauthorized Your X-Api-Key header is missing or wrong. Make sure the key starts with smk_ and has not been revoked.

warning: 403 Forbidden Your plan does not allow what you asked for. Examples:

  • Free caps size_inches at 3
  • Free and Starter cap dpi at 300
  • Free does not allow custom logos
  • Free does not allow bulk generation

See Plans and limits for the full table.

warning: 429 Too Many Requests You used your monthly quota. On Starter and Pro, overage is allowed and billed per unit; on Free and Enterprise, you wait for the 1st of next month or upgrade.

What is next

Manage your keys: rotate, revoke, scope per environment.

vCard, Wi-Fi, email, SMS, geo, and dynamic encoding rules.

Colors, gradients, eye shapes, frames, transparent backgrounds.

Every parameter, every response code, every header.

On this page