{"openapi":"3.1.0","info":{"title":"Linkwave Business QR API","version":"1.0.0","description":"Workspace-scoped branded QR generation for server-to-server ticketing integrations. 120 requests/minute/workspace. Static ticket validity and redemption remain with your ticketing system."},"servers":[{"url":"https://linkwavecloud.com/api/v1"}],"security":[{"WorkspaceKey":[]}],"tags":[{"name":"QR codes"},{"name":"Designs"}],"paths":{"/publications":{"get":{"operationId":"listPublications","summary":"List workspace publications","tags":["Publications"],"description":"Requires publications:read. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"maximum":499,"default":0}}],"responses":{"200":{"description":"Publication operation completed"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}},"post":{"operationId":"createPublication","summary":"Create a draft publication","tags":["Publications"],"description":"Requires publications:write. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title"],"additionalProperties":false,"properties":{"title":{"type":"string","minLength":1,"maxLength":150}}}}}},"responses":{"200":{"description":"Publication operation completed"},"201":{"description":"Resource created"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}}},"/publications/{id}":{"get":{"operationId":"getPublication","summary":"Get publication and viewer/embed URLs","tags":["Publications"],"description":"Requires publications:read. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Publication operation completed"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}},"patch":{"operationId":"updatePublication","summary":"Update metadata or archive with status=archived","tags":["Publications"],"description":"Requires publications:write. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"title":{"type":"string","maxLength":150},"description":{"type":"string","maxLength":2000},"category":{"type":"string","maxLength":80},"status":{"enum":["draft","published","archived"]},"visibility":{"enum":["public","workspace"]},"allow_download":{"type":"boolean"},"allow_print":{"type":"boolean"},"allow_embed":{"type":"boolean"},"accent_color":{"type":"string","pattern":"^#[a-fA-F0-9]{6}$"},"background_color":{"type":"string","pattern":"^#[a-fA-F0-9]{6}$"},"logo_data_url":{"type":["string","null"],"description":"PNG data URL, max 180000 characters"},"thumbnail_data_url":{"type":["string","null"],"description":"PNG data URL, max 180000 characters"}}}}}},"responses":{"200":{"description":"Publication operation completed"},"201":{"description":"Resource created"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}},"delete":{"operationId":"deletePublication","summary":"Soft-delete a publication and revoke its public viewer","tags":["Publications"],"description":"Requires publications:write. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"responses":{"200":{"description":"Publication operation completed"},"201":{"description":"Resource created"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}}},"/publications/{id}/uploads":{"post":{"operationId":"reservePublicationUpload","summary":"Reserve private PDF upload; returns path, token, upload_id and signed_url","tags":["Publications"],"description":"Requires publications:write. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["bytes"],"additionalProperties":false,"properties":{"bytes":{"type":"integer","minimum":1,"maximum":20971520}}}}}},"responses":{"200":{"description":"Publication operation completed"},"201":{"description":"Resource created"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}}},"/publications/{id}/finalize":{"post":{"operationId":"finalizePublicationUpload","summary":"Validate uploaded PDF and atomically replace the current revision","tags":["Publications"],"description":"Requires publications:write. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["upload_id"],"additionalProperties":false,"properties":{"upload_id":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"Publication operation completed"},"201":{"description":"Resource created"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}}},"/publications/{id}/duplicate":{"post":{"operationId":"duplicatePublication","summary":"Duplicate as a new draft with a new public URL","tags":["Publications"],"description":"Requires publications:write. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false}}}},"responses":{"200":{"description":"Publication operation completed"},"201":{"description":"Resource created"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}}},"/publications/{id}/analytics":{"get":{"operationId":"getPublicationAnalytics","summary":"Get view, page, session, reading-time and link metrics","tags":["Publications"],"description":"Requires publications:read. Workspace scoped. Mutations use atomic idempotency and plan limits.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Publication operation completed"},"401":{"description":"Invalid API key"},"402":{"description":"Plan or storage quota exceeded"},"403":{"description":"Missing scope"},"404":{"description":"Publication not found"},"409":{"description":"Idempotency, revision or upload conflict"},"422":{"description":"Invalid PDF or input"},"429":{"description":"Workspace rate limit exceeded"}}}},"/qr-codes":{"post":{"operationId":"createQrCode","tags":["QR codes"],"summary":"Create a branded QR code","description":"Requires qr:write. The same Idempotency-Key and normalized request return the same resource. Keys are retained for the workspace lifetime, even if the QR is deleted. Business and Business Plus quotas count all QR codes created during the UTC calendar month, including deleted codes.","parameters":[{"in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[!-~]+$"},"description":"Unique per ticket, e.g. ticket:ticket_987:v1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQr"}}}},"responses":{"200":{"description":"Existing QR returned on retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QrWithImage"}}}},"201":{"description":"QR created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QrWithImage"}}}},"400":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listQrCodes","tags":["QR codes"],"summary":"List workspace QR codes","description":"Requires qr:read. Images are omitted from list responses.","parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}}],"responses":{"200":{"description":"Workspace QR codes","content":{"application/json":{"schema":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Qr"}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"}}}}}}}},"400":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/qr-codes/{id}":{"get":{"operationId":"getQrCode","tags":["QR codes"],"summary":"Get a workspace QR code","description":"Requires qr:read. A QR belonging to another workspace returns 404.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"QR metadata and design","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Qr"}}}}}},"400":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/qr-codes/{id}/image":{"get":{"operationId":"getQrSvg","tags":["QR codes"],"summary":"Render the saved design as SVG","description":"Requires qr:read. Authenticate from your backend; never put an API key in an image URL. Uses the saved design. External dashboard logo URLs are unsupported; API-created embedded/preset logos render without remote requests.","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"query","name":"size","schema":{"type":"integer","minimum":128,"maximum":2048,"default":720},"description":"Inner QR design size; the output also includes its frame and padding"}],"responses":{"200":{"description":"Styled SVG image","content":{"image/svg+xml":{"schema":{"type":"string"}}}},"400":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates":{"get":{"operationId":"listDesigns","tags":["Designs"],"summary":"List template and logo preset IDs","description":"Requires qr:read.","responses":{"200":{"description":"Design catalog","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"templates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}}},"logo_presets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}}}}}},"400":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"WorkspaceKey":{"type":"http","scheme":"bearer","bearerFormat":"lw_live_...","description":"Create in Dashboard > Developers. Only the SHA-256 hash is stored; the full key is shown once."}},"schemas":{"Design":{"type":"object","additionalProperties":false,"properties":{"foreground":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","default":"#16181d"},"background":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","default":"#ffffff"},"template":{"type":"string","enum":["clean","rounded","circle-label","label","label-dark","circle","orbit","confetti","circle-solid","double-frame","brackets","corners","ticket","scan-strip","poster"],"default":"clean"},"label":{"type":"string","maxLength":28,"default":"Scan me"},"logo":{"oneOf":[{"type":"null"},{"type":"object","additionalProperties":false,"required":["preset"],"properties":{"preset":{"type":"string","examples":["whatsapp","menu"]}}},{"type":"object","additionalProperties":false,"required":["data_url"],"properties":{"data_url":{"type":"string","maxLength":140000,"description":"Base64 PNG, JPEG or WebP data URL. Decoded image up to 100 KB. Remote URLs and user-provided SVG are unsupported."}}}],"default":null}}},"CreateQr":{"type":"object","additionalProperties":false,"required":["name","payload"],"properties":{"name":{"type":"string","minLength":1,"maxLength":150},"mode":{"type":"string","enum":["static","dynamic"],"default":"static"},"payload":{"type":"string","minLength":1,"maxLength":2048,"description":"Up to 1024 UTF-8 bytes. Static: ticket token or validation URL. Dynamic: absolute HTTP(S) URL without credentials."},"design":{"$ref":"#/components/schemas/Design"},"size":{"type":"integer","minimum":128,"maximum":2048,"default":720}},"example":{"name":"Ticket ticket_987","mode":"static","payload":"https://tickets.example.com/validate/unguessable-token","design":{"template":"ticket","label":"ADMIT ONE","foreground":"#16181d","background":"#ffffff","logo":{"preset":"calendar"}}}},"Qr":{"type":"object","required":["id","name","mode","payload","encoded_value","status","created_at","image_endpoint"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"mode":{"type":"string","enum":["static","dynamic"]},"payload":{"type":"string"},"encoded_value":{"type":"string"},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"image_endpoint":{"type":"string","format":"uri"},"design":{"type":"object"}}},"QrWithImage":{"type":"object","required":["data"],"properties":{"data":{"allOf":[{"$ref":"#/components/schemas/Qr"},{"type":"object","required":["image"],"properties":{"image":{"type":"object","required":["format","svg","data_uri"],"properties":{"format":{"const":"svg"},"svg":{"type":"string"},"data_uri":{"type":"string"}}}}}]}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}