Zurück

API-Dokumentation

Die Privago REST-API deckt den kompletten Upload → Redact → Export Flow ab. Hinweis: Einen Maschinenzugang (API-Schlüssel oder Service-Accounts) gibt es derzeit nicht — die folgenden Beispiele setzen ein Token aus einer aktiven Browser-Sitzung voraus. Interaktive Swagger-UI: privago.eu/docs

1. Authentifizierung

Alle Endpunkte (außer /health) erfordern einen gültigen JWT-Bearer-Token aus Keycloak. Token-Lebensdauer: 5 Minuten.

# Token abrufen (Keycloak)
# HINWEIS: Der Password-Grant (Direct Access Grants) ist im Realm derzeit
# DEAKTIVIERT — dieses Beispiel setzt voraus, dass er fuer API-Zugriffe
# freigeschaltet wurde. Eigene API-Keys existieren noch nicht (Roadmap).
TOKEN=$(curl -s -X POST \
  https://privago.eu/auth/realms/privago/protocol/openid-connect/token \
  -d "grant_type=password" \
  -d "client_id=privago-api" \
  -d "username=DEINE_EMAIL" \
  -d "password=DEIN_PASSWORT" \
  | jq -r '.access_token')

echo $TOKEN

Den Token bei jedem Request als Authorization: Bearer $TOKEN Header mitsenden.

2. Dokument hochladen

POST /api/v1/documents — Multipart-Form mit file Feld. Max. 100 MB und 150 Seiten. Unterstütztes Format: PDF (digital oder gescannt).

curl -s -X POST https://privago.eu/api/v1/documents \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@vertrag.pdf" \
  | jq .

# Antwort:
# {
#   "data": {
#     "document_id": "550e8400-e29b-41d4-a716-446655440000",
#     "filename": "vertrag.pdf",
#     "status": "uploaded"
#   }
# }

DOC_ID="550e8400-e29b-41d4-a716-446655440000"

3. Verarbeitungsstatus prüfen

GET /api/v1/documents/{id} — Poll alle 2 Sekunden bis status == "ready_for_review".

# Einmalig prüfen
curl -s -H "Authorization: Bearer $TOKEN" \
  https://privago.eu/api/v1/documents/$DOC_ID \
  | jq '.data.status'

# Poll-Loop (bash)
while true; do
  STATUS=$(curl -s -H "Authorization: Bearer $TOKEN" \
    https://privago.eu/api/v1/documents/$DOC_ID | jq -r '.data.status')
  echo "Status: $STATUS"
  [ "$STATUS" = "ready_for_review" ] && break
  [ "$STATUS" = "failed" ] && echo "Fehler!" && exit 1
  sleep 2
done

Status-Werte:

  • uploaded — Hochgeladen, Verarbeitung startet
  • processing — KI analysiert das Dokument
  • ready_for_review — Analyse abgeschlossen, bereit zur Prüfung
  • failed — Verarbeitung fehlgeschlagen
  • exported — PDF wurde geschwärzt und exportiert

4. PII-Entitäten abrufen

GET /api/v1/documents/{id}/entities — gibt alle erkannten PII-Entitäten zurück. Unterstützt Pagination (page, page_size) und Filter (category, min_confidence).

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://privago.eu/api/v1/documents/$DOC_ID/entities?page_size=50" \
  | jq '.data[] | {id, category, text, confidence, status}'

# Nur Personennamen mit Konfidenz > 80%:
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://privago.eu/api/v1/documents/$DOC_ID/entities?category=person_name&min_confidence=0.8" \
  | jq .

5. Entitäten akzeptieren

PATCH /api/v1/documents/{id}/entities/{entity_id} — Status setzen auf accepted oder rejected.

Für die offenen Vorschläge mehrerer Kategorien auf einmal: PATCH /api/v1/documents/{id}/entities mit from_status, to_status und der Pflichtliste categories. Nur Vorschläge dieser Kategorien ändern sich. Zulässig ist jeder Eintrag (bis 50 Zeichen, höchstens 512 Einträge), der eine bekannte Kategorie ist oder im Dokument offene Vorschläge hat — auch manual. Fehlt die Liste, ist sie leer oder ist ein Eintrag weder bekannt noch offen, antwortet die API mit 422 und ändert nichts. Die Aktion läuft serverseitig über alle Entitäten des Dokuments in diesen Kategorien — anders als eine Schleife über eine abgerufene Seite, die bei 200 Einträgen endet. Welche Kategorien noch offene Vorschläge haben, nennt meta.open_by_category in GET /api/v1/documents/{id}/entities.

ENTITY_ID="abc123..."

# Entität akzeptieren (wird im Export geschwärzt)
curl -s -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "accepted"}' \
  https://privago.eu/api/v1/documents/$DOC_ID/entities/$ENTITY_ID \
  | jq '.data.status'

