# `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`): ```json { "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`._