Feldprüfung
Einzelne extrahierte Felder bestätigen oder korrigieren und eine Rechnung optional über einen zeitlich begrenzten Link an externe Prüfer übergeben.
Die Feldprüfung hält pro extrahiertem Feld genau eine Entscheidung fest — bestätigt, korrigiert oder verworfen — und zwar neben dem Wert, den die Extraktion ursprünglich geliefert hat. Nichts wird überschrieben: Die Korrektur steht neben dem Original, und die extrahierte Rechnung selbst bleibt unverändert.
Es gibt zwei Zugänge. Feldprüfungen an einer Rechnung sind Teil der öffentlichen API und funktionieren mit jedem aktiven API-Schlüssel. Gehostete Prüfsitzungen übergeben eine einzelne Rechnung über einen Token-Link an jemanden ohne Parsurai-Konto und sind standardmäßig deaktiviert.
Endpunkte
| Methode | Pfad | Berechtigung | Feature-Flag |
|---|---|---|---|
GET | /v1/invoices/{invoice_id}/field-reviews | API-Schlüssel | — |
PATCH | /v1/invoices/{invoice_id}/field-reviews | API-Schlüssel | — |
POST | /v1/invoices/{invoice_id}/review-sessions | API-Schlüssel | Erforderlich |
GET | /v1/review-sessions/{token} | Sitzungs-Token | Erforderlich |
GET | /v1/review-sessions/{token}/field-reviews | Sitzungs-Token | Erforderlich |
PATCH | /v1/review-sessions/{token}/field-reviews | Sitzungs-Token | Erforderlich |
Die beiden Routen unter /v1/invoices/{invoice_id}/field-reviews sind weder an einen Tarif noch an ein Feature-Flag gebunden. Alles unter Gehostete Prüfsitzungen dagegen schon.
Feldprüfungen lesen
curl "https://api.parsurai.com/v1/invoices/2f7d7f8a-32fb-4a7c-a3b1-53b61b64252f/field-reviews" \
-H "X-API-Key: $PARSURAI_API_KEY"
{
"invoice_id": "2f7d7f8a-32fb-4a7c-a3b1-53b61b64252f",
"reviews": [
{
"field_path": "vendor.iban",
"original_value": "DE44500105175407324931",
"corrected_value": "DE02120300000000202051",
"review_state": "edited",
"confidence": null,
"reason_codes": ["low_confidence", "manual_edit"],
"reviewed_by_user_id": "8b2a1e4c-5f31-4d0b-9a77-6c3e2d1f4a90",
"reviewed_at": "2026-06-14T09:12:44Z",
"version": 1
}
],
"summary": {
"needs_review": 7,
"edited": 1,
"confirmed": 0,
"dismissed": 0,
"review_completion": 0.125
}
}
| Feld | Typ | Beschreibung |
|---|---|---|
field_path | string | Das geprüfte Feld in Punktnotation |
original_value | any | Der vom Beleg gelesene Wert, aufgelöst beim Schreiben der Prüfung |
corrected_value | any | Der von der prüfenden Person gelieferte Wert oder null |
review_state | string | needs_review, confirmed, edited oder dismissed |
confidence | number | null | Reserviert. Über diese API geschriebene Prüfungen enthalten immer null |
reason_codes | string[] | Warum das Feld markiert oder geändert wurde |
reviewed_by_user_id | UUID | null | Das Konto, dem die Entscheidung zugeordnet wurde |
reviewed_at | timestamp | null | Wann die Entscheidung festgehalten wurde |
version | integer | Zähler für optimistische Sperrung, steigt bei jedem Schreibvorgang |
reviews enthält nur Felder, die tatsächlich geprüft wurden. Eine unbearbeitete Rechnung liefert ein leeres Array.
Zusammenfassung
summary wird über acht feste Kernfelder berechnet — vendor.name, vendor.iban, buyer.name, invoice_number, issue_date, due_date, total_amount.amount, currency — zuzüglich jedes weiteren Feldes, das bereits eine Prüfung hat. Ein Kernfeld ohne Prüfung zählt als needs_review.
| Feld | Bedeutung |
|---|---|
needs_review | Felder, die noch auf eine Entscheidung warten |
edited | Felder, deren Wert korrigiert wurde |
confirmed | Felder, die wie extrahiert übernommen wurden |
dismissed | Felder, bei denen bewusst nichts unternommen wurde |
review_completion | (confirmed + edited + dismissed) / gesamt, von 0.0 bis 1.0 |
Eine Rechnung ganz ohne Prüfungen meldet daher needs_review: 8 und review_completion: 0.0.
Entscheidungen übermitteln
PATCH /v1/invoices/{invoice_id}/field-reviews wendet einen Stapel von Entscheidungen in einer einzigen Transaktion an. Entweder greifen alle Aktualisierungen im Body oder keine.
curl -X PATCH "https://api.parsurai.com/v1/invoices/2f7d7f8a-32fb-4a7c-a3b1-53b61b64252f/field-reviews" \
-H "X-API-Key: $PARSURAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"updates": [
{
"field_path": "vendor.iban",
"review_state": "edited",
"corrected_value": "DE02120300000000202051",
"reason_codes": ["manual_edit"],
"expected_version": 0
},
{
"field_path": "invoice_number",
"review_state": "confirmed",
"expected_version": 1
}
]
}'
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
field_path | string | Ja | Muss ein prüfbarer Pfad sein (siehe unten) |
review_state | string | Ja | needs_review, confirmed, edited oder dismissed |
corrected_value | any | Nein | Standardwert null |
reason_codes | string[] | Nein | Standardwert: leere Liste |
expected_version | integer | Ja | Die zuletzt gelesene version, 0 oder größer |
Die Antwort ist dieselbe Stapel-Struktur wie beim GET und spiegelt nach dem Schreiben alle Prüfungen der Rechnung wider.
Optimistische Sperrung
Ein nie geprüftes Feld hat keinen Datensatz, und dieses Fehlen ist Version 0. Senden Sie für die erste Entscheidung zu einem Feld expected_version: 0; der dabei angelegte Datensatz hat version: 1. Jeder weitere Schreibvorgang muss die zuletzt gelesene version senden und erhöht sie um eins.
Weicht die gespeicherte Version ab, wird der gesamte Stapel mit 409 field_review_conflict abgelehnt. Der Fehler enthält den aktuellen serverseitigen Stand des kollidierenden Feldes, sodass Sie anzeigen können, was sich unterdessen geändert hat, und mit der frischen Version erneut senden:
{
"code": "field_review_conflict",
"message": "Field review for path 'vendor.iban' has version conflict. DB: 2, expected: 1.",
"current_review": {
"field_path": "vendor.iban",
"review_state": "confirmed",
"version": 2
}
}
Begründungscodes
| Code | Bedeutung |
|---|---|
low_confidence | Die Extraktion war sich beim Wert unsicher |
validator_warning | Eine Validierungsregel hat den Wert beanstandet |
missing_value | Das Feld fehlte auf dem Beleg |
manual_edit | Eine Person hat den Wert geändert |
source_mismatch | Der Wert widerspricht einer anderen Quelle |
stale_update | Der Wert wurde gegen veraltete Daten geschrieben |
Prüfbare Felder
Nur skalare Felder der Rechnung können geprüft werden. Alles andere führt zu 422 invalid_field_review.
- Partnerfelder unter
vendor.undbuyer.:name,address,email,phone,tax_id,iban,bank_name invoice_number,currency,payment_instructionsissue_date,due_date,billing_period_start,billing_period_endsubtotal.amount,discount_total.amount,tax_total.amount,total_amount.amountreference_numbers[n].valueline_items[n].:description,quantity,unit,unit_price,discount,total,tax_ratetax_breakdown[n].:rate,taxable_amount,tax_amount
Ein Pfad, der auf ein Objekt oder eine Liste zeigt, wird ebenfalls abgelehnt — prüfbar sind ausschließlich Einzelwerte.
Fehlerbehandlung
| Status | Code | Typische Ursache |
|---|---|---|
404 | — | Die Rechnung liegt nicht in Ihrem Workspace |
409 | field_review_conflict | expected_version passt nicht zur gespeicherten Version |
422 | invalid_field_review | Der Pfad ist nicht prüfbar oder zeigt nicht auf einen Einzelwert |
404 behandelt eine fehlende Rechnung und eine Rechnung aus einem fremden Workspace identisch. Die API lässt sich damit nicht nutzen, um die Existenz fremder Rechnungs-IDs zu bestätigen.
Gehostete Prüfsitzungen
Gehostete Prüfsitzungen werden pro Deployment aktiviert und sind standardmäßig deaktiviert.
Die Sperre wirkt serverseitig und schließt im Zweifel: hosted_review_sessions_enabled steht auf false, eine nicht gesetzte Umgebungsvariable bedeutet also deaktiviert. Es gibt keinen Bypass über Header, Query-Parameter oder interne Route. Solange die Funktion aus ist, antwortet jede Route dieses Abschnitts mit 404 und dem Code hosted_review_disabled — identisch, unabhängig davon, ob es das Token in der URL je gab.
Klären Sie das mit dem Betreiber Ihres Deployments, bevor Sie darauf aufbauen, und gehen Sie davon aus, dass die Funktion aus ist, solange sie nicht bewusst eingeschaltet wurde.
Eine Prüfsitzung übergibt eine einzelne Rechnung an eine prüfende Person ohne Parsurai-Konto. Das Sitzungs-Token ist die einzige Berechtigung: Es authentifiziert für sich allein, dahinter steht keine Anmeldung.
Sitzung erstellen
POST /v1/invoices/{invoice_id}/review-sessions erwartet die Origin, die die Prüfseite einbetten darf.
curl -X POST "https://api.parsurai.com/v1/invoices/2f7d7f8a-32fb-4a7c-a3b1-53b61b64252f/review-sessions" \
-H "X-API-Key: $PARSURAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"allowed_origin": "https://ap.example.com"}'
allowed_origin ist eine serialisierte Origin — Schema, Host und optionaler Port, ohne Pfad und ohne abschließenden Schrägstrich — oder *, um die Prüfung abzuschalten.
{
"token": "0m3Zx1qKQ8w7nS2vB4tR9pL6dY5hJ0cA1fG3eU8iO2s",
"expires_at": "2026-06-14T10:12:44Z",
"allowed_origin": "https://ap.example.com"
}
Das Token wird genau einmal zurückgegeben und nur als Hash gespeichert, ist also später nicht mehr auslesbar. Es gilt eine Stunde ab Erstellung.
Sitzung verwenden
Die prüfende Person öffnet https://www.parsurai.com/{locale}/review/{token}; dort rendert Parsurai die gehostete Prüfseite zur Sitzung. Ihr eigenes Frontend kann stattdessen direkt die Sitzungs-Routen aufrufen:
| Methode | Pfad | Liefert |
|---|---|---|
GET | /v1/review-sessions/{token} | invoice_id, allowed_origin, expires_at, invoice_json |
GET | /v1/review-sessions/{token}/field-reviews | Dieselbe Stapel-Struktur wie die Rechnungsroute |
PATCH | /v1/review-sessions/{token}/field-reviews | Dieselbe Stapel-Struktur nach dem Schreiben |
invoice_json ist das rohe Extraktionsergebnis der Rechnung hinter dem Token.
Das Token steht im URL-Pfad, deshalb werden diese Antworten mit Cache-Control: no-store, private und Referrer-Policy: no-referrer ausgeliefert. Behandeln Sie den Link selbst wie ein Geheimnis: Alles, was die URL protokolliert, zwischenspeichert oder weiterreicht, gibt ihn preis.
Wann ein Link aufhört zu funktionieren
| Status | Ursache |
|---|---|
401 | Das Token ist unbekannt oder die Sitzung abgelaufen — eine abgelaufene Sitzung wird sofort gelöscht |
401 | Das Konto, für das der Link ausgestellt wurde, existiert nicht mehr |
428 | Für dieses Konto steht eine erneute Zustimmung zu den Rechtstexten aus; der Link wird genauso gesperrt wie eine angemeldete Sitzung |
404 | Gehostete Prüfsitzungen sind in diesem Deployment nicht aktiviert |
Webhook-Ereignisse
Die Feldprüfung löst zwei der in der Webhooks-Übersicht aufgeführten Ereignisse aus:
review.required, sobald eine Prüfsitzung erstellt wird — also nur dort, wo gehostete Prüfsitzungen aktiviert sind. Die Payload enthältinvoice_id,review_session_idundfields_flagged, die Anzahl der Felder mit einer Extraktionskonfidenz unter0.85.review.completed, sobald ein Stapel von Entscheidungensummary.needs_reviewauf null bringt. Die Payload enthältinvoice_idundreview_session_id. Dieses Ereignis wird auch für Entscheidungen über die Rechnungsrouten ausgelöst; ein Stapel ohne Sitzung erhält eine generiertereview_session_id.
Lesen Sie den aktuellen Stapel vor jedem Schreibvorgang. expected_version verhindert, dass zwei prüfende Personen sich gegenseitig unbemerkt überschreiben — und das nur, wenn die gesendete Version die gerade gelesene ist.