QRQR Code Agency
API reference

POST /api/v1/generate/

Render a single QR and return its PNG or SVG bytes. Every parameter, every header, every response code.

POST /api/v1/generate/

Render a QR code and return its PNG or SVG bytes.

Endpoint

POST /api/v1/generate/
Host: api.qrstudio.agency
X-Api-Key: smk_...
Content-Type: application/json

For logo or background-image uploads, use multipart instead:

POST /api/v1/generate/
Host: api.qrstudio.agency
X-Api-Key: smk_...
Content-Type: multipart/form-data

Body parameters

Payload (what to encode)

FieldTypeRequiredDefaultDescription
datastringfor url and textn/aRaw URL or text. Max 2 048 chars.
data_typeenum"url"url, text, vcard, wifi, email, sms, geo, dynamic
payloadobjectfor non-url/text typesn/aStructured payload. Schema depends on data_type.

For url and text, just pass data. For all others, build a payload object - see Data types.

Output format and dimensions

FieldTypeRequiredDefaultDescription
formatenum"png"png or svg
size_inchesnumberyesn/a0.5 to 15. Plan capped.
dpiinteger30072 to 600. Plan capped.

Pixel size = size_inches x dpi. So 4 inches at 300 DPI = 1 200 x 1 200 px.

Style

FieldTypeRequiredDefaultDescription
colorstring"black"black, white, or #RRGGBB[AA]
backgroundstring"transparent"Same as color, plus "transparent"
patternenum"rounded"rounded, squares, dot, diamond, liquid, connected-h, connected-v, hexagon, star, halftone, frame
gradient_fromhexn/aTop stop of vertical gradient (must pair with gradient_to)
gradient_tohexn/aBottom stop of vertical gradient

Eye styling

FieldTypeDefaultDescription
eye_shapeenum"square"Coarse knob: square, rounded, circle, frame
eye_colorhexinherits colorCustom eye color
eye_outer_frameboolfalseAdd a subtle outer ring
eye_outer_frame_matchboolfalseMatch the outer ring to the eye color
eye_border_shapeenumderivedsquare, rounded, circle, leaf-tl, leaf-tr, leaf-br, leaf-bl, frame
eye_center_shapeenumderivedsquare, rounded, circle, leaf-tl, sunburst, star, diamond, cross
eye_border_colorhexderivedIndependent border color
eye_center_colorhexderivedIndependent center color

Frame

FieldTypeDefaultDescription
frame_styleenum"none"none, rounded, scan-me-top, scan-me-bottom, wave, topo, botanical
frame_colorhex#6c48e8Frame fill color
frame_labelstringemptyUp to 24 chars, shown in scan-me-* styles
frame_label_colorhex#ffffffLabel text color

Logo (optional, Starter+ only)

FieldTypeDefaultDescription
logo_filefilen/aMultipart upload. Max 2 MB, max 1024 x 1024 px.
logo_urlURLn/aHTTPS URL we fetch. SSRF protected.
logo_size_rationumber0.240.0 to 0.30. Logo diameter as fraction of QR.
logo_clear_zonebooltrueCarve a clean zone behind the logo.
logo_neon_alphaboolfalseStrip dark backings via luminance alpha.

You can supply either logo_file or logo_url, not both. Custom logos require Starter plan or higher.

Background image (optional, Starter+ only)

FieldTypeDefaultDescription
bg_image_filefilen/aMultipart upload, painted under the modules
bg_image_urlURLn/aHTTPS URL, SSRF protected
bg_image_opacitynumber0.350.0 to 1.0

Pair with pattern: "halftone" for the photo-revealed-through-dots effect.

Response

Success: 200 OK

HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 59143
X-QR-Cache: MISS
X-QR-Duration-Ms: 318
X-QR-Plan: starter
X-QR-Quota-Remaining: 487
X-Request-Id: 01HZ8X...

<binary PNG bytes>

The body is the raw image. Save it directly, stream it, or pipe to S3.

For dynamic items (data_type: "dynamic") the response also adds:

