92 lines
3.0 KiB
Markdown
92 lines
3.0 KiB
Markdown
# `POST /delivery/parse`
|
|
|
|
Protected. Requires a valid session cookie (`credentials: 'include'`).
|
|
|
|
Parse document (SSE)
|
|
|
|
Accepts an invoice or delivery note as PDF or text file
|
|
(`multipart/form-data`, field `file`) and streams extraction results as
|
|
Server-Sent Events until parsing is complete.
|
|
|
|
PDFs are read via `pdftotext -layout`; text files are decoded as UTF-8.
|
|
Pages are separated by the form feed character (`\f`). If no form feed
|
|
is present, the input is treated as a single page.
|
|
|
|
The extracted pages are fed 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` (or the server's
|
|
`OPENROUTER_FREE_KEY` if not configured); 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 |
|
|
|-------|----------|------|-------------|
|
|
| `file` | yes | file | Document to parse (max 50 MB, application/pdf or text file) |
|
|
|
|
## SSE Events
|
|
|
|
The response is a `text/event-stream`. Events are emitted in order until the stream closes.
|
|
|
|
| Event | Description | Payload |
|
|
|-------|-------------|---------|
|
|
| `status` | Document 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 document 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",
|
|
"lieferant_id": 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 file uploaded, unsupported file type, or OpenRouter key not configured — `{"error":"…"}` |
|
|
| 401 | Unauthorized — `{"error":"…"}` |
|
|
|
|
---
|
|
|
|
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._
|