{"openapi": "3.0.3", "info": {"title": "Instnt Print", "version": "1.0.0", "description": "Print labels en bonnen vanaf elk systeem dat een HTTP-verzoek kan doen. Geen driver, geen wachtrij op een pc: je stuurt wat erop moet, en er komt papier uit.\n\nAlles gaat over sjablonen. Een sjabloon legt de vorm vast; jij stuurt alleen de gegevens die per keer verschillen."}, "servers": [{"url": "https://print.instnt.studio"}], "security": [{"sleutel": []}], "tags": [{"name": "Printen", "description": "Opdrachten versturen."}, {"name": "Opzoeken", "description": "Wat er te printen valt, en waarop."}, {"name": "Meldingen", "description": "Laten weten wanneer er iets gebeurt."}], "components": {"securitySchemes": {"sleutel": {"type": "http", "scheme": "bearer", "description": "Een integratiesleutel uit het dashboard onder Sleutels. Een sleutel die met `lbl_test_` begint rendert alles maar laat geen papier komen \u2014 precies wat je wilt terwijl je bouwt."}}, "schemas": {"Opdracht": {"type": "object", "properties": {"id": {"type": "string", "example": "job_iXa5xr8bk9dr"}, "status": {"type": "string", "enum": ["queued", "printing", "done", "failed", "expired"]}, "mode": {"type": "string", "enum": ["live", "test"]}, "template": {"type": "string", "nullable": true}, "copies": {"type": "integer"}, "error": {"type": "string", "nullable": true}, "created_at": {"type": "number"}, "finished_at": {"type": "number", "nullable": true}}}, "Webhook": {"type": "object", "properties": {"id": {"type": "string", "example": "wh_8Kd2p1qZ"}, "url": {"type": "string"}, "secret": {"type": "string", "description": "Waarmee wij ondertekenen.", "example": "whsec_..."}, "events": {"type": "array", "items": {"type": "string"}}, "active": {"type": "boolean"}}}, "Fout": {"type": "object", "properties": {"error": {"type": "string", "example": "geen printer met de naam 'Kassa'"}}}}}, "paths": {"/v1/jobs": {"post": {"tags": ["Printen"], "summary": "Print \u00e9\u00e9n label of bon", "description": "Stuur een sjabloonnaam met de gegevens die erin moeten, of `lines` met kale tekstregels.\n\nAntwoordt met **202** en een opdracht-id: de printer kan uit staan, en daar mag jouw systeem niet op wachten. Wil je het t\u00f3ch meteen weten, geef dan `?wait=true` mee \u2014 dan komt er 200 zodra hij klaar is.", "parameters": [{"name": "wait", "in": "query", "schema": {"type": "boolean"}, "description": "Wacht tot de printer klaar is."}, {"name": "Idempotency-Key", "in": "header", "schema": {"type": "string"}, "description": "Een tekst die deze ene gebeurtenis beschrijft \u2014 een bonnummer, een ordernummer. Stuur je hem twee keer, dan krijg je het eerste antwoord terug en komt er geen tweede bon uit. Onmisbaar zodra er een netwerk tussen zit."}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"printer": {"type": "string", "description": "De naam uit het dashboard. Heb je er \u00e9\u00e9n, dan mag dit weg.", "example": "Kassa balie"}, "template": {"type": "string", "example": "Kassabon"}, "data": {"type": "object", "description": "De velden van het sjabloon. Een lijst (zoals de regels van een bon) zet je hier als array onder zijn eigen naam.", "example": {"bonnummer": "1043", "totaal": "17,45", "regels": [{"aantal": "2", "omschrijving": "Koffie", "bedrag": "6,40"}]}}, "lines": {"type": "array", "items": {"type": "string"}, "description": "Zonder sjabloon: kale tekstregels op het label dat in de printer zit."}, "copies": {"type": "integer", "default": 1}, "label": {"type": "string", "description": "Ander formaat dan wat er volgens de instellingen in zit."}, "cut": {"type": "boolean", "default": true, "description": "Alleen bij bonprinters."}, "drawer": {"type": "boolean", "default": false, "description": "Open de kassalade."}, "reverse": {"type": "boolean", "description": "Print het ontwerp een halve slag gedraaid, voor een printer die ingebouwd staat."}, "sample": {"type": "boolean", "description": "Vul lege velden met aannemelijke inhoud. Voor een proefdruk."}, "idempotency_key": {"type": "string"}}}}}}, "responses": {"202": {"description": "Aangenomen; staat in de rij.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Opdracht"}}}}, "200": {"description": "Klaar (bij `?wait=true`), of een herhaling van een opdracht die je al eerder stuurde.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Opdracht"}}}}, "404": {"description": "Onbekende printer of sjabloon."}, "400": {"description": "Er staat iets niet goed in het verzoek \u2014 bij meerdere printers zonder keuze bijvoorbeeld."}, "503": {"description": "De printer is niet bereikbaar."}}}}, "/v1/jobs/batch": {"post": {"tags": ["Printen"], "summary": "Print een reeks", "description": "Elke rij wordt een label. Naar een bonprinter wordt de hele reeks juist \u00e9\u00e9n bon \u2014 veertig regels horen op \u00e9\u00e9n bon te staan, niet veertig bonnetjes te worden.\n\nElke rij krijgt een eigen sleutel, afgeleid van die van de reeks. Een herhaalde aanroep levert dus geen dubbele labels op, ook niet als hij halverwege afbrak.", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["rows"], "properties": {"printer": {"type": "string"}, "template": {"type": "string"}, "rows": {"type": "array", "items": {"type": "object"}, "description": "Per rij de velden voor \u00e9\u00e9n label."}, "into": {"type": "string", "description": "Bij een bon: onder welke lijstnaam de rijen het sjabloon in gaan.", "example": "regels"}, "idempotency_key": {"type": "string"}}}}}}, "responses": {"202": {"description": "Aangenomen."}}}}, "/v1/jobs/{id}": {"get": {"tags": ["Printen"], "summary": "Hoe staat het met een opdracht", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Opdracht"}}}, "description": "De opdracht."}, "404": {"description": "Onbekende opdracht."}}}}, "/v1/webhooks": {"get": {"tags": ["Meldingen"], "summary": "Welke webhooks er staan", "responses": {"200": {"description": "De webhooks van jouw organisatie.", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Webhook"}}}}}}}, "post": {"tags": ["Meldingen"], "summary": "Een webhook aanmelden", "description": "Wij bellen jouw adres zodra er iets gebeurt, in plaats van dat jij blijft vragen. Elk bericht is ondertekend met het geheim dat je hier terugkrijgt: `X-Instnt-Signature` is `sha256=` gevolgd door een HMAC-SHA256 over `tijdstip.lichaam`, met `X-Instnt-Timestamp` als tijdstip. Weiger wat ouder is dan een paar minuten.\n\nMislukt de bezorging, dan proberen we het nog twee keer: na twintig seconden en na twee minuten.", "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["url", "events"], "properties": {"url": {"type": "string", "example": "https://jouwsysteem.nl/instnt"}, "events": {"type": "array", "items": {"type": "string", "enum": ["job.done", "job.failed", "printer.online", "printer.offline"]}, "example": ["job.done", "job.failed"]}}}}}}, "responses": {"201": {"description": "Aangemeld. Bewaar het geheim.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Webhook"}}}}, "400": {"description": "Het adres wijst naar een netwerk in plaats van naar buiten, of er is geen gebeurtenis gekozen.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fout"}}}}}}}, "/v1/webhooks/{id}": {"delete": {"tags": ["Meldingen"], "summary": "Een webhook afmelden", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Afgemeld."}}}}, "/v1/printers": {"get": {"tags": ["Opzoeken"], "summary": "Welke printers er zijn", "description": "Met `kind` erbij: `label` of `receipt`. Daarmee weet je waar een sjabloon naartoe kan zonder het aan de modelnaam te hoeven raden.", "responses": {"200": {"description": "De printers van jouw organisatie.", "content": {"application/json": {"schema": {"type": "array", "items": {"type": "object", "properties": {"name": {"type": "string"}, "model": {"type": "string"}, "label": {"type": "string"}, "kind": {"type": "string", "enum": ["label", "receipt"]}, "online": {"type": "boolean"}}}}}}}}}}, "/v1/templates": {"get": {"tags": ["Opzoeken"], "summary": "Welke sjablonen er zijn", "description": "Met per sjabloon de velden die het verwacht, en welk soort invoer erbij hoort \u2014 genoeg om er een formulier van te bouwen zonder de vorm te kennen.", "responses": {"200": {"description": "De sjablonen van jouw organisatie.", "content": {"application/json": {"schema": {"type": "array", "items": {"type": "object", "properties": {"name": {"type": "string"}, "kind": {"type": "string", "enum": ["label", "receipt"]}, "description": {"type": "string"}, "label": {"type": "string"}, "fields": {"type": "array", "items": {"type": "string"}}, "lists": {"type": "array", "items": {"type": "string"}}, "field_kinds": {"type": "object"}, "list_fields": {"type": "object"}}}}}}}}}}, "/v1/preview": {"post": {"tags": ["Printen"], "summary": "Een voorbeeld als afbeelding", "description": "Hetzelfde verzoek als printen, maar er komt een PNG terug in plaats van papier. Handig om te laten zien wat er gaat gebeuren.", "responses": {"200": {"description": "De afdruk als afbeelding.", "content": {"image/png": {}}}}}}}}