Ergebnisse abrufen
Ergebnisse werden nicht gepusht, sondern über den Auslieferungs-Feed abgeholt.
Der Feed ist eine geordnete Sicht auf abgeschlossene Läufe. Der Server merkt sich
nichts als „konsumiert“ – ihr speichert den zurückgegebenen nextCursor und schickt
ihn beim nächsten Poll wieder mit.
Der Feed: GET /v1/scans
Abschnitt betitelt „Der Feed: GET /v1/scans“curl "https://api.legentio.com/v1/scans?cursor=$CURSOR" \ -H "Authorization: Bearer $SCAN_PORTAL_API_KEY"Antwort:
{ "items": [ { "scanId": "k17c9c8f2a1b3d4e5f6a7b8c9d0e1f2", "revision": 1, "status": "completed", "environment": "prod", "documentType": { "slug": "rechnung", "name": "Rechnung" }, "fileName": "rechnung.pdf", "partnerName": "Muster GmbH", "partnerTestMode": false, "ocrConfidence": 0.98, "data": { "Rechnungsnummer": "…", "Partner": "Muster GmbH" }, "submittedAt": "2026-07-08T09:00:00.000Z", "completedAt": "2026-07-08T09:00:12.000Z", "deliveredAt": "2026-07-08T09:00:12.000Z", "resultTruncated": false } ], "nextCursor": "eyJ2IjoxLCJ0IjoxNzUyMH0"}partnerTestMode ist true, wenn der erkannte Partner für den Dokumenttyp im
Testmodus steht. Solche Läufe werden normal verarbeitet und ausgeliefert, sollten aber
nicht produktiv übernommen, sondern nur zur Kontrolle abgelegt werden (siehe
Partner).
Query-Parameter
Abschnitt betitelt „Query-Parameter“| Parameter | Beschreibung |
|---|---|
cursor |
Position aus dem nextCursor der letzten Antwort. Schließt since aus. |
since |
Startpunkt in der Vergangenheit (ISO 8601 oder Millisekunden). Für Backfill/Recovery. Schließt cursor aus. |
status |
Komma-Liste aus completed,failed. Standard: nur completed. |
environment |
prod (Standard), test oder all. |
documentType |
Auf einen Dokumenttyp-Slug einschränken. |
limit |
Seitengröße 1–200 (Standard 50). |
markdown |
true/1/yes hängt das erkannte markdown an jeden Eintrag an. |
Ohne cursor und ohne since beginnt der Feed am Anfang der Historie. status,
environment und documentType sind Lesezeit-Filter – der Cursor läuft auch
über übersprungene Läufe weiter, und ihr dürft Filter zwischen zwei Polls wechseln
(bereits passierte Einträge werden dadurch aber nicht rückwirkend sichtbar).
Die Polling-Schleife
Abschnitt betitelt „Die Polling-Schleife“cursor ← gespeicherte Position (oder leer beim ersten Mal)wiederhole in Intervallen: antwort ← GET /v1/scans?cursor={cursor} für jeden eintrag in antwort.items: verarbeite(eintrag) # idempotent! upsert nach scanId cursor ← antwort.nextCursor speichere(cursor) # NACH dem Verarbeiten persistierenSpeichert den Cursor erst nach dem Verarbeiten der Einträge. Stürzt der Client dazwischen ab, seht ihr dieselben Einträge erneut – das ist beabsichtigt (at-least-once).
Revisionen & idempotente Verarbeitung
Abschnitt betitelt „Revisionen & idempotente Verarbeitung“Jeder Eintrag trägt eine revision. Ein Retry oder eine Korrektur erhöht sie und
liefert den Lauf erneut im Feed aus, vor jedem gespeicherten Cursor. Führt euren
Speicher deshalb als Upsert nach scanId und behaltet die höchste
revision.
Ergebnis zu groß? – resultTruncated
Abschnitt betitelt „Ergebnis zu groß? – resultTruncated“data und markdown werden im Feed nur als Inline-Kopie mitgeliefert. War ein Wert
zu groß, ist resultTruncated: true und der Wert fehlt. Ladet ihn dann über die
Einzelabfrage nach.
Einzelabfrage: GET /v1/scans/{scanId}
Abschnitt betitelt „Einzelabfrage: GET /v1/scans/{scanId}“Liefert einen einzelnen Lauf in derselben Form wie ein Feed-Eintrag – zusätzlich aber:
- die nicht-terminalen Status (
processing, solange der Lauf noch läuft), - für abgeschlossene Läufe das vollständige
data(bei Bedarf aus dem ausgelagerten Speicher nachgeladen) sowierawOcrResult(OCR-Rohergebnis).
curl "https://api.legentio.com/v1/scans/$SCAN_ID?markdown=true" \ -H "Authorization: Bearer $SCAN_PORTAL_API_KEY"Der Parameter markdown=true hängt das vollständige erkannte Markdown an. Unbekannte
IDs (und interne Schema-Tests) sind ein 404.
Fehlgeschlagene Läufe
Abschnitt betitelt „Fehlgeschlagene Läufe“Bei status = failed tragen die Einträge failureReason (maschinenlesbar) und
error (deutsche Meldung) statt data. Nimm failed über
status=completed,failed in den Feed auf, wenn ihr Fehlschläge automatisch
auswerten wollt.