{"openapi":"3.1.0","info":{"title":"Printercow API","version":"1","description":"Print on the USB printers your Printercow dongles connect: saved label templates, recipe actions, and print jobs that wait their turn, with webhooks that say how each one ended.\n\nAuthenticate with an API token from the Connect page (`Authorization: Bearer pc_live_...`), or an OAuth access token. A token limited to some dongles sees and prints on those only.\n\nEvery print is a print job in its dongle's queue. `POST /api/v1/print-jobs` answers at once and waits out an offline dongle; the template print and recipe action endpoints wait for the result. Send an `Idempotency-Key` so a retry never prints twice.\n\nAI clients connect to the MCP server at https://milk.printercow.com/mcp instead."},"servers":[{"url":"https://milk.printercow.com"}],"security":[{"bearer":[]}],"tags":[{"name":"Dongles"},{"name":"Print jobs"},{"name":"Label templates"},{"name":"Recipe actions"},{"name":"Rendering"},{"name":"Assets"}],"paths":{"/api/v1/dongles":{"get":{"tags":["Dongles"],"operationId":"listDongles","summary":"The dongles this token reaches","description":"Each with what is plugged in, the receipt paper width, the approved recipe's actions and the label templates that print there. A token limited to some dongles sees those only.","responses":{"200":{"description":"The dongles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiDonglesResponse"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/print-jobs":{"post":{"tags":["Print jobs"],"operationId":"createPrintJob","summary":"Send a print to wait in the dongle's queue","description":"Answers at once with the job, which prints in its turn: one job at a time per dongle, first in, first out. It waits out an offline dongle or a printer being plugged back in until `expiresInSeconds`; a try that could have reached the printer is never repeated by itself. Follow it with GET /api/v1/print-jobs/{jobId} or the `print.job.*` webhooks. A dongle takes 100 open jobs.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$"},"description":"Your own id for this print, such as an order number. Sent again with the same body, it answers with the job (and run) it made the first time instead of printing again; with another body it is 409 `idempotency_key_reused`. Kept per organization as long as the job (30 days after it ended)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePrintJobRequest"}}}},"responses":{"200":{"description":"The job this Idempotency-Key made before, as it is now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobResponse"}}}},"202":{"description":"The job, queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobResponse"}}}},"400":{"description":"A body, template values or key that do not fit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown dongle or template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`idempotency_key_reused`: the key was sent before with another print (`job` is that print, when this token may see it).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`queue_full`, or rate-limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Print jobs"],"operationId":"listPrintJobs","summary":"Print jobs, newest first","parameters":[{"name":"dongleId","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"$ref":"#/components/schemas/PrintJobStatus"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"The jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobsResponse"}}}},"400":{"description":"An unknown status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/print-jobs/{jobId}":{"get":{"tags":["Print jobs"],"operationId":"getPrintJob","summary":"One print job","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"},"description":"`pjb_...`"}],"responses":{"200":{"description":"The job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobResponse"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/print-jobs/{jobId}/cancel":{"post":{"tags":["Print jobs"],"operationId":"cancelPrintJob","summary":"Cancel a job that has not started printing","description":"A queued job, or one that waits for the operator after its strip. A job that is printing finishes.","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"},"description":"`pjb_...`"}],"responses":{"200":{"description":"The canceled job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintJobResponse"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`not_cancelable`: it is printing or already final.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/label-templates":{"get":{"tags":["Label templates"],"operationId":"listLabelTemplates","summary":"Saved label templates","parameters":[{"name":"dongleId","in":"query","schema":{"type":"string"},"description":"Only the templates that print on this dongle."}],"responses":{"200":{"description":"The templates, without their layouts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelTemplatesResponse"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Label templates"],"operationId":"saveLabelTemplate","summary":"Save a layout as a template with typed parameters","description":"Renders it with the example values; `replace: true` saves a new version of an existing name. A token limited to some dongles cannot save templates.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveLabelTemplateRequest"}}}},"responses":{"200":{"description":"Saved as a new version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveLabelTemplateResponse"}}}},"201":{"description":"Saved, version 1.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveLabelTemplateResponse"}}}},"400":{"description":"A draft or layout that does not fit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A token limited to some dongles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`deviceId` names no dongle of this token, or it has no render action for the profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The name is taken (without `replace`), or too many templates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/label-templates/{template}":{"get":{"tags":["Label templates"],"operationId":"getLabelTemplate","summary":"One template, its layout, and the dongles that print it","parameters":[{"name":"template","in":"path","required":true,"schema":{"type":"string"},"description":"The template's name or id (`tpl_...`)."}],"responses":{"200":{"description":"The template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelTemplateResponse"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Label templates"],"operationId":"updateLabelTemplate","summary":"Save a new version of a template","parameters":[{"name":"template","in":"path","required":true,"schema":{"type":"string"},"description":"The template's name or id (`tpl_...`)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLabelTemplateRequest"}}}},"responses":{"200":{"description":"The new version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveLabelTemplateResponse"}}}},"400":{"description":"A draft or layout that does not fit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A token limited to some dongles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The new name is taken.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Label templates"],"operationId":"deleteLabelTemplate","summary":"Delete a template","parameters":[{"name":"template","in":"path","required":true,"schema":{"type":"string"},"description":"The template's name or id (`tpl_...`)."}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["deleted"],"properties":{"deleted":{"const":true}}}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A token limited to some dongles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/label-templates/{template}/preview.png":{"get":{"tags":["Label templates"],"operationId":"getLabelTemplatePreview","summary":"The stored preview, drawn with the example values","parameters":[{"name":"template","in":"path","required":true,"schema":{"type":"string"},"description":"The template's name or id (`tpl_...`)."}],"responses":{"200":{"description":"The 1-bit picture as PNG.","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/label-templates/{template}/preview":{"post":{"tags":["Label templates"],"operationId":"previewLabelTemplate","summary":"Draw a template with other values, optionally as a dongle prints it","description":"The headers X-Render-Width, X-Render-Height, X-Render-Hash and X-Render-Language describe the picture.","parameters":[{"name":"template","in":"path","required":true,"schema":{"type":"string"},"description":"The template's name or id (`tpl_...`)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewLabelTemplateRequest"}}},"description":"Send `{}` for the example values."},"responses":{"200":{"description":"The 1-bit picture as PNG.","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Values or a layout that do not fit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such template or dongle.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The template does not fit the dongle.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Too large to render.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/label-templates/{template}/print":{"post":{"tags":["Label templates"],"operationId":"printLabelTemplate","summary":"Print a template and wait for the result","description":"The print is a print job in the dongle's queue, waited for: it waits up to 25 s for prints ahead of it instead of failing as busy, then prints. A receipt goes through Printercow's receipt path on a dongle whose paper width is set, a label through the dongle's approved recipe (or `action`). The first big graphic on a printer nobody checked prints a top strip and Printercow asks the operator on the dongle page (`render.checkQuestionId`); after their yes the job prints whole by itself, so do not send it again. To wait out an offline dongle, use POST /api/v1/print-jobs instead.","parameters":[{"name":"template","in":"path","required":true,"schema":{"type":"string"},"description":"The template's name or id (`tpl_...`)."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$"},"description":"Your own id for this print, such as an order number. Sent again with the same body, it answers with the job (and run) it made the first time instead of printing again; with another body it is 409 `idempotency_key_reused`. Kept per organization as long as the job (30 days after it ended)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrintLabelTemplateRequest"}}}},"responses":{"200":{"description":"The run: its step results, the check, the render outcome and the print job it ran as. Also when the check failed, and with `error: print_timeout` when the deadline stopped a run after a script was published: read the run before repeating anything.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueuedRun"}}}},"202":{"description":"Still printing (`still_printing`) when the request had to answer: the job goes on, GET /api/v1/print-jobs/{jobId} says when it is done. Do not send it again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueuedRun"}}}},"400":{"description":"Bad parameters, or a layout that does not render.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown dongle, template, action or recipe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"408":{"description":"`print_timeout`: the print waited its turn for 25 s behind other prints and never started, or the publication deadline passed before anything was sent. Nothing was printed; it is safe to send again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The dongle is offline, has another device or no recipe, the paper width is not set or does not fit (`paper_width_unset`, `paper_width_mismatch`, `template_misfit`), or `idempotency_key_reused`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"A label too large to render.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-limited, or `queue_full`: the dongle already has 100 open jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/devices/{dongleId}/actions/{action}":{"post":{"tags":["Recipe actions"],"operationId":"runRecipeAction","summary":"Run an action of the approved recipe and wait for the result","description":"The body is the action's parameters as a JSON object (GET /api/v1/dongles names the actions). A print job in the dongle's queue, waited for, exactly like the template print. `?confirmLargeWrite=true` allows more than 32 KiB of raw writes for an action without a render step.","parameters":[{"name":"dongleId","in":"path","required":true,"schema":{"type":"string"},"description":"The dongle, `dev_...` (GET /api/v1/dongles)."},{"name":"action","in":"path","required":true,"schema":{"type":"string"}},{"name":"confirmLargeWrite","in":"query","schema":{"type":"string","enum":["true"]}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$"},"description":"Your own id for this print, such as an order number. Sent again with the same body, it answers with the job (and run) it made the first time instead of printing again; with another body it is 409 `idempotency_key_reused`. Kept per organization as long as the job (30 days after it ended)."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"The action's parameters by name."}}}},"responses":{"200":{"description":"The run: its step results, the check, the render outcome and the print job it ran as. Also when the check failed, and with `error: print_timeout` when the deadline stopped a run after a script was published: read the run before repeating anything.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueuedRun"}}}},"202":{"description":"Still printing (`still_printing`) when the request had to answer: the job goes on, GET /api/v1/print-jobs/{jobId} says when it is done. Do not send it again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueuedRun"}}}},"400":{"description":"Bad parameters, or a layout that does not render.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown dongle, template, action or recipe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"408":{"description":"`print_timeout`: the print waited its turn for 25 s behind other prints and never started, or the publication deadline passed before anything was sent. Nothing was printed; it is safe to send again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The dongle is offline, has another device or no recipe, the paper width is not set or does not fit (`paper_width_unset`, `paper_width_mismatch`, `template_misfit`), or `idempotency_key_reused`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"A label too large to render.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-limited, or `queue_full`: the dongle already has 100 open jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/devices/{dongleId}/printer-checks":{"post":{"tags":["Recipe actions"],"operationId":"printPrinterCheck","summary":"Print the small test receipt of \"Check this printer\"","description":"Through Printercow's receipt path; Printercow then asks the operator on the dongle page whether it came out clean, and their yes checks the printer. Only a signed-in person can answer.","parameters":[{"name":"dongleId","in":"path","required":true,"schema":{"type":"string"},"description":"The dongle, `dev_...` (GET /api/v1/dongles)."}],"responses":{"200":{"description":"The test receipt's run and Printercow's question.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrinterCheckStartResponse"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown dongle: `run.error` is `not_found`, `questionId` null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrinterCheckStartResponse"}}}},"408":{"description":"`print_timeout` before anything was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrinterCheckStartResponse"}}}},"409":{"description":"Offline, `not_a_receipt_printer`, `no_endpoint`, or busy: `run.error` says which, `questionId` is null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrinterCheckStartResponse"}}}},"429":{"description":"Rate-limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/render/preview":{"post":{"tags":["Rendering"],"operationId":"renderPreview","summary":"Draw a layout as a 1-bit picture without printing","description":"For a printer profile, or as a dongle's render action draws it (`deviceId`). The headers X-Render-Width, X-Render-Height, X-Render-Hash and X-Render-Language describe the picture. 30 a minute per token.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderPreviewRequest"}}}},"responses":{"200":{"description":"The 1-bit picture as PNG.","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"A layout that does not render (`invalid_layout`, `missing_glyph`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"An unknown dongle, or one without a render action (`no_render_recipe`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Two previews already render (`busy`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Too large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/assets":{"get":{"tags":["Assets"],"operationId":"listAssets","summary":"The image library: logos and artwork layouts name","responses":{"200":{"description":"The assets and the library's usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelAssetsResponse"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Assets"],"operationId":"uploadAsset","summary":"Add an image (PNG or JPEG)","description":"A token limited to some dongles cannot add assets.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"},"name":{"type":"string","description":"Lowercase letters, digits and hyphens."}}}}}},"responses":{"201":{"description":"Added.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelAssetResponse"}}}},"400":{"description":"No file, or a name that does not fit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A token limited to some dongles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"408":{"description":"The upload took too long.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The name is taken, the library is full, or busy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Too large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Not a PNG or JPEG (`unsupported_image`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/assets/{assetId}":{"patch":{"tags":["Assets"],"operationId":"renameAsset","summary":"Rename an asset","parameters":[{"name":"assetId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameAssetRequest"}}}},"responses":{"200":{"description":"Renamed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelAssetResponse"}}}},"400":{"description":"A name that does not fit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A token limited to some dongles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such asset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The name is taken.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Assets"],"operationId":"deleteAsset","summary":"Delete an asset","parameters":[{"name":"assetId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"const":true}}}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A token limited to some dongles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such asset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/assets/{assetId}/preview":{"get":{"tags":["Assets"],"operationId":"previewAsset","summary":"The asset as the printer would see it, 1-bit","parameters":[{"name":"assetId","in":"path","required":true,"schema":{"type":"string"}},{"name":"width","in":"query","schema":{"type":"integer","minimum":16,"maximum":800,"default":320}},{"name":"dither","in":"query","schema":{"type":"string","enum":["floyd","none"]}},{"name":"threshold","in":"query","schema":{"anyOf":[{"const":"auto"},{"type":"integer","minimum":1,"maximum":254}]}},{"name":"invert","in":"query","schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"The 1-bit picture as PNG.","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"A query that does not fit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No or no valid token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such asset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Busy drawing other previews.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate-limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"printer.connection.online":{"post":{"tags":["Webhooks: Connection"],"summary":"Printer connected","description":"A printer reports online for the first time. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.connection.offline":{"post":{"tags":["Webhooks: Connection"],"summary":"Printer offline","description":"A printer reports offline or is marked offline by the heartbeat monitor. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.connection.recovered":{"post":{"tags":["Webhooks: Connection"],"summary":"Printer recovered","description":"A printer comes back after being offline. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.heartbeat.received":{"post":{"tags":["Webhooks: Heartbeat"],"summary":"Heartbeat received","description":"A telemetry heartbeat arrives from firmware. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.heartbeat.lost":{"post":{"tags":["Webhooks: Heartbeat"],"summary":"Heartbeat lost","description":"No heartbeat was received inside the expected timeout. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.heartbeat.restored":{"post":{"tags":["Webhooks: Heartbeat"],"summary":"Heartbeat restored","description":"Heartbeats resume after a timeout. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.heartbeat.anomaly":{"post":{"tags":["Webhooks: Heartbeat"],"summary":"Heartbeat anomaly","description":"Heartbeat timing is delayed but not yet considered lost. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.wifi.rssi.warning":{"post":{"tags":["Webhooks: Wi-Fi signal"],"summary":"Weak Wi-Fi","description":"RSSI drops into the warning band. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.wifi.rssi.critical":{"post":{"tags":["Webhooks: Wi-Fi signal"],"summary":"Critical Wi-Fi","description":"RSSI drops into the critical band. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.wifi.rssi.recovered":{"post":{"tags":["Webhooks: Wi-Fi signal"],"summary":"Wi-Fi recovered","description":"RSSI returns to a healthy band. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.wifi.ip_changed":{"post":{"tags":["Webhooks: Wi-Fi signal"],"summary":"IP address changed","description":"The printer reports a different local IP address. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.status.updated":{"post":{"tags":["Webhooks: Printer status"],"summary":"Status updated","description":"Firmware sends a status payload. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.telemetry.received":{"post":{"tags":["Webhooks: Printer status"],"summary":"Telemetry received","description":"Firmware sends a telemetry payload. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"printer.error.reported":{"post":{"tags":["Webhooks: Printer status"],"summary":"Printer error","description":"Firmware reports an error event. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"usb_device.attached":{"post":{"tags":["Webhooks: USB device"],"summary":"Device attached","description":"A USB device was plugged into the dongle, or was still there when the dongle reconnected. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"usb_device.detached":{"post":{"tags":["Webhooks: USB device"],"summary":"Device detached","description":"The USB device was unplugged from the dongle. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"slot.changed":{"post":{"tags":["Webhooks: Sensor slots"],"summary":"Slot level changed","description":"A sensor slot's debounced level went high or low; the payload carries the slot, its label, the level and the millivolts. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"print.job.completed":{"post":{"tags":["Webhooks: Print jobs"],"summary":"Print job completed","description":"A print job printed, and the printer acknowledged it. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"print.job.failed":{"post":{"tags":["Webhooks: Print jobs"],"summary":"Print job failed","description":"A print job did not go through. It may have printed in part, so it is never repeated by itself. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"print.job.waiting_for_operator":{"post":{"tags":["Webhooks: Print jobs"],"summary":"Print job waiting for the operator","description":"A print job printed a strip to check a new printer and waits for the operator's yes on the dongle page. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}},"print.job.expired":{"post":{"tags":["Webhooks: Print jobs"],"summary":"Print job expired","description":"A print job did not start in time, for example while its dongle was offline. Nothing was printed. Sent to the URL you set on the Connect page, signed: `printercow-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint's secret>`, with `printercow-event` and `printercow-delivery` headers. Answer 2xx; other answers are retried.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Received."}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"An API token from the Connect page (`pc_live_...`), or an OAuth access token."}},"schemas":{"Layout_LayoutNode":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"box"},"x":{"$ref":"#/components/schemas/Layout_Offset"},"y":{"$ref":"#/components/schemas/Layout_Offset"},"right":{"$ref":"#/components/schemas/Layout_Offset"},"bottom":{"$ref":"#/components/schemas/Layout_Offset"},"direction":{"description":"Main axis; default column.","type":"string","enum":["row","column"]},"gap":{"type":"integer","minimum":0,"maximum":1000},"padding":{"description":"One value, [vertical, horizontal] or [top, right, bottom, left].","anyOf":[{"type":"integer","minimum":0,"maximum":1000},{"minItems":2,"maxItems":2,"type":"array","items":{"type":"integer","minimum":0,"maximum":1000}},{"minItems":4,"maxItems":4,"type":"array","items":{"type":"integer","minimum":0,"maximum":1000}}]},"border":{"description":"Black border width in dots.","type":"integer","minimum":0,"maximum":100},"radius":{"type":"integer","minimum":0,"maximum":1000},"background":{"description":"Default: transparent.","type":"string","enum":["black","white"]},"align":{"description":"Cross axis; default stretch.","type":"string","enum":["start","center","end","stretch"]},"justify":{"type":"string","enum":["start","center","end","between","around","evenly"]},"width":{"description":"Dots or % of the parent, padding and border included (border-box): padding wider than that grows the box. By default the root box spans the page width.","$ref":"#/components/schemas/Layout_Length"},"height":{"description":"Like width. By default the root box fills the page height on a label, and on a receipt it is as tall as its content; a height of its own overrides both.","$ref":"#/components/schemas/Layout_Length"},"grow":{"description":"Share of the free space along the main axis.","type":"integer","minimum":0,"maximum":100},"children":{"description":"At most 256 nodes in the whole layout (1024 with repeats filled in), 12 deep.","maxItems":256,"type":"array","items":{"$ref":"#/components/schemas/Layout_LayoutNode"}}},"required":["type"],"additionalProperties":false,"description":"A flex container; children may be placed with x/y instead (Offset)."},{"type":"object","properties":{"type":{"type":"string","const":"text"},"x":{"$ref":"#/components/schemas/Layout_Offset"},"y":{"$ref":"#/components/schemas/Layout_Offset"},"right":{"$ref":"#/components/schemas/Layout_Offset"},"bottom":{"$ref":"#/components/schemas/Layout_Offset"},"text":{"type":"string","maxLength":4096,"description":"May contain {{param}} placeholders; a newline breaks the line."},"size":{"description":"Font size in dots, at least 8 pt (23 at 203 dpi, 34 at 300); default 10 pt.","type":"integer","minimum":23,"maximum":1000},"weight":{"description":"sans and mono have normal, bold; geist has normal, medium, semibold, bold, black (400 to 900).","type":"string","enum":["normal","medium","semibold","bold","black"]},"font":{"description":"sans (default, Liberation Sans), mono, or geist (geometric, five weights, for headlines): geist draws Latin-1 and takes other characters from sans, but refuses accented letters beyond Latin-1 (ř, ő).","type":"string","enum":["sans","mono","geist"]},"align":{"type":"string","enum":["left","center","right"]},"maxLines":{"description":"Cut longer text with an ellipsis.","type":"integer","minimum":1,"maximum":100},"color":{"description":"Default black; white on a black box.","type":"string","enum":["black","white"]},"lineHeight":{"description":"Dots from line to line, at least 0.8 x size; default the font's (1.12 x size, geist 1.3 x). Less only shrinks the gaps between lines.","type":"integer","minimum":1,"maximum":2000},"letterSpacing":{"description":"Dots added after every character; negative tightens, down to a tenth of the size.","type":"integer","minimum":-100,"maximum":100},"rotate":{"description":"Clockwise: 90 reads top to bottom, 270 bottom to top, 180 upside down. At 90 and 270 it does not wrap (use \\n) and takes its turned size in the flow.","type":"number","enum":[0,90,180,270]}},"required":["type","text"],"additionalProperties":false,"description":"A paragraph in one font, size and weight. Wraps at word boundaries, or anywhere if it must. Prints Latin, Greek, Cyrillic, currency signs, box drawing and ♥ ♠ ♣ ♦ ● ○ ■ □ ▲ ▼ ► ◄ • · † § ° № € ← → ↑ ↓ ↔ ↕ ✔ ✖ ☑ ☎ ✉ ✂ ☀ ⚠; ↩ ↪ ↖ ↗ ↘ ↙ ▶ ◀ as white on black; ★ ☆ ✓ ⇒ ◆ ◇ ① ② only with the server's CJK fonts; no font has ✗ ✘ ➜ ➔ ↵ ₹."},{"type":"object","properties":{"type":{"type":"string","const":"image"},"x":{"$ref":"#/components/schemas/Layout_Offset"},"y":{"$ref":"#/components/schemas/Layout_Offset"},"right":{"$ref":"#/components/schemas/Layout_Offset"},"bottom":{"$ref":"#/components/schemas/Layout_Offset"},"src":{"description":"A PNG or JPEG data URI, or a public http(s) URL (PNG, JPEG, WebP, GIF), fetched once and kept in the asset library.","type":"string","maxLength":349558},"asset":{"description":"Asset name from list_assets; give src or asset.","type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,62}$"},"width":{"type":"integer","minimum":1,"maximum":4800,"description":"Final width in dots; the image (or crop) is scaled to it."},"height":{"type":"integer","minimum":1,"maximum":4800},"fit":{"description":"Default contain, on white.","type":"string","enum":["contain","cover","fill"]},"crop":{"description":"Source pixels or percentages, before rotate; view_asset helps find it.","type":"object","properties":{"x":{"$ref":"#/components/schemas/Layout_CropLength"},"y":{"$ref":"#/components/schemas/Layout_CropLength"},"width":{"$ref":"#/components/schemas/Layout_CropLength"},"height":{"$ref":"#/components/schemas/Layout_CropLength"}},"required":["x","y","width","height"],"additionalProperties":false},"rotate":{"description":"Clockwise degrees, after crop, before scaling.","anyOf":[{"type":"number","const":0},{"type":"number","const":90},{"type":"number","const":180},{"type":"number","const":270}]},"dither":{"description":"floyd (default) for photos and greys; none, a hard threshold, for logos, line art and photos of prints.","type":"string","enum":["floyd","none"]},"threshold":{"description":"Grey level (0 black, 255 white) below which a dot is black, default 128; \"auto\" picks it per image (Otsu), good for photos of prints. Implies dither none.","anyOf":[{"type":"integer","minimum":1,"maximum":254},{"type":"string","const":"auto"}]},"invert":{"description":"Swap black and white first.","type":"boolean"}},"required":["type","width","height"],"additionalProperties":false,"description":"A photo or logo, turned to 1 bit at its final size, optionally cropped, rotated and inverted first.","oneOf":[{"required":["src"]},{"required":["asset"]}]},{"type":"object","properties":{"type":{"type":"string","const":"svg"},"x":{"$ref":"#/components/schemas/Layout_Offset"},"y":{"$ref":"#/components/schemas/Layout_Offset"},"right":{"$ref":"#/components/schemas/Layout_Offset"},"bottom":{"$ref":"#/components/schemas/Layout_Offset"},"width":{"type":"integer","minimum":1,"maximum":4800},"height":{"type":"integer","minimum":1,"maximum":4800},"viewBox":{"description":"\"minX minY width height\", fitted into the box (aspect kept, centred). Default: the box in dots.","type":"string","maxLength":200},"paths":{"minItems":1,"maxItems":64,"type":"array","items":{"type":"object","properties":{"d":{"type":"string","minLength":1,"maxLength":8192,"pattern":"^[MmLlHhVvCcSsQqTtAaZz0-9eE.,+\\-\\s]*$","description":"Circle r=50: \"M0 50a50 50 0 1 0 100 0a50 50 0 1 0-100 0z\"."},"fill":{"description":"Default black, as in SVG.","type":"string","enum":["black","white","none"]},"stroke":{"description":"Default none.","type":"string","enum":["black","white","none"]},"strokeWidth":{"description":"viewBox units, default 1; 2 dots to the box size once scaled.","type":"number","exclusiveMinimum":0,"maximum":10000},"strokeLinecap":{"type":"string","enum":["butt","round","square"]},"strokeLinejoin":{"type":"string","enum":["miter","round","bevel"]},"fillRule":{"description":"evenodd: inner contours cut holes.","type":"string","enum":["nonzero","evenodd"]}},"required":["d"],"additionalProperties":false},"description":"Painted in order. At most 4096 segments per layout, an arc up to 4."}},"required":["type","width","height","paths"],"additionalProperties":false,"description":"Vector shapes (blobs, icons, logos) from SVG path data in a fixed box; nodes after it paint on top."},{"type":"object","properties":{"type":{"type":"string","const":"barcode"},"x":{"$ref":"#/components/schemas/Layout_Offset"},"y":{"$ref":"#/components/schemas/Layout_Offset"},"right":{"$ref":"#/components/schemas/Layout_Offset"},"bottom":{"$ref":"#/components/schemas/Layout_Offset"},"symbology":{"type":"string","enum":["code128","gs1-128","code39","code93","ean13","ean8","upca","upce","interleaved2of5","codabar"]},"data":{"type":"string","maxLength":4096,"description":"May contain {{param}} placeholders."},"module":{"description":"Narrow bar in dots, at least 2. Alone the code is as wide as its data; with width it is fixed.","type":"integer","minimum":2,"maximum":20},"width":{"description":"Reserved width in dots, quiet zones included: always this wide, the code centred at the largest module 2-20 that fits. render_preview reports codes[].spareChars.","type":"integer","minimum":1,"maximum":4800},"height":{"type":"integer","minimum":8,"maximum":4800,"description":"Bar height in dots."}},"required":["type","symbology","data","height"],"additionalProperties":false,"description":"A 1D code at whole dots per module with quiet zones of about 10 modules, never scaled. Give width (best for {{param}} data), module, or both.","anyOf":[{"required":["module"]},{"required":["width"]}]},{"type":"object","properties":{"type":{"type":"string","const":"qr"},"x":{"$ref":"#/components/schemas/Layout_Offset"},"y":{"$ref":"#/components/schemas/Layout_Offset"},"right":{"$ref":"#/components/schemas/Layout_Offset"},"bottom":{"$ref":"#/components/schemas/Layout_Offset"},"data":{"type":"string","maxLength":4096,"description":"May contain {{param}} placeholders."},"module":{"description":"Dots per module, at least 4. Alone the code grows with its data; with size it is fixed.","type":"integer","minimum":4,"maximum":40},"size":{"description":"Reserved square in dots, quiet zone included (at least 116): always this size, the code centred at the largest module 4-40 that fits. render_preview reports codes[].spareBytes.","type":"integer","minimum":116,"maximum":4800},"version":{"description":"Fix the version (1-40), so every value draws the same grid; longer data is an error.","type":"integer","minimum":1,"maximum":40},"ecc":{"description":"Error correction: L, M (default), Q or H.","type":"string","enum":["L","M","Q","H"]},"fixedEcc":{"description":"Keep ecc exact; default false allows an upgrade.","type":"boolean"},"gs1":{"description":"GS1 QR: data is an element string such as (01)...; default false.","type":"boolean"}},"required":["type","data"],"additionalProperties":false,"description":"A QR code at whole dots per module with a 4-module quiet zone, never scaled. Give size (best for {{param}} data), module, or both. Modules a side, quiet zone included: 29 + 4 x (version - 1). For ordinary QR at ecc M version 1 takes any 11 bytes, 2: 21, 3: 34, 4: 50, 5: 67, 6: 85.","anyOf":[{"required":["module"]},{"required":["size"]}]},{"type":"object","properties":{"type":{"type":"string","const":"repeat"},"each":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]{0,63}$","description":"A list parameter; its items are objects."},"as":{"description":"Name for the current item: {{item.field}} in the template. Default \"item\".","type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]{0,63}$"},"max":{"type":"integer","minimum":1,"maximum":100,"description":"More items than this is an error."},"template":{"$ref":"#/components/schemas/Layout_LayoutNode"}},"required":["type","each","max","template"],"additionalProperties":false,"description":"The template once per item of a list parameter, in place. Repeats do not nest."}]},"Layout_Offset":{"type":"integer","minimum":-4800,"maximum":4800,"description":"Dots from the parent's inner border, ignoring padding; x, y, right or bottom remove the node from flow. Opposite offsets stretch an unsized box or text not turned 90/270; a missing axis is 0. On a borderless root they are page coordinates; the root cannot be placed. Later nodes paint on top; codes and images print on white above all. A node may leave its parent, not the page; placed layouts may cover the page 16 times."},"Layout_Length":{"anyOf":[{"type":"integer","minimum":0,"maximum":4800},{"type":"string","pattern":"^(100(\\.0{1,2})?|\\d{1,2}(\\.\\d{1,2})?)%$"}]},"Layout_CropLength":{"anyOf":[{"type":"integer","minimum":0,"maximum":16384},{"type":"string","pattern":"^(100|\\d{1,2})(\\.\\d{1,2})?%$"}],"description":"Source pixels, or a percentage of the source (\"12.5%\")."},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"A stable code, such as `not_found` or `queue_full`."},"message":{"type":"string","description":"What happened and what to do, in a sentence."}}},"PrinterProfile":{"type":"object","properties":{"language":{"type":"string","enum":["tspl","zpl","escpos"],"description":"Which encoder builds the graphic: TSPL BITMAP, ZPL ^GF, ESC/POS GS v 0."},"dpi":{"anyOf":[{"type":"number","const":203},{"type":"number","const":300}]},"width":{"type":"integer","minimum":8,"maximum":2400,"description":"Printable width in dots. ESC/POS: 384 (58 mm paper) or 576 (80 mm); a recipe is refused any other ESC/POS width."},"height":{"type":"integer","minimum":1,"maximum":4800,"description":"Label height in dots, such as 1200 for 150 mm at 203 dpi; for ESC/POS the most rows the layout may produce."},"textStroke":{"description":"Dots of stroke around every glyph, so thin strokes survive a thermal head. Default 0.5.","anyOf":[{"type":"number","const":0},{"type":"number","const":0.5},{"type":"number","const":1}]}},"required":["language","dpi","width","height"]},"Layout":{"anyOf":[{"$ref":"#/components/schemas/Layout_LayoutNode"},{"type":"object","properties":{"template":{"type":"string","maxLength":65536,"description":"HTML subset: div, p, span, br, img (src: data URI, URL or asset:name), inline svg, barcode, qr, repeat; inline flex styles in px (= dots) or %, and position: absolute as in Offset."}},"required":["template"],"additionalProperties":false,"description":"An HTML/CSS-subset template, parsed into the same node tree."}],"description":"A layout node tree (box, text, image, svg, barcode, qr and repeat nodes; sizes in printer dots; {{name}} placeholders in text and code data, {{item.field}} inside a repeat), or { \"template\": \"<div>…</div>\" } with an HTML subset parsed into the same tree. Budget: 256 nodes in the whole tree, 12 levels deep, 8 KiB of text after placeholders, 4 MiB and 262144 values of layout JSON; HTTP requests default to 128 KiB total. A layout with more than 128 SVG path validation problems is stopped early. Errors name each node by its path, such as layout.children[3].children[0]."},"PrintJobStatus":{"type":"string","enum":["queued","printing","waiting_for_operator","completed","failed","canceled","expired"],"description":"`queued`: waiting its turn. `printing`: running, never canceled or expired part way. `waiting_for_operator`: it printed a strip to check a new printer and waits for the operator's yes on the dongle page, then prints whole by itself. Final: `completed`; `failed` (it may have printed in part and is never repeated by itself); `canceled`; `expired` (it did not start before `expiresAt`: nothing printed, unless it expired waiting for the operator, when its check strip did)."},"PrintJobTarget":{"oneOf":[{"type":"object","required":["kind","template","action"],"properties":{"kind":{"const":"template"},"template":{"type":"string"},"action":{"anyOf":[{"type":"string"},{"type":"null"}]}}},{"type":"object","required":["kind","action","usbId"],"properties":{"kind":{"const":"action"},"action":{"type":"string"},"usbId":{"anyOf":[{"type":"string"},{"type":"null"}]}}},{"type":"object","required":["kind","action"],"properties":{"kind":{"const":"layout"},"action":{"anyOf":[{"type":"string"},{"type":"null"}]}}}]},"PrintJobRun":{"type":"object","required":["runId","ok","error","message","rowsSent","height"],"properties":{"runId":{"anyOf":[{"type":"string"},{"type":"null"}]},"ok":{"type":"boolean"},"error":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"rowsSent":{"anyOf":[{"type":"integer","description":"Rows of a drawn graphic the printer acknowledged."},{"type":"null"}]},"height":{"anyOf":[{"type":"integer"},{"type":"null"}]}}},"PrintJob":{"type":"object","required":["id","dongleId","status","what","source","createdBy","idempotencyKey","createdAt","startedAt","finishedAt","expiresAt","attempts","error","questionId","position","run"],"properties":{"id":{"type":"string","description":"`pjb_...`"},"dongleId":{"type":"string"},"status":{"$ref":"#/components/schemas/PrintJobStatus"},"what":{"$ref":"#/components/schemas/PrintJobTarget"},"source":{"type":"string","enum":["api","mcp","dashboard"]},"createdBy":{"type":"string","description":"The API token, connected app or person that sent it, by name."},"idempotencyKey":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"expiresAt":{"type":"string","format":"date-time","description":"A job that has not started by then expires; one that is printing finishes."},"attempts":{"type":"integer","description":"Runs started: more than one after a retry before anything was sent, or after the operator's yes."},"error":{"anyOf":[{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}},"description":"Why it failed, expired or was canceled; while it waits, why its last try sent nothing."},{"type":"null"}]},"questionId":{"anyOf":[{"type":"string","description":"Printercow's printer-check question, while it waits for the operator."},{"type":"null"}]},"position":{"anyOf":[{"type":"integer","description":"Jobs ahead of it while it is queued."},{"type":"null"}]},"run":{"anyOf":[{"$ref":"#/components/schemas/PrintJobRun"},{"type":"null"}]}}},"PrintJobResponse":{"type":"object","required":["job"],"properties":{"job":{"$ref":"#/components/schemas/PrintJob"}}},"PrintJobsResponse":{"type":"object","required":["jobs"],"properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/PrintJob"}}}},"CreatePrintJobRequest":{"type":"object","properties":{"dongleId":{"type":"string","minLength":1,"maxLength":100},"template":{"type":"string","minLength":1,"maxLength":80},"action":{"type":"string","minLength":1,"maxLength":80},"params":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"expiresInSeconds":{"type":"integer","minimum":10,"maximum":86400}},"required":["dongleId"],"additionalProperties":false,"anyOf":[{"required":["template"]},{"required":["action"]}],"description":"A template by name or id (through Printercow's receipt path, the recipe's render action, or `action`), or without one the recipe action `action` with `params` as its parameters. `expiresInSeconds`: 10 to 86400, 600 by default."},"UsbStepOutcome":{"type":"object","required":["op","ok"],"properties":{"op":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"string"},"message":{"type":"string"},"length":{"type":"integer","description":"Bytes the device took (writes) or sent (reads)."},"data":{"type":"string","description":"Bytes read, base64."}},"additionalProperties":true},"RecipeRenderOutcome":{"type":"object","required":["width","height","rowsSent","bytes","bulkOutSteps","hash","renderer","next","checkQuestionId","complete"],"properties":{"width":{"type":"integer"},"height":{"type":"integer"},"rowsSent":{"type":"integer","description":"Rows the printer acknowledged: every row, a top strip while the printer waits for its check, or 0."},"bytes":{"type":"integer"},"bulkOutSteps":{"type":"integer"},"hash":{"type":"string"},"renderer":{"type":"string"},"next":{"anyOf":[{"type":"string","description":"After a strip: that Printercow asked the operator and what happens next."},{"type":"null"}]},"checkQuestionId":{"anyOf":[{"type":"string"},{"type":"null"}]},"complete":{"type":"boolean","description":"The whole graphic went out and every write was acknowledged."}}},"RecipeActionRun":{"type":"object","required":["runId","ok","error","message","results","check","render"],"properties":{"runId":{"anyOf":[{"type":"string","description":"Null when nothing was sent."},{"type":"null"}]},"ok":{"type":"boolean"},"error":{"anyOf":[{"type":"string"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/UsbStepOutcome"}},"check":{"type":"object","required":["outcome","message"],"properties":{"outcome":{"type":"string","enum":["passed","failed","unverifiable"]},"message":{"type":"string"}}},"render":{"anyOf":[{"$ref":"#/components/schemas/RecipeRenderOutcome"},{"type":"null"}]}}},"QueuedRun":{"allOf":[{"$ref":"#/components/schemas/RecipeActionRun"},{"type":"object","required":["job"],"properties":{"job":{"anyOf":[{"$ref":"#/components/schemas/PrintJob"},{"type":"null"}]},"template":{"type":"object","description":"For a template print: which template and version it printed.","required":["id","name","version","revision"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"version":{"type":"integer"},"revision":{"type":"string"}}}}}]},"PrinterCheckStartResponse":{"type":"object","required":["run","questionId"],"properties":{"run":{"$ref":"#/components/schemas/RecipeActionRun"},"questionId":{"anyOf":[{"type":"string","description":"Printercow's question about the receipt; null when it did not print whole."},{"type":"null"}]}}},"ApiDongle":{"type":"object","required":["id","name","status","lastSeenAt","pluggedIn","paperWidthMm","recipe","templates"],"properties":{"id":{"type":"string","description":"`dev_...`"},"name":{"type":"string"},"status":{"type":"string","enum":["online","offline","unknown"]},"lastSeenAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"pluggedIn":{"anyOf":[{"type":"object","required":["attached","usbId","manufacturer","product"],"properties":{"attached":{"type":"boolean"},"usbId":{"type":"string","description":"\"0416:5011\""},"manufacturer":{"anyOf":[{"type":"string"},{"type":"null"}]},"product":{"anyOf":[{"type":"string"},{"type":"null"}]}}},{"type":"null"}]},"paperWidthMm":{"anyOf":[{"type":"integer","enum":[58,80],"description":"The receipt paper the operator set on the dongle page."},{"type":"null"}]},"recipe":{"anyOf":[{"type":"object","required":["name","version","actions"],"properties":{"name":{"type":"string"},"version":{"type":"integer"},"actions":{"type":"array","items":{"type":"string"}}},"description":"The approved recipe for what is plugged in; its actions run with POST /api/v1/devices/{dongleId}/actions/{action}."},{"type":"null"}]},"templates":{"type":"array","items":{"type":"string"},"description":"Saved label templates that print here."}}},"ApiDonglesResponse":{"type":"object","required":["dongles"],"properties":{"dongles":{"type":"array","items":{"$ref":"#/components/schemas/ApiDongle"}}}},"LabelTemplateParameter":{"type":"object","required":["name","type","example"],"properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","integer","boolean","array"]},"description":{"type":"string"},"example":{},"maxLength":{"type":"integer"},"minimum":{"type":"integer"},"maximum":{"type":"integer"},"maxItems":{"type":"integer","description":"For a list: how many rows fit the template."},"items":{"type":"object","description":"For a list: the parameters of one row."}},"additionalProperties":true},"LabelTemplateSummary":{"type":"object","required":["id","name","description","profile","parameters","version","preview","createdAt","updatedAt","updatedBy"],"properties":{"id":{"type":"string","description":"`tpl_...`"},"name":{"type":"string","description":"Lowercase words joined by dashes, unique in the organization."},"description":{"type":"string"},"profile":{"$ref":"#/components/schemas/PrinterProfile"},"parameters":{"type":"array","items":{"$ref":"#/components/schemas/LabelTemplateParameter"}},"version":{"type":"integer"},"preview":{"type":"object","required":["width","height","hash","renderer"],"properties":{"width":{"type":"integer"},"height":{"type":"integer"},"hash":{"type":"string"},"renderer":{"type":"string"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updatedBy":{"type":"string"}}},"LabelTemplate":{"allOf":[{"$ref":"#/components/schemas/LabelTemplateSummary"},{"type":"object","required":["layout"],"properties":{"layout":{"$ref":"#/components/schemas/Layout"}}}]},"LabelTemplatesResponse":{"type":"object","required":["templates"],"properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/LabelTemplateSummary"}}}},"LabelTemplateResponse":{"type":"object","required":["template","targets","misfits"],"properties":{"template":{"$ref":"#/components/schemas/LabelTemplate"},"targets":{"type":"array","description":"The dongles that print it, and through which recipe and action.","items":{"type":"object","required":["deviceId","deviceName","online","recipe","recipeVersion","action","problem"],"properties":{"deviceId":{"type":"string"},"deviceName":{"type":"string"},"online":{"type":"boolean"},"recipe":{"type":"string"},"recipeVersion":{"anyOf":[{"type":"integer"},{"type":"null"}]},"action":{"type":"string"},"problem":{"anyOf":[{"type":"string"},{"type":"null"}]}}}},"misfits":{"type":"array","description":"Every other dongle of the organization, and why it cannot print it.","items":{"type":"object","required":["deviceId","deviceName","reason"],"properties":{"deviceId":{"type":"string"},"deviceName":{"type":"string"},"reason":{"type":"string"}}}}}},"SaveLabelTemplateResponse":{"type":"object","required":["template","warnings"],"properties":{"template":{"$ref":"#/components/schemas/LabelTemplate"},"warnings":{"type":"array","items":{"type":"string"},"description":"Such as an example value near its maxLength."}}},"SaveLabelTemplateRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":48,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","description":"Lowercase words joined by dashes, such as \"printplanet-gutschein\". Unique in the organization."},"description":{"description":"What it is and when to print it, for the next agent and the dashboard, such as \"Coupon for the next order\".","type":"string","maxLength":500},"example":{"description":"A value for every {{placeholder}} (and rows for every repeat), realistic ones: the template is rendered with them, and they become the stored preview and the example the next caller sees.","type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"anyOf":[{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},{"maxItems":100,"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":1000},{"type":"number"},{"type":"boolean"}]}}}]}},"parameters":{"description":"Optional types for placeholders: string (maxLength, minLength, enum), integer (minimum, maximum), boolean, or array (maxItems, items) for a repeat; each with description and default. A parameter with a default is optional. Undeclared placeholders are derived from the example: text gets the longest length that still renders, up to 200.","type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"string"},"description":{"type":"string","maxLength":300},"minLength":{"type":"integer","minimum":0,"maximum":4096},"maxLength":{"description":"The longest value the layout takes; default 200, or what the save measured to fit.","type":"integer","minimum":1,"maximum":4096},"enum":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","maxLength":200}},"default":{"type":"string","maxLength":4096}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"integer"},"description":{"type":"string","maxLength":300},"minimum":{"type":"integer","minimum":-1000000000,"maximum":1000000000},"maximum":{"type":"integer","minimum":-1000000000,"maximum":1000000000},"default":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["type","minimum","maximum"]},{"type":"object","properties":{"type":{"type":"string","const":"boolean"},"description":{"type":"string","maxLength":300},"default":{"type":"boolean"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"array"},"description":{"type":"string","maxLength":300},"maxItems":{"type":"integer","minimum":1,"maximum":200},"items":{"type":"object","properties":{"type":{"type":"string","const":"object"},"properties":{"type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"string"},"description":{"type":"string","maxLength":300},"maxLength":{"description":"Default 200.","type":"integer","minimum":1,"maximum":1000},"default":{"type":"string","maxLength":1000}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"integer"},"description":{"type":"string","maxLength":300},"minimum":{"type":"integer","minimum":-1000000000,"maximum":1000000000},"maximum":{"type":"integer","minimum":-1000000000,"maximum":1000000000},"default":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["type","minimum","maximum"]},{"type":"object","properties":{"type":{"type":"string","const":"boolean"},"description":{"type":"string","maxLength":300},"default":{"type":"boolean"}},"required":["type"]}]}},"required":{"maxItems":12,"type":"array","items":{"type":"string"}}},"required":["type","properties"]},"default":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","number","boolean"]}}}},"required":["type","maxItems","items"]}]}},"layout":{"$ref":"#/components/schemas/Layout"},"profile":{"type":"object","properties":{"language":{"type":"string","enum":["tspl","zpl","escpos"],"description":"Which encoder builds the graphic: TSPL BITMAP, ZPL ^GF, ESC/POS GS v 0."},"dpi":{"anyOf":[{"type":"number","const":203},{"type":"number","const":300}]},"width":{"type":"integer","minimum":8,"maximum":2400,"description":"Printable width in dots. ESC/POS: 384 (58 mm paper) or 576 (80 mm); a recipe is refused any other ESC/POS width."},"height":{"type":"integer","minimum":1,"maximum":4800,"description":"Label height in dots, such as 1200 for 150 mm at 203 dpi; for ESC/POS the most rows the layout may produce."},"textStroke":{"description":"Dots of stroke around every glyph, so thin strokes survive a thermal head. Default 0.5.","anyOf":[{"type":"number","const":0},{"type":"number","const":0.5},{"type":"number","const":1}]}},"required":["language","dpi","width","height"]},"deviceId":{"type":"string"},"action":{"type":"string"},"replace":{"type":"boolean"}},"required":["name","layout"],"additionalProperties":false},"UpdateLabelTemplateRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":48,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","description":"Lowercase words joined by dashes, such as \"printplanet-gutschein\". Unique in the organization."},"description":{"description":"What it is and when to print it, for the next agent and the dashboard, such as \"Coupon for the next order\".","type":"string","maxLength":500},"example":{"description":"A value for every {{placeholder}} (and rows for every repeat), realistic ones: the template is rendered with them, and they become the stored preview and the example the next caller sees.","type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"anyOf":[{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},{"maxItems":100,"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":1000},{"type":"number"},{"type":"boolean"}]}}}]}},"parameters":{"description":"Optional types for placeholders: string (maxLength, minLength, enum), integer (minimum, maximum), boolean, or array (maxItems, items) for a repeat; each with description and default. A parameter with a default is optional. Undeclared placeholders are derived from the example: text gets the longest length that still renders, up to 200.","type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"string"},"description":{"type":"string","maxLength":300},"minLength":{"type":"integer","minimum":0,"maximum":4096},"maxLength":{"description":"The longest value the layout takes; default 200, or what the save measured to fit.","type":"integer","minimum":1,"maximum":4096},"enum":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","maxLength":200}},"default":{"type":"string","maxLength":4096}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"integer"},"description":{"type":"string","maxLength":300},"minimum":{"type":"integer","minimum":-1000000000,"maximum":1000000000},"maximum":{"type":"integer","minimum":-1000000000,"maximum":1000000000},"default":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["type","minimum","maximum"]},{"type":"object","properties":{"type":{"type":"string","const":"boolean"},"description":{"type":"string","maxLength":300},"default":{"type":"boolean"}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"array"},"description":{"type":"string","maxLength":300},"maxItems":{"type":"integer","minimum":1,"maximum":200},"items":{"type":"object","properties":{"type":{"type":"string","const":"object"},"properties":{"type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"string"},"description":{"type":"string","maxLength":300},"maxLength":{"description":"Default 200.","type":"integer","minimum":1,"maximum":1000},"default":{"type":"string","maxLength":1000}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","const":"integer"},"description":{"type":"string","maxLength":300},"minimum":{"type":"integer","minimum":-1000000000,"maximum":1000000000},"maximum":{"type":"integer","minimum":-1000000000,"maximum":1000000000},"default":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["type","minimum","maximum"]},{"type":"object","properties":{"type":{"type":"string","const":"boolean"},"description":{"type":"string","maxLength":300},"default":{"type":"boolean"}},"required":["type"]}]}},"required":{"maxItems":12,"type":"array","items":{"type":"string"}}},"required":["type","properties"]},"default":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","number","boolean"]}}}},"required":["type","maxItems","items"]}]}},"layout":{"$ref":"#/components/schemas/Layout"},"profile":{"type":"object","properties":{"language":{"type":"string","enum":["tspl","zpl","escpos"],"description":"Which encoder builds the graphic: TSPL BITMAP, ZPL ^GF, ESC/POS GS v 0."},"dpi":{"anyOf":[{"type":"number","const":203},{"type":"number","const":300}]},"width":{"type":"integer","minimum":8,"maximum":2400,"description":"Printable width in dots. ESC/POS: 384 (58 mm paper) or 576 (80 mm); a recipe is refused any other ESC/POS width."},"height":{"type":"integer","minimum":1,"maximum":4800,"description":"Label height in dots, such as 1200 for 150 mm at 203 dpi; for ESC/POS the most rows the layout may produce."},"textStroke":{"description":"Dots of stroke around every glyph, so thin strokes survive a thermal head. Default 0.5.","anyOf":[{"type":"number","const":0},{"type":"number","const":0.5},{"type":"number","const":1}]}},"required":["language","dpi","width","height"]},"deviceId":{"type":"string"},"action":{"type":"string"}},"required":["layout"],"additionalProperties":false},"PrintLabelTemplateRequest":{"type":"object","properties":{"dongleId":{"type":"string"},"params":{"type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"anyOf":[{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},{"maxItems":100,"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":1000},{"type":"number"},{"type":"boolean"}]}}}]},"maxProperties":40},"action":{"type":"string"}},"required":["dongleId"],"additionalProperties":false},"PreviewLabelTemplateRequest":{"type":"object","properties":{"params":{"type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"anyOf":[{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},{"maxItems":100,"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":1000},{"type":"number"},{"type":"boolean"}]}}}]},"maxProperties":40},"deviceId":{"type":"string"},"action":{"type":"string"}},"additionalProperties":false},"RenderPreviewRequest":{"type":"object","properties":{"profile":{"type":"object","properties":{"language":{"type":"string","enum":["tspl","zpl","escpos"],"description":"Which encoder builds the graphic: TSPL BITMAP, ZPL ^GF, ESC/POS GS v 0."},"dpi":{"anyOf":[{"type":"number","const":203},{"type":"number","const":300}]},"width":{"type":"integer","minimum":8,"maximum":2400,"description":"Printable width in dots. ESC/POS: 384 (58 mm paper) or 576 (80 mm); a recipe is refused any other ESC/POS width."},"height":{"type":"integer","minimum":1,"maximum":4800,"description":"Label height in dots, such as 1200 for 150 mm at 203 dpi; for ESC/POS the most rows the layout may produce."},"textStroke":{"description":"Dots of stroke around every glyph, so thin strokes survive a thermal head. Default 0.5.","anyOf":[{"type":"number","const":0},{"type":"number","const":0.5},{"type":"number","const":1}]}},"required":["language","dpi","width","height"]},"deviceId":{"type":"string"},"layout":{"$ref":"#/components/schemas/Layout"},"params":{"type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"anyOf":[{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]},{"maxItems":200,"type":"array","items":{"type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":4096},{"type":"number"},{"type":"boolean"}]}}}]}},"action":{"type":"string"}},"required":["layout"],"additionalProperties":false,"anyOf":[{"required":["profile"]},{"required":["deviceId"]}]},"LabelAsset":{"type":"object","required":["id","name","source","sourceUrl","contentType","width","height","bytes","sha256","addedBy","createdAt"],"properties":{"id":{"type":"string"},"name":{"type":"string","description":"What a layout names it by: `{ \"type\": \"image\", \"asset\": name }`."},"source":{"type":"string","enum":["upload","url"]},"sourceUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"contentType":{"type":"string","enum":["image/png","image/jpeg"]},"width":{"type":"integer"},"height":{"type":"integer"},"bytes":{"type":"integer"},"sha256":{"type":"string"},"addedBy":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"}}},"LabelAssetsResponse":{"type":"object","required":["assets","usage"],"properties":{"assets":{"type":"array","items":{"$ref":"#/components/schemas/LabelAsset"}},"usage":{"type":"object","required":["count","bytes","maxCount","maxBytes"],"properties":{"count":{"type":"integer"},"bytes":{"type":"integer"},"maxCount":{"type":"integer"},"maxBytes":{"type":"integer"}}}}},"LabelAssetResponse":{"type":"object","required":["asset"],"properties":{"asset":{"$ref":"#/components/schemas/LabelAsset"}}},"RenameAssetRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":64}},"required":["name"],"additionalProperties":false},"WebhookEvent":{"type":"object","required":["id","type","apiVersion","created","livemode","data"],"properties":{"id":{"type":"string","description":"`wev_...`, the same for every endpoint the event went to."},"type":{"type":"string"},"apiVersion":{"type":"string"},"created":{"type":"integer","description":"Unix seconds."},"livemode":{"type":"boolean"},"data":{"type":"object","required":["object"],"properties":{"object":{"type":"object","required":["object","orgId","deviceId"],"description":"`object` is \"print_job\" with `job` for print.job.* events, \"printer_event\" for the rest.","properties":{"object":{"type":"string"},"orgId":{"type":"string"},"deviceId":{"anyOf":[{"type":"string"},{"type":"null"}]},"job":{"$ref":"#/components/schemas/PrintJob"}},"additionalProperties":true}}}}}}}}