X-QR-Dynamic-Short-Id: aBc12dEf
X-QR-Dynamic-Public-Url: https://q.qrstudio.agency/q/aBc12dEf/

400 Bad Request

Validation failure. Body is JSON describing the bad fields:

{
 "size_inches": ["Ensure this value is less than or equal to 15."],
 "logo_url": "refusing to fetch evil.com: resolves to private/internal IP 10.0.0.5"
}

401 Unauthorized

Missing or invalid X-Api-Key.

{ "detail": "Invalid or revoked API key." }

403 Forbidden

Your plan does not allow what you asked for.

{ "detail": "Plan 'free' allows up to 3\". Upgrade for larger sizes." }

429 Too Many Requests

Monthly quota exhausted (Free / Enterprise) or rate limit exceeded.

{ "detail": "Monthly quota of 5 exceeded for plan 'free'." }

500 Internal Server Error

Render engine failed. Rare, retry once with backoff. If it persists, include X-Request-Id in your support ticket.

Validate

Same body schema as /generate/, but it only validates and returns the parsed payload. No image is rendered, no quota is spent.

POST /api/v1/validate/
X-Api-Key: smk_...
Content-Type: application/json
{
 "data": "https://example.com",
 "size_inches": 4,
 "color": "rouge"
}

Response (validation failure):

{
 "color": "Invalid color 'rouge'. Use 'black', 'white', or hex like #RRGGBB / #RRGGBBAA."
}

Useful for client-side form validation before charging quota.

Examples

Minimal

curl -X POST https://api.qrstudio.agency/api/v1/generate/ \
 -H "X-Api-Key: smk_..." \
 -H "Content-Type: application/json" \
 -d '{"data": "https://example.com", "size_inches": 4}' \
 --output qr.png
{
 "data": "https://yourbrand.com",
 "size_inches": 8,
 "color": "white",
 "background": "transparent",
 "pattern": "rounded",
 "logo_url": "https://cdn.yourbrand.com/logo.png",
 "logo_neon_alpha": true,
 "logo_clear_zone": true,
 "format": "png"
}

Wi-Fi poster as SVG

{
 "data_type": "wifi",
 "payload": {
 "ssid": "Cafe Plein Soleil",
 "password": "BienvenueChezNous2026",
 "auth": "WPA"
 },
 "size_inches": 8,
 "color": "#0d0820",
 "background": "white",
 "format": "svg"
}

vCard business card

{
 "data_type": "vcard",
 "payload": {
 "name": "Darius Tokam",
 "org": "QR Code Agency",
 "phone": "+15145551234",
 "email": "darius@qrstudio.agency",
 "url": "https://qrstudio.agency"
 },
 "size_inches": 2,
 "color": "black"
}

Dynamic QR

{
 "data_type": "dynamic",
 "payload": {
 "name": "Spring 2026 menu",
 "destination_url": "https://example.com/menus/spring-2026"
 },
 "size_inches": 6
}

Gradient with frame

{
 "data": "https://yourbrand.com",
 "size_inches": 6,
 "background": "white",
 "pattern": "rounded",
 "gradient_from": "#6c48e8",
 "gradient_to": "#1a0d3a",
 "eye_color": "#1a0d3a",
 "frame_style": "scan-me-bottom",
 "frame_color": "#6c48e8",
 "frame_label": "Scan to view menu"
}

Halftone over a photo

{
 "data": "https://yourbrand.com",
 "size_inches": 6,
 "background": "white",
 "color": "#0d0820",
 "pattern": "halftone",
 "bg_image_url": "https://cdn.yourbrand.com/coffee.jpg",
 "bg_image_opacity": 0.45
}

Notes

  • All requests must use HTTPS in production. HTTP is allowed only on localhost.
  • Maximum request body: 5 MB (covers logo and background uploads).
  • The data string is encoded as UTF-8 before being passed to the QR generator.
  • ERROR_CORRECT_H is hardcoded and not tunable. This gives you a 30% obstruction tolerance, which the logo never exceeds.

See also

On this page