4.6 KiB
Backend API – LabelPrintAgent
Diese Datei beschreibt die Endpunkte des PaperlessManager-Backends für den LabelPrintAgent.
Das Backend rendert das fertige Etikettbild (SVG -> PNG via resvg-js). Der Agent ist nur lokaler Druck-Connector.
Authentifizierung
Alle Endpunkte erfordern einen Bearer Token (JWT oder API-Key):
Authorization: Bearer {token}
/jobs/next, /jobs/:id/image, /jobs/:id/printed und /jobs/:id/error benötigen keine spezifische Permission, nur einen gültigen Token. POST /jobs und POST /preview erfordern VIEW_SCANNER.
1. Job manuell anlegen (Frontend -> Backend)
POST /api/label-print-agent/jobs
Content-Type: application/json
Request Body
{
"templateId": 3,
"fieldValues": {
"datum": "2026-05-09"
}
}
| Feld | Pflicht | Beschreibung |
|---|---|---|
templateId |
ja | ID des BarcodeTemplates |
fieldValues |
nein | Feldwerte für Platzhalter; Datumsfelder im Format YYYY-MM-DD |
Antwort
201 Created
{ "jobId": "42" }
2. Vorschau-Bild rendern (kein Job, keine Nummer-Reservierung)
POST /api/label-print-agent/preview
Content-Type: application/json
Request Body
Identisch mit POST /jobs. {number} wird immer als 1 gerendert; die GET-URL wird nicht aufgerufen.
Antwort
200 OK
Content-Type: image/png
Body: binäres PNG-Bild.
3. Nächsten Druckjob abrufen (Agent-Polling)
GET /api/label-print-agent/jobs/next?agentId={agentId}
| Parameter | Pflicht | Beschreibung |
|---|---|---|
agentId |
nein | Eindeutige Agent-ID, z. B. Rechnername; Fallback: unknown |
Antwort – kein Job vorhanden
204 No Content
Antwort – Job vorhanden
200 OK
Content-Type: application/json
{
"jobId": "42",
"labelImageBase64": "iVBORw0KGgoAAAANSUhEUgAA...",
"labelImageContentType": "image/png",
"labelWidthMm": 57,
"labelHeightMm": 32
}
| Feld | Beschreibung |
|---|---|
jobId |
Job-ID für Rückmeldungen |
labelImageBase64 |
Base64-PNG; null wenn Rendering fehlgeschlagen |
labelImageContentType |
Immer image/png |
labelWidthMm / labelHeightMm |
Etikettenmaß in mm |
Das Backend setzt beim Ausliefern einen Lock (5-Minuten-TTL). Jobs mit abgelaufenem Lock werden erneut angeboten.
4. Etikettbild separat abrufen
Alternativ zum Base64-Feld in jobs/next.
GET /api/label-print-agent/jobs/{jobId}/image
Antwort
200 OK
Content-Type: image/png
Body: binäres PNG-Bild.
404 Not Found
Job oder Bild nicht vorhanden.
5. Erfolgreichen Druck melden
POST /api/label-print-agent/jobs/{jobId}/printed
Content-Type: application/json
Request Body
{
"agentId": "PC-BUERO",
"printerName": "DYMO LabelWriter 450"
}
Alle Felder optional; Fallback jeweils "" / unknown.
Antwort
200 OK
{ "ok": true }
Das Backend setzt den Job auf printed, speichert Zeitstempel und ruft die konfigurierte LabelPrintedUrl des Templates auf (POST).
6. Druckfehler melden
POST /api/label-print-agent/jobs/{jobId}/error
Content-Type: application/json
Request Body
{
"agentId": "PC-BUERO",
"printerName": "DYMO LabelWriter 450",
"errorMessage": "Drucker nicht verfügbar."
}
Antwort
200 OK
{ "ok": true }
Das Backend setzt den Job auf error und ruft die konfigurierte LabelReleaseUrl des Templates auf (POST).
Job-Lebenszyklus
createJob()
|
v
pending ---- jobs/next ---- Lock (5 Min TTL)
|
Agent druckt
|
+-------+-------+
printed error
(PrintedUrl) (ReleaseUrl)
7. Server-Sent Events – neue Druckaufträge (Push)
GET /api/label-print-agent/events
Authorization: Bearer {token}
Accept: text/event-stream
Der Agent verbindet sich einmalig. Sobald ein neuer Druckauftrag erstellt wird, sendet das Backend:
data: {"type":"label-job-available"}
Der Agent ruft daraufhin sofort GET /jobs/next auf. Polling bleibt als Fallback sinnvoll, z. B. alle 30 Sekunden, falls die SSE-Verbindung unterbrochen wurde.
Es werden keine agentId-Parameter ausgewertet; alle verbundenen Agents erhalten das Event.
Statuscodes
| Situation | Status |
|---|---|
| Kein Job vorhanden | 204 No Content |
| Job / Bild vorhanden | 200 OK |
| Job erstellt | 201 Created |
| Token fehlt / ungültig | 401 Unauthorized |
| Fehlende Permission | 403 Forbidden |
| Job-ID unbekannt | 404 Not Found |
| Backend-Fehler | 500 Internal Server Error |