Dokumentation

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

MethodePfadBerechtigungFeature-Flag
GET/v1/invoices/{invoice_id}/field-reviewsAPI-Schlüssel—
PATCH/v1/invoices/{invoice_id}/field-reviewsAPI-Schlüssel—
POST/v1/invoices/{invoice_id}/review-sessionsAPI-SchlüsselErforderlich
GET/v1/review-sessions/{token}Sitzungs-TokenErforderlich
GET/v1/review-sessions/{token}/field-reviewsSitzungs-TokenErforderlich
PATCH/v1/review-sessions/{token}/field-reviewsSitzungs-TokenErforderlich

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
  }
}
FeldTypBeschreibung
field_pathstringDas geprüfte Feld in Punktnotation
original_valueanyDer vom Beleg gelesene Wert, aufgelöst beim Schreiben der Prüfung
corrected_valueanyDer von der prüfenden Person gelieferte Wert oder null
review_statestringneeds_review, confirmed, edited oder dismissed
confidencenumber | nullReserviert. Über diese API geschriebene Prüfungen enthalten immer null
reason_codesstring[]Warum das Feld markiert oder geändert wurde
reviewed_by_user_idUUID | nullDas Konto, dem die Entscheidung zugeordnet wurde
reviewed_attimestamp | nullWann die Entscheidung festgehalten wurde
versionintegerZä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.

FeldBedeutung
needs_reviewFelder, die noch auf eine Entscheidung warten
editedFelder, deren Wert korrigiert wurde
confirmedFelder, die wie extrahiert übernommen wurden
dismissedFelder, 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
      }
    ]
  }'
FeldTypPflichtBeschreibung
field_pathstringJaMuss ein prüfbarer Pfad sein (siehe unten)
review_statestringJaneeds_review, confirmed, edited oder dismissed
corrected_valueanyNeinStandardwert null
reason_codesstring[]NeinStandardwert: leere Liste
expected_versionintegerJaDie 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

CodeBedeutung
low_confidenceDie Extraktion war sich beim Wert unsicher
validator_warningEine Validierungsregel hat den Wert beanstandet
missing_valueDas Feld fehlte auf dem Beleg
manual_editEine Person hat den Wert geändert
source_mismatchDer Wert widerspricht einer anderen Quelle
stale_updateDer 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. und buyer.: name, address, email, phone, tax_id, iban, bank_name
  • invoice_number, currency, payment_instructions
  • issue_date, due_date, billing_period_start, billing_period_end
  • subtotal.amount, discount_total.amount, tax_total.amount, total_amount.amount
  • reference_numbers[n].value
  • line_items[n].: description, quantity, unit, unit_price, discount, total, tax_rate
  • tax_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

StatusCodeTypische Ursache
404—Die Rechnung liegt nicht in Ihrem Workspace
409field_review_conflictexpected_version passt nicht zur gespeicherten Version
422invalid_field_reviewDer 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:

MethodePfadLiefert
GET/v1/review-sessions/{token}invoice_id, allowed_origin, expires_at, invoice_json
GET/v1/review-sessions/{token}/field-reviewsDieselbe Stapel-Struktur wie die Rechnungsroute
PATCH/v1/review-sessions/{token}/field-reviewsDieselbe 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.

StatusUrsache
401Das Token ist unbekannt oder die Sitzung abgelaufen — eine abgelaufene Sitzung wird sofort gelöscht
401Das Konto, für das der Link ausgestellt wurde, existiert nicht mehr
428Für dieses Konto steht eine erneute Zustimmung zu den Rechtstexten aus; der Link wird genauso gesperrt wie eine angemeldete Sitzung
404Gehostete 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ält invoice_id, review_session_id und fields_flagged, die Anzahl der Felder mit einer Extraktionskonfidenz unter 0.85.
  • review.completed, sobald ein Stapel von Entscheidungen summary.needs_review auf null bringt. Die Payload enthält invoice_id und review_session_id. Dieses Ereignis wird auch für Entscheidungen über die Rechnungsrouten ausgelöst; ein Stapel ohne Sitzung erhält eine generierte review_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.