{"openapi":"3.1.0","info":{"title":"OpenQR API","version":"1.0.0","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.","contact":{"name":"OpenQR","url":"https://openqr.uk/api"},"license":{"name":"AGPL-3.0","url":"https://www.gnu.org/licenses/agpl-3.0.html"}},"servers":[{"url":"https://openqr.uk","description":"Production"}],"security":[{"bearerAuth":[]}],"paths":{"/v1/qr":{"get":{"operationId":"generateQrGet","summary":"Generate a QR code (query params)","description":"Returns a QR code as SVG or PNG. Encode any text or URL via the `data` parameter.","parameters":[{"name":"data","in":"query","required":true,"schema":{"type":"string","maxLength":2000},"description":"Text or URL to encode."},{"name":"format","in":"query","schema":{"type":"string","enum":["svg","png"],"default":"svg"}},{"name":"size","in":"query","schema":{"type":"integer","minimum":64,"maximum":2048,"default":512},"description":"Pixel size (PNG) or viewBox (SVG)."},{"name":"margin","in":"query","schema":{"type":"integer","minimum":0,"maximum":16,"default":4}},{"name":"dark","in":"query","schema":{"type":"string"},"description":"Foreground colour as a hex code, e.g. 232E3A."},{"name":"light","in":"query","schema":{"type":"string"},"description":"Background colour as a hex code, e.g. FFFFFF."}],"responses":{"200":{"description":"The rendered QR code.","content":{"image/svg+xml":{"schema":{"type":"string"}},"image/png":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"generateQrPost","summary":"Generate a QR code (JSON body)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"string","maxLength":2000,"description":"Text or URL to encode."},"format":{"type":"string","enum":["svg","png"],"default":"svg"},"size":{"type":"integer","minimum":64,"maximum":2048,"default":512},"margin":{"type":"integer","minimum":0,"maximum":16,"default":4},"dark":{"type":"string","description":"Foreground hex, e.g. 232E3A."},"light":{"type":"string","description":"Background hex, e.g. FFFFFF."}}}}}},"responses":{"200":{"description":"The rendered QR code.","content":{"image/svg+xml":{"schema":{"type":"string"}},"image/png":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/dynamic":{"get":{"operationId":"listDynamicCodes","summary":"List your dynamic (editable) QR codes","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":200}}],"responses":{"200":{"description":"Your dynamic codes.","content":{"application/json":{"schema":{"type":"object","properties":{"codes":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/DynamicCode"},{"type":"object","properties":{"label":{"type":["string","null"]},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}]}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"createDynamicCode","summary":"Create a dynamic (editable) QR code","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.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["destination"],"properties":{"destination":{"type":"string","format":"uri","description":"The http(s) URL the code redirects to."},"label":{"type":"string","description":"Optional label for your dashboard."}}}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicCode"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/dynamic/bulk":{"post":{"operationId":"bulkCreateDynamicCodes","summary":"Create up to 200 dynamic codes at once","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["codes"],"properties":{"codes":{"type":"array","maxItems":200,"items":{"type":"object","required":["destination"],"properties":{"destination":{"type":"string","format":"uri"},"label":{"type":"string"}}}}}}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"array","items":{"$ref":"#/components/schemas/DynamicCode"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/dynamic/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"operationId":"updateDynamicCode","summary":"Edit a dynamic code (any field the dashboard can edit)","description":"Send only the fields you want to change: destination, label, custom slug, tags, folder or style.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"destination":{"type":"string","format":"uri"},"label":{"type":["string","null"]},"slug":{"type":"string","description":"Custom short-link back-half: 3–48 letters, numbers or hyphens."},"tags":{"type":"array","items":{"type":"string"},"description":"Replaces the code's tags (max 10)."},"folder_id":{"type":["string","null"],"description":"Folder id to file under, or null to un-file."},"style":{"type":"object","description":"QR style JSON (colours, dot/corner shapes, etc.) for re-download."}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicCode"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteDynamicCode","summary":"Delete a dynamic code","responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/dynamic/{id}/scans":{"get":{"operationId":"getDynamicCodeScans","summary":"Get scan analytics for a dynamic code","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}}],"responses":{"200":{"description":"Scan summary.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DynamicCode"},{"type":"object","properties":{"scans":{"type":"object","properties":{"total":{"type":"integer"},"last7":{"type":"integer"},"topCountry":{"type":["string","null"]},"topDevice":{"type":["string","null"]}}},"analytics":{"type":"object","description":"Detailed breakdowns over the window (default 30 days, ?days=).","properties":{"days_window":{"type":"integer"},"total":{"type":"integer"},"window_total":{"type":"integer"},"daily":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string"},"n":{"type":"integer"}}}},"by_country":{"$ref":"#/components/schemas/Breakdown"},"by_device":{"$ref":"#/components/schemas/Breakdown"},"by_referrer":{"$ref":"#/components/schemas/Breakdown"}}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/folders":{"get":{"operationId":"listFolders","summary":"List your folders","responses":{"200":{"description":"Your folders.","content":{"application/json":{"schema":{"type":"object","properties":{"folders":{"type":"array","items":{"$ref":"#/components/schemas/Folder"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"createFolder","summary":"Create a folder","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"}}}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Folder"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/folders/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"operationId":"renameFolder","summary":"Rename a folder","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"}}}}}},"responses":{"200":{"description":"Renamed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Folder"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteFolder","summary":"Delete a folder (its codes are un-filed, not deleted)","responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"oqr_…","description":"Your OpenQR API key, created at /api."}},"schemas":{"DynamicCode":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"short_url":{"type":"string","format":"uri"},"destination":{"type":"string","format":"uri"}}},"Folder":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"Breakdown":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"n":{"type":"integer"}}}},"Error":{"type":"object","properties":{"error":{"type":"string"}}}},"responses":{"BadRequest":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Code not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many codes created recently.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}