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 $TOKENDen 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
doneStatus-Werte:
uploaded— Hochgeladen, Verarbeitung startetprocessing— KI analysiert das Dokumentready_for_review— Analyse abgeschlossen, bereit zur Prüfungfailed— Verarbeitung fehlgeschlagenexported— 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 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
| HTTP | Code | Beschreibung |
|---|---|---|
| 401 | UNAUTHORIZED | Token fehlt oder abgelaufen |
| 402 | — | Monatliches Seitenkontingent erreicht (Klartextmeldung ohne Fehlercode) |
| 404 | NOT_FOUND | Dokument oder Entität nicht gefunden |
| 409 | EXPORT_INCOMPLETE_REVIEW | Export gesperrt: unbearbeitete Vorschläge vorhanden (Feld open_count nennt die Anzahl) |
| 409 | DOCUMENT_NOT_READY | Dokument ist nicht im Zustand ready_for_review oder exported |
| 409 | OCR_REVIEW_REQUIRED | Scan-Ergebnis muss vor dem Export bestätigt werden |
| 410 | ORIGINAL_PURGED | Original nach Aufbewahrungsfrist entfernt — kein Export mehr möglich |
| 422 | VALIDATION_ERROR | Ungültige Request-Parameter, nicht unterstütztes Format, Datei über 100 MB oder mehr als 150 Seiten |
| 429 | RATE_LIMITED | Zu viele Anfragen (Standard 600/min, Upload 30/min, Export 20/min pro IP; Retry-After-Header beachten) |
| 500 | INTERNAL_ERROR | Interner 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) mitRetry-After-Header
Interaktive API-Referenz
Alle Endpunkte mit Schemas und Try-it-out direkt im Browser testen.