Core Resource • QR Code Lifecycle

QR Codes API Reference

Programmatically generate static and dynamic QR codes, customize dot palettes and embedded branding, re-target destination URLs post-print, and access destination version history.

Static vs Dynamic Commercial Boundary

Static QRs: Directly encode destination content into the QR matrix. 0 credits deducted, unlimited creation, free forever. Destination URLs cannot be edited post-print and scans are not tracked.

Dynamic QRs: Route through QRnaly managed shortlinks (qrnaly.com/q/{slug}). Consumes 1 Dynamic QR capacity. Enables real-time destination re-targeting and scan telemetry.

Dynamic Update Accounting

Editing a live dynamic QR destination URL or restoring a prior destination version consumes 1 Dynamic Update from your monthly plan allowance.

Exporting SVG/PNG/PDF, toggling pause/resume status, renaming, or updating folder assignment consumes 0 Dynamic Updates.

GET/api/v1/qr

List Workspace QR Codes

Returns a paginated list of QR codes owned by the authenticated workspace, with optional folder filtering.

Authentication: Bearer Token / x-api-key
Required Scope: qr:read
Quota Impact: 0 Updates (Read-only)
Rate Limit: Counts toward 30 or 60 req/min

Query Parameters

  • page (optional, integer, default: 1): Page index for pagination.
  • limit (optional, integer, default: 20, max: 100): Number of QR records per page.
  • folderId (optional, string): Filter results to a specific campaign folder.

Example cURL

curl -X GET "https://qrnaly.com/api/v1/qr?page=1&limit=20" \
  -H "Authorization: Bearer qrs_live_your_api_key_here"

Successful Response (HTTP 200)

{
  "data": [
    {
      "id": "qr_01j8m4k8...",
      "workspaceId": "ws_01j8m1...",
      "slug": "summer-festival",
      "name": "Summer Festival Billboard",
      "type": "url",
      "folderId": "fol_01j8m2...",
      "targetUrl": "https://example.com/summer-pass",
      "status": "active",
      "lifecycleStatus": "active",
      "scanCount": 142,
      "isDynamic": true,
      "scanUrl": "https://qrnaly.com/q/summer-festival",
      "design": { "fgColor": "#0f172a", "bgColor": "#ffffff" },
      "createdAt": "2026-09-10T12:00:00.000Z",
      "updatedAt": "2026-09-12T14:30:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1
  }
}
POST/api/v1/qr

Create QR Code (Static or Dynamic)

Generates a new QR code with atomic quota verification and vector SVG generation. Supports Idempotency-Key header to prevent duplicates on network retry.

Authentication: Bearer Token / x-api-key
Required Scope: qr:write
Quota Impact: Dynamic consumes 1 dynamic slot; Static consumes 0.
Headers: Idempotency-Key (optional)

Request Body Schema

  • targetUrl (required, string): Destination URL (must begin with http:// or https://).
  • name (optional, string): Human-readable name (default: "API Generated QR").
  • isDynamic (optional, boolean, default: true): If true, creates a managed shortlink QR. If false, creates pure static QR.
  • type (optional, string, default: "url"): Content payload type (url, vcard, whatsapp, location).
  • folderId (optional, string): Assigns the QR code to an existing campaign folder.
  • design (optional, object): Color and styling configuration (fgColor, bgColor, dotType, cornerSquareType, brandingMode).

Example 1: Create Dynamic Trackable QR (cURL)

curl -X POST "https://qrnaly.com/api/v1/qr" \
  -H "Authorization: Bearer qrs_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: req_summer_promo_001" \
  -d '{
    "name": "Summer Festival Billboard",
    "targetUrl": "https://example.com/summer-pass",
    "isDynamic": true,
    "design": {
      "fgColor": "#0f172a",
      "bgColor": "#ffffff"
    }
  }'

Example 2: Create Pure Static QR (cURL)

curl -X POST "https://qrnaly.com/api/v1/qr" \
  -H "Authorization: Bearer qrs_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Direct Guest WiFi QR",
    "targetUrl": "WIFI:S:GuestNetwork;T:WPA;P:Secret123;;",
    "isDynamic": false,
    "design": {
      "fgColor": "#1e293b",
      "bgColor": "#ffffff"
    }
  }'

TypeScript / Node.js Example

const response = await fetch('https://qrnaly.com/api/v1/qr', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.QRNALY_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'req_order_8821'
  },
  body: JSON.stringify({
    name: 'Order Confirmation #8821',
    targetUrl: 'https://myshop.com/orders/8821',
    isDynamic: true
  })
});

const { data } = await response.json();
console.log('Shortlink URL:', data.scanUrl);
console.log('SVG QR:', data.svg);

Python Example

import requests

url = "https://qrnaly.com/api/v1/qr"
headers = {
    "Authorization": "Bearer qrs_live_your_api_key_here",
    "Content-Type": "application/json"
}
payload = {
    "name": "Warehouse Shelf B12",
    "targetUrl": "https://erp.internal/bins/B12",
    "isDynamic": True
}

res = requests.post(url, json=payload, headers=headers)
print("Created QR:", res.json()["data"]["scanUrl"])

Successful Response (HTTP 201)

{
  "data": {
    "id": "qr_01j8m4k8...",
    "workspaceId": "ws_01j8m1...",
    "slug": "summer-promo",
    "name": "Summer Festival Billboard",
    "type": "url",
    "targetUrl": "https://example.com/summer-pass",
    "status": "active",
    "lifecycleStatus": "active",
    "scanCount": 0,
    "isDynamic": true,
    "scanUrl": "https://qrnaly.com/q/summer-promo",
    "design": { "fgColor": "#0f172a", "bgColor": "#ffffff" },
    "svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" ...>...</svg>",
    "createdAt": "2026-10-06T10:00:00.000Z",
    "updatedAt": "2026-10-06T10:00:00.000Z"
  },
  "creditsDeducted": 1,
  "balance": {
    "remaining": 49,
    "limit": 50
  }
}

