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:

  • uploadedHochgeladen, Verarbeitung startet
  • processingKI analysiert das Dokument
  • ready_for_reviewAnalyse abgeschlossen, bereit zur Prüfung
  • failedVerarbeitung fehlgeschlagen
  • exportedPDF 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 alle offenen Vorschläge auf einmal: PATCH /api/v1/documents/{id}/entities mit from_status und to_status. Die Aktion läuft serverseitig über alle Entitäten des Dokuments — anders als eine Schleife über eine abgerufene Seite, die bei 200 Einträgen endet.

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'

# Alle offenen Vorschlaege auf einmal entscheiden (Sammelaktion)
curl -s -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"from_status": "proposed", "to_status": "accepted"}' \
  https://privago.eu/api/v1/documents/$DOC_ID/entities \
  | jq '.data.updated_count'

# Oder: den Rest 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"}' \
  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). Die Sammelaktion laeuft serverseitig ueber
#    ALLE Entitaeten — eine Schleife ueber ?page_size=200 wuerde bei mehr als
#    200 Entitaeten den Rest stehen lassen und der Export bliebe gesperrt.
curl -s -X PATCH -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"from_status":"proposed","to_status":"accepted"}' \
  "$API/documents/$DOC_ID/entities" | jq '.data.updated_count'
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
402Monatliches Seitenkontingent erreicht (Klartextmeldung ohne Fehlercode)
404NOT_FOUNDDokument oder Entität nicht gefunden
409EXPORT_INCOMPLETE_REVIEWExport gesperrt: unbearbeitete Vorschläge vorhanden (Feld open_count nennt die Anzahl)
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