Files
dashback/docs/api/routes/delivery/parsePDF.md
seb 12f37ac4c0 feat(delivery): add POST /delivery/parsePDF SSE route
- Accepts multipart/form-data PDF, streams LLM extraction via SSE
- Uses libllmorbiter (OpenRouterProvider) with API key from companysetting keys.openrouter
- Extracts manifest basedata, notes, and line items from invoices/delivery notes
- Events: status, llm_call, tool_call, usage, progress, result, error
- Extends generateApiDocs.js: multipart field table + x-sse-events table support
- Docs: docs/api/routes/delivery/parsePDF.md (auto-generated)
2026-09-15 07:45:32 +02:00

2.8 KiB

POST /delivery/parsePDF

Protected. Requires a valid session cookie (credentials: 'include').

Parse PDF (SSE)

Accepts a PDF invoice or delivery note (multipart/form-data, field pdf) and streams extraction results as Server-Sent Events until parsing is complete.

The PDF is read via pdftotext -layout and fed page-by-page to an LLM (OpenRouter) which fills a structured manifest of header data and line items. The OpenRouter API key is read from the authenticated user's company setting keys.openrouter; the endpoint returns 400 if the key is not configured.

The stream ends after the final result event (or an error event on failure).

Body (multipart/form-data)

Field Required Type Description
pdf yes file PDF file to parse (max 50 MB, application/pdf)

SSE Events

The response is a text/event-stream. Events are emitted in order until the stream closes.

Event Description Payload
status PDF parse confirmation and LLM status messages { "message": "…" }
llm_call Fired before each LLM request { "model": "…", "promptSize": 0, "messages": 0 }
tool_call Fired when the output_manifest tool is invoked { "name": "output_manifest" }
usage Token usage after each LLM response { "input": 0, "cached": 0, "output": 0, "cost": 0 }
progress Intermediate accumulated extraction state (basedata / notes / items) ManifestResult
result Final accumulated extraction — emitted just before the stream closes ManifestResult
error Emitted on PDF parse or LLM failure; stream closes immediately after { "message": "…" }

Response 200

text/event-stream — emits status, llm_call, tool_call, usage, progress, result (and error on failure). See SSE Events table below.

ManifestResult shape (used by progress and result):

{
  "basedata": {
    "date": "2026-01-15",
    "kLieferant": 42,
    "lieferantName": "Muster GmbH",
    "manifestNr": "LS-2026-001",
    "manifestType": "lieferschein"
  },
  "notes": ["Pos. 3: VPE-Angabe fehlte, Standardwert 1 angenommen."],
  "items": {
    "pagesFrom": 1,
    "pagesTo": 2,
    "items": [
      {
        "position": 1,
        "count": 10,
        "vpe": 1,
        "unit": "Stk.",
        "articleName": "Einhängesieb Stahl",
        "liefArtNr": "ES-100",
        "mwst": "19",
        "eknetto": 450,
        "page": 1
      }
    ]
  }
}

Errors

Status Description
400 No PDF uploaded or OpenRouter key not configured — {"error":"…"}
401 Unauthorized — {"error":"…"}

Generated from @openapi JSDoc. Do not edit by hand — run npm run docs:api.