Developers · Pro
QR API
Create QR codes from your own app. Send the content and a design, and get back the same PNG or SVG file that Download gives in the editor.
POSThttps://pretty-qr.com/api/v1/qr
Quick start
- The API is part of Pretty QR Pro. Sign in with your Pro account.
- Create a key on the API keys page and keep it somewhere safe: it is shown once.
- Set it as
PRETTY_QR_KEYand send your first request. This one savesqr.png:
curl https://pretty-qr.com/api/v1/qr \
-H "Authorization: Bearer $PRETTY_QR_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "https://example.com",
"design": {
"backgroundColor": "#ffffff",
"foregroundStyle": {
"colors": [
"#000000"
]
}
},
"format": "png"
}' \
-o qr.pngAuthentication
Send the key as a bearer token: Authorization: Bearer pqr_…. A key works while its account has Pro. Treat it like a password: keep it on your server, never in a web page or app that others can download. You can revoke a key on the API keys page at any time; you can have up to 10.
Request
POST /api/v1/qr with a JSON body of three fields. Everything about the look lives in design, which uses the same options as the editor.
contentstringrequired- What the code encodes: a URL or any text. At most 2331 bytes (UTF-8), or 1273 with a logo or the shield shape.
formatstringrequiredpng(2048 × 2048 px) orsvg.designobjectrequired- How the code looks. Unknown fields are refused with a 400, so a typo never gives a different code.
designstringrequired.backgroundColor - Background colour as
#rrggbb. designstring[]required.foregroundStyle .colors - Module colour as
#rrggbb. Accepts 1 to 5 colours; only the first is drawn until gradients launch. designstring.foregroundStyle .type - Gradient type:
linear,radial. designstring.foregroundStyle .direction - Gradient direction:
top-bottom,left-right,top-left-bottom-right,top-right-bottom-left. designstring.moduleShape square,circle,rounded,dot. Defaultsquare.designstring.eyeShape - Shape of the three corner squares:
square,circle,rounded. Defaultsquare. designnumber.cornerRadius - Rounds the code's background, 0 to 1000.
designstring.shape .type - Silhouette:
square,circle,heart,shield,house,pin. Silhouettes hold at most 213 bytes of content (119 with a logo or the shield). designobject | null.logo - A logo in the middle of the code. Omit it or send
nullfor none. designstringrequired.logo .src - Base64 data URL of a PNG, JPEG, WebP or SVG image. SVGs must not reference external files or contain scripts.
designnumberrequired.logo .size - Share of the code's width, 0.1 to 0.5.
designnumberrequired.logo .margin - Space around the logo, 0 to 50.
designbooleanrequired.logo .hideBackgroundDots - Clear the modules behind the logo.
designobject | null.frame - A frame around the code. Omit it or send
nullfor none. designtruerequired.frame .enabled - Always
true. designstringrequired.frame .type rectangle,speech-bubble,banner,shopping-bag,coffee-cup.designnumberrequired.frame .borderWidth - 1 to 20.
designstringrequired.frame .borderColor #rrggbb.designnumberrequired.frame .padding - 8 to 48.
designnumberrequired.frame .cornerRadius - 0 to 50.
designobject.frame .text - Label:
{ "enabled": boolean, "content": string }, at most 24 characters. Shown on every frame exceptrectangle. designstring.frame .outerColor - Colour outside the frame,
#rrggbb.
Fields under design.logo and design.frame marked required are required only when you send that object.
Response and errors
A 200 is the file itself: image/png (2048 × 2048 px) or image/svg+xml. Anything else is JSON with one field, { "error": "…" }, a sentence that says what to fix.
| Status | When |
|---|---|
| 400Bad request | The body is not JSON, a field is unknown or out of range, the logo does not decode, or the content is too long for the chosen silhouette. |
| 401Unauthorized | No Authorization: Bearer header, or the key is unknown or revoked. |
| 403Forbidden | The account the key belongs to no longer has Pro. |
| 413Too large | The body is over 1 MB, or the content is over what a QR code holds. |
| 429Too many requests | Over 1,000 requests in the last hour or 10,000 this calendar month (UTC). Wait for the seconds in Retry-After. |
| 503Unavailable | The renderer is busy or restarting. Retry after a few seconds. |
Limits
- 1,000 requests in any hour and 10,000 per calendar month (UTC, resets on the 1st), per account across all its keys.
- Every request with a valid key counts, including ones that fail with 400 or 413.
- Request bodies up to 1 MB, logo included.
- Requests are rendered one after another. Send them in sequence rather than hundreds at once, and retry a
503after a few seconds.
Examples
Each image is what the request next to it returns. Start from one and change the fields you need.

curl https://pretty-qr.com/api/v1/qr \
-H "Authorization: Bearer $PRETTY_QR_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "https://example.com/menu",
"design": {
"backgroundColor": "#ffffff",
"foregroundStyle": {
"colors": [
"#4338ca"
]
},
"moduleShape": "rounded",
"eyeShape": "rounded",
"cornerRadius": 24,
"frame": {
"enabled": true,
"type": "banner",
"borderWidth": 8,
"borderColor": "#4338ca",
"padding": 16,
"cornerRadius": 16,
"text": {
"enabled": true,
"content": "SCAN ME"
}
}
},
"format": "png"
}' \
-o qr.png
curl https://pretty-qr.com/api/v1/qr \
-H "Authorization: Bearer $PRETTY_QR_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "https://example.com/love",
"design": {
"backgroundColor": "#111827",
"foregroundStyle": {
"colors": [
"#ffffff"
]
},
"moduleShape": "square",
"eyeShape": "rounded",
"logo": {
"src": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgcng9IjIyIiBmaWxsPSIjZWY0NDQ0Ii8+PGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iMjYiIGZpbGw9IiNmZmZmZmYiLz48cGF0aCBkPSJNMzggNTJsOCA4IDE2LTE4IiBmaWxsPSJub25lIiBzdHJva2U9IiNlZjQ0NDQiIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PC9zdmc+",
"size": 0.4,
"margin": 0,
"hideBackgroundDots": false
},
"frame": {
"enabled": true,
"type": "speech-bubble",
"borderWidth": 12,
"borderColor": "#ffffff",
"padding": 8,
"cornerRadius": 16,
"text": {
"enabled": true,
"content": "SCAN ME"
}
},
"shape": {
"type": "heart"
}
},
"format": "png"
}' \
-o qr.png
curl https://pretty-qr.com/api/v1/qr \
-H "Authorization: Bearer $PRETTY_QR_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "https://example.com/coffee",
"design": {
"backgroundColor": "#fdf2f8",
"foregroundStyle": {
"colors": [
"#312e81"
]
},
"moduleShape": "dot",
"eyeShape": "rounded",
"frame": {
"enabled": true,
"type": "coffee-cup",
"borderWidth": 12,
"borderColor": "#312e81",
"padding": 8,
"cornerRadius": 16,
"text": {
"enabled": true,
"content": "Scan for 10% off"
},
"outerColor": "#db2777"
},
"shape": {
"type": "circle"
}
},
"format": "png"
}' \
-o qr.pngPostman and OpenAPI
The Postman collection has every example on this page and the common errors, each with a test. To use it:
- In Postman, choose Import and drop in both the collection and the environment.
- Select the Pretty QR environment and paste your key into
apiKey. - Send a request. Use Send and Download to save the file.
The OpenAPI file describes the same request and responses. Import it into Insomnia, Bruno or any OpenAPI tool, or generate a client from it.
Questions or a field you need? Write to [email protected].