{
  "info": {
    "name": "OpenQR API",
    "_postman_id": "openqr-api-v1",
    "description": "Free REST API for generating QR codes and managing dynamic (editable) codes with scan analytics. All endpoints require a Bearer API key — create one free at https://openqr.uk/api, then send it as `Authorization: Bearer oqr_…`.\n\n## Error catalogue\nEvery error response is JSON: `{ \"error\": \"<human-readable message>\" }`. Status codes used across the API:\n\n- **400 Bad Request** — invalid JSON body, a missing/invalid required field (e.g. `data` is required), or a disallowed dynamic-code destination. Destinations must be public `http(s)` URLs: private/internal/loopback hosts and `oqr.to` self-loops are rejected (e.g. `Destinations can't point to private or internal addresses.`).\n- **401 Unauthorized** — the `Authorization: Bearer oqr_…` header is missing or the key is invalid/revoked.\n- **404 Not Found** — the referenced code, folder or theme doesn't exist or isn't owned by your key.\n- **409 Conflict** — a requested custom `slug` is already taken by another code.\n- **429 Too Many Requests** — dynamic-code creation rate limit hit (20 codes per hour, per user). Each created code consumes one unit of the rolling window: a bulk request consumes one unit per code, so it is rejected up-front (nothing is created) when its row count exceeds the remaining budget. Code-creation responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` (unix seconds); a 429 also includes `Retry-After`.\n- **500 Internal Server Error** — an unexpected server-side failure.\n\n---\n**Setup:** set the collection variable `apiKey` to your OpenQR key (create one free at https://openqr.uk/api). `baseUrl` defaults to https://openqr.uk. Auth is applied at the collection level as `Authorization: Bearer {{apiKey}}`.",
    "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://openqr.uk",
      "type": "string"
    },
    {
      "key": "apiKey",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Discovery",
      "item": [
        {
          "name": "API discovery index",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1"
              ]
            },
            "description": "Public, unauthenticated. Returns the API version, links to the docs/OpenAPI spec/MCP server, the auth scheme, the rate-limit summary, and a map of every endpoint.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Account",
      "item": [
        {
          "name": "Get the account that owns your API key",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/me",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "me"
              ]
            },
            "description": "Returns your own account identity — email, name and signup date. Useful as a connection/auth check."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Generate QR",
      "item": [
        {
          "name": "Generate a QR code (query params)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/qr?data=https%3A%2F%2Fopenqr.uk&format=png&size=512&margin=4&dark=232E3A&light=FFFFFF&theme=Brand",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "qr"
              ],
              "query": [
                {
                  "key": "data",
                  "value": "https://openqr.uk",
                  "description": "(required) Text or URL to encode.",
                  "disabled": false
                },
                {
                  "key": "format",
                  "value": "png",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "size",
                  "value": "512",
                  "description": "Pixel size (PNG) or viewBox (SVG).",
                  "disabled": true
                },
                {
                  "key": "margin",
                  "value": "4",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "dark",
                  "value": "232E3A",
                  "description": "Foreground colour as a hex code, e.g. 232E3A.",
                  "disabled": true
                },
                {
                  "key": "light",
                  "value": "FFFFFF",
                  "description": "Background colour as a hex code, e.g. FFFFFF.",
                  "disabled": true
                },
                {
                  "key": "theme",
                  "value": "Brand",
                  "description": "A saved theme id or name. Applies the theme's colours/margin (SVG). Explicit dark/light/margin override it.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns a QR code as SVG or PNG. Encode any text or URL via the `data` parameter."
          },
          "response": []
        },
        {
          "name": "Generate a QR code (JSON body)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/qr",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "qr"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"data\": \"https://openqr.uk\",\n  \"format\": \"png\",\n  \"size\": 512,\n  \"margin\": 4,\n  \"dark\": \"232E3A\",\n  \"light\": \"FFFFFF\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Dynamic codes",
      "item": [
        {
          "name": "List your dynamic (editable) QR codes",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/dynamic?limit=200",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "dynamic"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "200",
                  "description": "",
                  "disabled": true
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "Create a dynamic (editable) QR code",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/dynamic",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "dynamic"
              ]
            },
            "description": "Creates a short link on oqr.to that you can re-point later. Encode the returned `short_url` in a QR code to print.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"destination\": \"https://example.com/menu\",\n  \"label\": \"Spring menu\",\n  \"theme\": \"Brand\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Create up to 200 dynamic codes at once",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/dynamic/bulk",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "dynamic",
                "bulk"
              ]
            },
            "description": "Each code consumes one unit of the rolling code-creation rate limit (20/hour, per user). If the number of codes in the request exceeds the remaining budget the whole request is rejected with 429 (nothing is created); otherwise the 201 response carries `X-RateLimit-*` headers reflecting the consumed budget.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"codes\": [\n    {\n      \"destination\": \"https://example.com/menu\",\n      \"label\": \"Spring menu\"\n    },\n    {\n      \"destination\": \"https://example.com/wifi\",\n      \"label\": \"Guest wifi\"\n    }\n  ],\n  \"theme\": \"Brand\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Edit a dynamic code (any field the dashboard can edit)",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/dynamic/{id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "dynamic",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "description": "Send only the fields you want to change: destination, label, custom slug, tags, folder or style.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"destination\": \"https://example.com/summer-menu\",\n  \"label\": \"Summer menu\",\n  \"slug\": \"summer-menu\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a dynamic code",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/dynamic/{id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "dynamic",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "Get scan analytics for a dynamic code",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/dynamic/{id}/scans?days=30",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "dynamic",
                ":id",
                "scans"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Themes",
      "item": [
        {
          "name": "List your saved style themes",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/themes",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "themes"
              ]
            },
            "description": "Apply a theme by passing its id or name as `theme` to the QR-generation and dynamic-code endpoints."
          },
          "response": []
        },
        {
          "name": "Save a reusable style theme",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/themes",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "themes"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Brand\",\n  \"style\": {\n    \"fgColor\": \"#232E3A\",\n    \"bgColor\": \"#FFFFFF\",\n    \"dotType\": \"rounded\",\n    \"cornerSquareType\": \"extra-rounded\",\n    \"margin\": 4\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a saved theme (styled codes keep their look)",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/themes/{id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "themes",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Folders",
      "item": [
        {
          "name": "List your folders",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/folders",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "folders"
              ]
            }
          },
          "response": []
        },
        {
          "name": "Create a folder",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/folders",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "folders"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Campaigns\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Rename a folder",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/folders/{id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "folders",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Q3 Campaigns\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a folder (its codes are un-filed, not deleted)",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/folders/{id}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "folders",
                ":id"
              ],
              "variable": [
                {
                  "key": "id",
                  "value": ""
                }
              ]
            }
          },
          "response": []
        }
      ]
    }
  ]
}