Common Error Responses

  • HTTP 400 Bad Request (BAD_REQUEST): targetUrl is missing or fails URL security validation.
  • HTTP 402 Payment Required (INSUFFICIENT_CREDITS): Workspace has 0 remaining dynamic capacity.
  • HTTP 403 Forbidden (ACTIVE_LIMIT_REACHED): Workspace concurrency cap reached (50 on Pro, 500 on Business).
GET/api/v1/qr/:id

Get QR Code by ID or Slug

Retrieves the complete configuration, design settings, routing target, and lifecycle status for a single QR code.

Authentication: Bearer Token / x-api-key
Required Scope: qr:read
Quota Impact: 0 Updates (Read-only)
Parameters: :id (UUID or slug)

Example cURL

curl -X GET "https://qrnaly.com/api/v1/qr/qr_01j8m4k8" \
  -H "Authorization: Bearer qrs_live_your_api_key_here"

Successful Response (HTTP 200)

{
  "data": {
    "id": "qr_01j8m4k8",
    "workspaceId": "ws_01j8m1...",
    "slug": "summer-festival",
    "name": "Summer Festival Billboard",
    "type": "url",
    "folderId": "fol_01j8m2...",
    "targetUrl": "https://example.com/summer-pass",
    "status": "active",
    "lifecycleStatus": "active",
    "scanCount": 142,
    "isDynamic": true,
    "scanUrl": "https://qrnaly.com/q/summer-festival",
    "design": { "fgColor": "#0f172a", "bgColor": "#ffffff" },
    "createdAt": "2026-09-10T12:00:00.000Z",
    "updatedAt": "2026-09-12T14:30:00.000Z"
  }
}
PATCH/api/v1/qr/:id

Update QR Code Destination & Metadata

Updates the destination URL without changing the printed QR code. Also allows updating name, folder assignment, or styling parameters.

Authentication: Bearer Token / x-api-key
Required Scope: qr:write
Quota Impact: Updating targetUrl consumes 1 Dynamic Update. Other fields consume 0.
Static Rule: Updating targetUrl on a Static QR returns HTTP 400 (STATIC_QR_IMMUTABLE).

Example cURL

curl -X PATCH "https://qrnaly.com/api/v1/qr/qr_01j8m4k8" \
  -H "Authorization: Bearer qrs_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Summer Festival Autumn Extension",
    "targetUrl": "https://example.com/autumn-pass",
    "folderId": "fol_01j8m2..."
  }'

Successful Response (HTTP 200)

{
  "data": {
    "id": "qr_01j8m4k8",
    "name": "Summer Festival Autumn Extension",
    "targetUrl": "https://example.com/autumn-pass",
    "status": "active",
    "updatedAt": "2026-10-06T10:15:00.000Z"
  }
}
DELETE/api/v1/qr/:id

Delete QR Code

Soft-deletes the QR record and releases dynamic capacity back to the workspace. Scans to the shortlink will receive HTTP 404.

Example cURL

curl -X DELETE "https://qrnaly.com/api/v1/qr/qr_01j8m4k8" \
  -H "Authorization: Bearer qrs_live_your_api_key_here"
POST/api/v1/qr/:id/pause

Pause QR Code

Halts public redirects for a dynamic QR code. Scanners are presented with a pause landing page. Consumes 0 Dynamic Updates.

curl -X POST "https://qrnaly.com/api/v1/qr/qr_01j8m4k8/pause" \
  -H "Authorization: Bearer qrs_live_your_api_key_here"
POST/api/v1/qr/:id/resume

Resume QR Code

Restores active redirection for a previously paused dynamic QR code. Consumes 0 Dynamic Updates.

curl -X POST "https://qrnaly.com/api/v1/qr/qr_01j8m4k8/resume" \
  -H "Authorization: Bearer qrs_live_your_api_key_here"
POST/api/v1/qr/:id/duplicate

Duplicate QR Code

Deep-clones the design palette, destination URL, and folder assignment into a new independent record named {Name} - Copy. Dynamic duplicates consume 1 dynamic slot.

curl -X POST "https://qrnaly.com/api/v1/qr/qr_01j8m4k8/duplicate" \
  -H "Authorization: Bearer qrs_live_your_api_key_here"
GET/api/v1/qr/:id/history

List Destination History

Provides an audit log of all destination URL updates, version numbers, change reasons, and timestamps for a dynamic QR code.

curl -X GET "https://qrnaly.com/api/v1/qr/qr_01j8m4k8/history" \
  -H "Authorization: Bearer qrs_live_your_api_key_here"

Successful Response (HTTP 200)

{
  "data": [
    {
      "versionNumber": 2,
      "destinationUrl": "https://example.com/autumn-pass",
      "changeReason": "API destination update",
      "createdAt": "2026-10-06T10:15:00.000Z"
    },
    {
      "versionNumber": 1,
      "destinationUrl": "https://example.com/summer-pass",
      "changeReason": "Initial destination",
      "createdAt": "2026-09-10T12:00:00.000Z"
    }
  ]
}
POST/api/v1/qr/:id/history/restore

Restore Destination Version

Rolls back the active destination URL to a previously recorded version number. Consumes 1 Dynamic Update.

curl -X POST "https://qrnaly.com/api/v1/qr/qr_01j8m4k8/history/restore" \
  -H "Authorization: Bearer qrs_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "versionNumber": 1
  }'

Explore Complementary APIs

Combine QR codes with digital menus, campaign folders, and privacy-preserving scan telemetry.

Digital Catalogue API