Create once. Update anytime.
Create a permanent scan link, turn it into a QR image, and change the destination without reprinting. All existing QuickChart API keys have access.
Create a code
Send your existing key in the Authorization header. Keep it on your server.
curl https://qr.quickchart.io/api/codes \
-H "Authorization: Bearer $QUICKCHART_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"name": "Summer menu",
"targetUrl": "https://example.com/menu",
"campaign": "Summer 2026",
"tags": ["menu", "in-store"],
"externalId": "menu-2026",
"appearance": {"size": 512, "dark": "175e35", "light": "ffffff"}
}'
A successful response returns HTTP 201 and {"success":true,"code":{...}}. The
code includes its id, scanUrl, imageUrl, destination,
appearance, tags, timestamps, and status. Print the image containing
scanUrl. Linking directly to the destination produces a static code.
Manage codes
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /api/codes |
List your codes |
| POST | /api/codes |
Create a code |
| GET | /api/codes/:id |
Read a code |
| PATCH | /api/codes/:id |
Update destination, name, appearance, tags, campaign, or external ID |
| GET | /api/codes/:id/image?format=svg |
Download PNG or SVG |
| POST | /api/codes/:id/pause |
Stop redirects temporarily |
| POST | /api/codes/:id/activate |
Resume redirects |
| POST | /api/codes/:id/archive |
Hide from the main list; keep redirects |
| POST | /api/codes/:id/restore |
Restore an archived code to the main list |
| DELETE | /api/codes/:id |
Permanently disable a code; cannot be undone |
curl -X PATCH https://qr.quickchart.io/api/codes/CODE_ID \
-H "Authorization: Bearer $QUICKCHART_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"targetUrl":"https://example.com/new-menu"}'
Destinations must be public HTTP or HTTPS URLs, at most 4,096 characters after URL encoding. Updates take effect on subsequent scans. Redirect responses are never cached. Codes do not expire automatically when a subscription ends. Pausing, deleting, or an abuse takedown can stop a code.
The account limit is one million undeleted codes; archived and paused codes count. An
externalId must be unique within your account, including previously deleted
codes. After an uncertain create response, search for that external ID before retrying.
List and search
Supported query parameters: q (name, destination, external ID, or code ID),
status=active|paused, campaign, tag,
archived=true, and limit (1–100, default 25). Pass the returned
nextCursor as cursor for another page. A null cursor means the
end.
Appearance
Images use the existing
QuickChart QR renderer. Store
renderer options in appearance: size, margin, dark/light colors, error
correction, logo URL and size, caption options, dot styles, and finder styles/colors. Use
centerImageUrl for a public logo URL. Size must be 100–3000 pixels. PNG and SVG
downloads use the same saved options. Codes with a logo must use PNG; the renderer does not
support embedded logos in SVG. Replacing appearance replaces the saved options; changing the
destination leaves them intact. Always scan-test before printing.
Scan analytics
curl 'https://qr.quickchart.io/api/analytics?days=30&codeId=CODE_ID' \
-H "Authorization: Bearer $QUICKCHART_API_KEY"
Use days=1|7|30|60 (default 7). Omit codeId for account totals.
Optional filters: campaign, tag, includeBots=true.
Add format=csv for export. Campaign and tag filters reflect the labels at scan
time.
Results include total scans, observed daily unique scans, scans by UTC day, last scan, top codes, and country/region/city, device, browser, operating system, referrer, and destination-host breakdowns. Previous-period comparison is available for windows up to 30 days; the total history window is 60 days.
A scan is a visit to the redirect link. Opening the link directly also counts; generating or
downloading an image does not. Known bots are excluded by default, but bot detection is
imperfect. Counts may be sampled and delayed. Daily unique scans count observed devices per
code per UTC day; they are not a count of distinct people across codes or days. When
summary.sampled is true, dailyUniqueScans counts only
devices observed in the sample and may undercount. Total scans are adjusted for sampling;
daily uniques are not extrapolated. The same flag is included in previous.
Location is approximate. No tracking cookies or raw scanner IPs are stored. Referrers are
reduced to hostnames and destination query strings are omitted from scan analytics.
Errors
Errors return JSON: {"success":false,"error":"..."}. HTTP 400 means invalid
input, 401 invalid authentication, 403 denied access, 404 an unavailable code, 409 a
conflicting external ID or code limit, 413 an oversized request, and 503 a temporarily
unavailable dependency. Retry temporary failures with backoff. Never expose API keys in
client-side JavaScript or URLs.