API documentation

Create QR codes programmatically. Generate an API key from your dashboard first — the raw key is shown once at creation time, so save it somewhere safe. Want an AI tool to do this for you instead of writing requests by hand? See the MCP server.

Authentication

Every request must include your API key as a Bearer token in the Authorization header:

Authorization: Bearer qrd_live_<your key>

A missing or malformed header returns 401. An unknown or revoked key also returns 401 with { "error": "Invalid or revoked API key" }.

API access itself requires the $30/mo plan or higher — a valid, non-revoked key belonging to a Free or $10/mo account still gets 403:

{ "error": "API access requires the $30/mo plan or higher" }

Rate limits

Rate limit depends on your plan: 60 requests/minute on $30/mo, 300 requests/minute on $50/mo. Exceeding it returns 429 with a Retry-After header (seconds) and:

{ "error": "Rate limit exceeded: max 60 requests per 60s" }

POST /api/v1/qr

Creates a QR code. Body fields:

FieldTypeRequiredNotes
type"url" | "wifi" | "vcard"yesWhich payload shape to encode.
dynamicbooleannoDefaults to true. Dynamic codes redirect through /q/<code>, track scans, and count against your plan's dynamic QR limit. Static codes encode the payload directly and aren't tracked or limited.
payloadobjectyesShape depends on type — see examples below.
styleobjectno{ foregroundColor?, backgroundColor?, logoDataUrl? } — hex colors and/or a base64 data: URL logo. Requires the $10/mo plan or higher; a logo automatically raises error correction to High so the code still scans.
aliasstringnoCustom short code for a dynamic QR code instead of a random one. Must be unique.
labelstringnoName shown in the dashboard, up to 80 characters.
expiresAtstringnoISO date string after which a dynamic code stops resolving.

If your account has an active custom domain, dynamic codes created here encode that domain instead of the shared app domain.

Example: dynamic URL QR code

curl -X POST https://your-domain.example/api/v1/qr \
  -H "Authorization: Bearer qrd_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "url",
    "dynamic": true,
    "payload": { "destination": "https://example.com" }
  }'

Example: static WiFi QR code

curl -X POST https://your-domain.example/api/v1/qr \
  -H "Authorization: Bearer qrd_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "wifi",
    "dynamic": false,
    "payload": { "ssid": "CoffeeShop", "password": "brew1234", "security": "WPA3", "hidden": false }
  }'

Success response — 200

The generated PNG is returned inline as a base64 data URL, so there's no separate image-fetch round trip. Dynamic codes also include the record id and shortCode:

{
  "id": "6f2c9a3e-...-c9ab",
  "shortCode": "aB3xY9",
  "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}

Error responses

  • 400 — invalid payload for the given type.
  • 401 — missing/malformed/invalid/revoked API key.
  • 403 — API access requires $30/mo+, custom styling requires $10/mo+, or your plan's dynamic QR code limit is reached.
  • 409 — the requested alias is already taken.
  • 429 — rate limit exceeded for this key.

Other endpoints

All authenticated the same way as above, and subject to the same rate limit.

EndpointWhat it does
GET /api/v1/qrLists every QR code owned by the key's account.
GET /api/v1/qr/<id>Fetches one QR code by id.
PATCH /api/v1/qr/<id>Edits a dynamic code's payload, label, expiresAt, or password — only fields you include are changed. Static codes can't be edited.
DELETE /api/v1/qr/<id>Deletes a QR code. Its short URL stops resolving immediately.
POST /api/v1/qr/bulkCreates many codes at once from CSV text in the csv field, with an optional shared style. Requires the $30/mo plan or higher. Max 500 data rows per request.