# Offene Vorschlaege je Kategorie (nur Zahlen)
curl -s -H "Authorization: Bearer $TOKEN" \
  https://privago.eu/api/v1/documents/$DOC_ID/entities \
  | jq '.meta.open_by_category'

# Offene Vorschlaege der genannten Kategorien auf einmal entscheiden
curl -s -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"from_status": "proposed", "to_status": "accepted", "categories": ["iban", "person_name"]}' \
  https://privago.eu/api/v1/documents/$DOC_ID/entities \
  | jq '.data.updated_count'

# Oder: den Rest einer Kategorie ablehnen, nachdem einzelne akzeptiert wurden
curl -s -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"from_status": "proposed", "to_status": "rejected", "categories": ["phone"]}' \
  https://privago.eu/api/v1/documents/$DOC_ID/entities \
  | jq '.data.updated_count'

6. Export auslösen & herunterladen

POST /api/v1/documents/{id}/export — Startet den asynchronen Export-Task. Danach poll auf GET /export/{export_id} bisstatus == "ready".

# Export starten
EXPORT_ID=$(curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  https://privago.eu/api/v1/documents/$DOC_ID/export \
  | jq -r '.data.export_id')

# Status pollen
while true; do
  RESULT=$(curl -s -H "Authorization: Bearer $TOKEN" \
    https://privago.eu/api/v1/documents/$DOC_ID/export/$EXPORT_ID)
  STATUS=$(echo $RESULT | jq -r '.data.status')
  echo "Export-Status: $STATUS"
  if [ "$STATUS" = "ready" ]; then
    break
  fi
  [ "$STATUS" = "failed" ] && echo "Export fehlgeschlagen!" && exit 1
  sleep 2
done

# Geschwärztes PDF über den Download-Proxy herunterladen.
# Hinweis: das Feld data.download_url ist ein RELATIVER API-Pfad und
# erfordert denselben Bearer-Token wie alle anderen Endpunkte.
curl -L -H "Authorization: Bearer $TOKEN" \
  -o geschwärzt.pdf "https://privago.eu/api/v1/documents/$DOC_ID/export/$EXPORT_ID/download"
echo "✅ Gespeichert als geschwärzt.pdf"

7. Kompletter Flow (ein Script)

Alles zusammen: Upload → warten → alle akzeptieren → exportieren → herunterladen.

#!/usr/bin/env bash
set -euo pipefail

API="https://privago.eu/api/v1"
FILE="${1:-dokument.pdf}"

# 1. Token
# HINWEIS: Der Password-Grant (Direct Access Grants) ist im Realm derzeit
# DEAKTIVIERT — dieses Beispiel setzt voraus, dass er fuer API-Zugriffe
# freigeschaltet wurde. Eigene API-Keys existieren noch nicht (Roadmap).
TOKEN=$(curl -s -X POST \
  https://privago.eu/auth/realms/privago/protocol/openid-connect/token \
  -d "grant_type=password&client_id=privago-api" \
  -d "username=$PRIVAGO_EMAIL&password=$PRIVAGO_PASSWORD" \
  | jq -r '.access_token')

# 2. Upload
DOC_ID=$(curl -s -X POST "$API/documents" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@$FILE" | jq -r '.data.document_id')
echo "Hochgeladen: $DOC_ID"

# 3. Warten bis ready
until [ "$(curl -s -H "Authorization: Bearer $TOKEN" \
  "$API/documents/$DOC_ID" | jq -r '.data.status')" = "ready_for_review" ]; do
  sleep 2
done
echo "Analyse abgeschlossen"

# 4. Alle offenen Vorschlaege entscheiden.
#    Der Export ist gesperrt, solange auch nur eine Erkennung unbearbeitet ist
#    (409 EXPORT_INCOMPLETE_REVIEW mit open_count und open_by_category). Die
#    Sammelaktion laeuft serverseitig ueber ALLE Entitaeten der genannten
#    Kategorien — eine Schleife ueber ?page_size=200 wuerde bei mehr als 200
#    Entitaeten den Rest stehen lassen und der Export bliebe gesperrt.
#    categories ist Pflicht: hier alle Kategorien mit offenen Vorschlaegen.
#    Ist nichts offen, ist die Liste leer — dann gibt es nichts zu entscheiden
#    (eine leere Liste beantwortet die API mit 422).
CATS=$(curl -s -H "Authorization: Bearer $TOKEN" \
  "$API/documents/$DOC_ID/entities" | jq -c '.meta.open_by_category | keys')
if [ "$CATS" != "[]" ]; then
  curl -s -X PATCH -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d "{\"from_status\":\"proposed\",\"to_status\":\"accepted\",\"categories\":$CATS}" \
    "$API/documents/$DOC_ID/entities" | jq '.data.updated_count'
fi
echo "Entitäten entschieden"

# 5. Export
EID=$(curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  "$API/documents/$DOC_ID/export" | jq -r '.data.export_id')

# Auf "failed" pruefen, nicht nur auf "ready" — sonst pollt das Skript endlos,
# wenn ein Guard im Export-Task greift (z.B. no_redactions, wenn alle
# Vorschlaege abgelehnt wurden und keine Schwaerzung uebrig ist).
while true; do
  S=$(curl -s -H "Authorization: Bearer $TOKEN" \
    "$API/documents/$DOC_ID/export/$EID" | jq -r '.data.status, .data.error')
  case "$(echo "$S" | head -1)" in
    ready)  break ;;
    failed) echo "Export fehlgeschlagen: $(echo "$S" | tail -1)"; exit 1 ;;
  esac
  sleep 2
