{
  "info": {
    "name": "QRD API v1",
    "description": "QRD v1 REST API — create, render, manage, and track QR codes, and manage scheduled email reports.\n\nSetup:\n1. Set the `baseUrl` variable (default https://qrd.cx).\n2. Set the `apiKey` variable to a key from Settings → API & MCP (starts with `qrd_live_`).\n3. Run \"Create QR code\" first — it saves the new id into the `qrId` variable so the other QR requests work. \"Create report schedule\" saves `reportId` similarly.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      { "key": "token", "value": "{{apiKey}}", "type": "string" }
    ]
  },
  "variable": [
    { "key": "baseUrl", "value": "https://qrd.cx", "type": "string" },
    { "key": "apiKey", "value": "qrd_live_...", "type": "string" },
    { "key": "qrId", "value": "", "type": "string" },
    { "key": "reportId", "value": "", "type": "string" }
  ],
  "item": [
    {
      "name": "QR Codes",
      "item": [
        {
          "name": "Create QR code",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const json = pm.response.json();",
                  "if (json && json.success && json.data && json.data.id) {",
                  "  pm.collectionVariables.set('qrId', json.data.id);",
                  "  console.log('Saved qrId =', json.data.id);",
                  "}",
                  "pm.test('created', () => pm.expect(pm.response.code).to.be.oneOf([201, 402, 503]));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/qr",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "qr"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"title\": \"Storefront flyer\",\n  \"targetUrl\": \"https://your-shop.com/deal\",\n  \"type\": \"DYNAMIC\",\n  \"tags\": [\"promo\"],\n  \"appearance\": {\n    \"foreground\": \"#101010\",\n    \"background\": \"#FFFFFF\",\n    \"size\": 512,\n    \"margin\": 2,\n    \"errorCorrection\": \"M\"\n  }\n}"
            },
            "description": "Create a QR code. DYNAMIC codes are tracked; the response includes `encodedUrl` and an inline `image` (PNG data URL)."
          }
        },
        {
          "name": "List QR codes",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/api/v1/qr?page=1&perPage=20&search=",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "qr"],
              "query": [
                { "key": "page", "value": "1" },
                { "key": "perPage", "value": "20" },
                { "key": "search", "value": "" }
              ]
            },
            "description": "List QR codes (paginated). `search` matches title or URL substring."
          }
        },
        {
          "name": "Get QR code",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/api/v1/qr/{{qrId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "qr", "{{qrId}}"]
            },
            "description": "Fetch a single code. Includes `encodedUrl` and an inline `image` (PNG data URL)."
          }
        },
        {
          "name": "Render QR image (PNG)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/api/v1/qr/{{qrId}}/image?format=png&size=512",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "qr", "{{qrId}}", "image"],
              "query": [
                { "key": "format", "value": "png" },
                { "key": "size", "value": "512" },
                { "key": "foreground", "value": "#101010", "disabled": true },
                { "key": "background", "value": "#FFFFFF", "disabled": true },
                { "key": "margin", "value": "2", "disabled": true },
                { "key": "errorCorrection", "value": "M", "disabled": true }
              ]
            },
            "description": "Returns the QR as a binary PNG image (use Postman's \"Send and Download\" to save it). Appearance query params override the stored config for this render."
          }
        },
        {
          "name": "Render QR image (SVG)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/api/v1/qr/{{qrId}}/image?format=svg",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "qr", "{{qrId}}", "image"],
              "query": [
                { "key": "format", "value": "svg" }
              ]
            },
            "description": "Returns the QR as SVG markup (Content-Type image/svg+xml)."
          }
        },
        {
          "name": "Update QR code",
          "request": {
            "method": "PATCH",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/qr/{{qrId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "qr", "{{qrId}}"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"title\": \"Storefront flyer (updated)\",\n  \"targetUrl\": \"https://your-shop.com/new-deal\",\n  \"status\": \"ACTIVE\",\n  \"tags\": [\"promo\", \"summer\"]\n}"
            },
            "description": "Update title / targetUrl / status (ACTIVE | PAUSED | ARCHIVED) / tags. Changing targetUrl on a DYNAMIC code re-points every printed QR."
          }
        },
        {
          "name": "Get scan events",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/api/v1/qr/{{qrId}}/scans?limit=100",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "qr", "{{qrId}}", "scans"],
              "query": [
                { "key": "limit", "value": "100" }
              ]
            },
            "description": "Most recent scan events (newest first). Max limit 500. Only DYNAMIC codes produce scans."
          }
        },
        {
          "name": "Delete QR code",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/api/v1/qr/{{qrId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "qr", "{{qrId}}"]
            },
            "description": "Permanently delete a code and its scan history. This cannot be undone."
          }
        }
      ]
    },
    {
      "name": "Reports",
      "item": [
        {
          "name": "Create report schedule",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const json = pm.response.json();",
                  "if (json && json.success && json.data && json.data.id) {",
                  "  pm.collectionVariables.set('reportId', json.data.id);",
                  "  console.log('Saved reportId =', json.data.id);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/reports",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "reports"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"recipients\": [\"owner@shop.com\"],\n  \"cadence\": \"weekly\"\n}"
            },
            "description": "Subscribe 1-20 emails to a recurring org summary. cadence: weekly (default) or monthly. Requires reports enabled on the deployment."
          }
        },
        {
          "name": "List report schedules",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/api/v1/reports",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "reports"]
            },
            "description": "List all report schedules for the organization."
          }
        },
        {
          "name": "Update report schedule",
          "request": {
            "method": "PATCH",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/reports/{{reportId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "reports", "{{reportId}}"]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"recipients\": [\"owner@shop.com\", \"marketing@shop.com\"],\n  \"cadence\": \"monthly\",\n  \"active\": true\n}"
            },
            "description": "Update recipients / cadence, or set active=false to pause and true to resume."
          }
        },
        {
          "name": "Delete report schedule",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/api/v1/reports/{{reportId}}",
              "host": ["{{baseUrl}}"],
              "path": ["api", "v1", "reports", "{{reportId}}"]
            },
            "description": "Stop and remove a report schedule."
          }
        }
      ]
    }
  ]
}