done

curl -L -H "Authorization: Bearer $TOKEN" \
  -o "geschwärzt_$(basename $FILE)" \
  "$API/documents/$DOC_ID/export/$EID/download"
echo "✅ Export fertig: geschwärzt_$(basename $FILE)"

8. Fehler-Codes

HTTPCodeBeschreibung
401UNAUTHORIZEDToken fehlt oder abgelaufen
402—Monatliches Seitenkontingent erreicht (Klartextmeldung ohne Fehlercode)
404NOT_FOUNDDokument oder Entität nicht gefunden
409EXPORT_INCOMPLETE_REVIEWExport gesperrt: unbearbeitete Vorschläge vorhanden (open_count nennt die Anzahl, open_by_category die Anzahl je Kategorie)
409DOCUMENT_NOT_READYDokument ist nicht im Zustand ready_for_review oder exported
409OCR_REVIEW_REQUIREDScan-Ergebnis muss vor dem Export bestätigt werden
410ORIGINAL_PURGEDOriginal nach Aufbewahrungsfrist entfernt — kein Export mehr möglich
422VALIDATION_ERRORUngültige Request-Parameter, nicht unterstütztes Format, Datei über 100 MB oder mehr als 150 Seiten
429RATE_LIMITEDZu viele Anfragen (Standard 600/min, Upload 30/min, Export 20/min pro IP; Retry-After-Header beachten)
500INTERNAL_ERRORInterner Serverfehler

9. Rate Limits

  • • 600 Requests/Minute pro Client-IP (Standard, alle Endpunkte)
  • • 30 Uploads/Minute und 20 Export-Starts/Minute pro Client-IP
  • • Bei Überschreitung: HTTP 429 (Code RATE_LIMITED) mit Retry-After-Header

Interaktive API-Referenz

Alle Endpunkte mit Schemas und Try-it-out direkt im Browser testen.

Swagger UI öffnen