Mit der SCFold-API kannst du Dokumente aus deinem eigenen Programm analysieren und die erkannten Werte als JSON abrufen. Du brauchst ein aktives Kundenkonto und einen eigenen API-Schlüssel. Diese Anleitung ist ohne Anmeldung lesbar; für die API-Aufrufe ist dein Schlüssel erforderlich.

![API verwenden: Konto und Schlüssel erstellen, Ausgabefelder speichern, Datei oder URL senden und eine direkte Antwort oder ZIP-Ergebnisse abrufen.](diagrams/public-api.svg)

## 1. Konto und API-Schlüssel vorbereiten

1. Erstelle ein Konto und bestätige deine E-Mail-Adresse. Die Schritte stehen unter [Konto & Anmeldung](konten-rechte.md).
2. Melde dich an und öffne deinen Dokumentenbereich.
3. Klappe **Einstellungen → API-Schlüssel** auf, gib unter **Name** eine Bezeichnung ein, etwa „Meine Anwendung“, und wähle **Schlüssel erstellen**.
4. Kopiere den vollständigen Schlüssel sofort. Er wird nur einmal angezeigt; später siehst du eine maskierte Kennung. Du kannst höchstens 20 aktive Schlüssel haben.
5. Hinterlege den Schlüssel vertraulich in deiner Anwendung. Verwende ihn nur auf deinem Server oder in deinem eigenen lokalen Programm; veröffentliche ihn nicht in einer Webseite, einem Screenshot oder einem gemeinsamen Repository.

Über **Widerrufen** sperrst du einen Schlüssel sofort für weitere Aufrufe. Hast du ihn verloren, erstelle einen neuen und widerrufe den alten. Das Widerrufen löscht keine bereits analysierten Dokumente. Ein anderer gültiger Schlüssel desselben Kontos kann weiterhin auf deine noch verfügbaren Jobs zugreifen.

## 2. Gewünschte Ausgabefelder festlegen

Speichere im Dokumentenbereich unter **Ausgabefelder** die gewünschten Feldnamen, beispielsweise `invoice_number` und `iban`. Neue Analysen geben genau diese Schlüssel zurück. Erkannte Werte sind Strings; ein fehlender oder nicht sicher erkannter Wert ist echtes JSON-`null`.

Ohne gespeicherte Felder ist `user_json` ein leeres Objekt `{}`. Bereits angenommene ZIP-Aufträge behalten die bei ihrer Annahme gespeicherten Felder, auch wenn du das Profil anschließend änderst. Prüfe wichtige Werte am Original, bevor du sie weiterverwendest.

## 3. Welche Endpunkte gibt es?

Die folgenden Pfade gehören zur SCFold-Adresse. Jede Kundenanfrage braucht den Header `Authorization: Bearer DEIN_API_SCHLUESSEL`.

| Methode und Pfad | Zweck und Antwort |
| --- | --- |
| `GET /api/v1/customer/identity` | Prüft den Schlüssel und gibt die zugehörige Benutzer-ID zurück. |
| `POST /api/v1/customer/invoke` | Analysiert eine hochgeladene Datei oder eine Datei von einer öffentlichen URL. Eine einzelne PNG-, JPEG- oder PDF-Datei liefert direkt HTTP 200; ein ZIP liefert HTTP 202 mit Job-ID. |
| `GET /api/v1/customer/jobs/{job_id}` | Liefert den aktuellen Status deines ZIP-Auftrags, Zähler und Zeitpunkte. |
| `GET /api/v1/customer/jobs/{job_id}/results` | Liefert nach Abschluss die gespeicherten Ergebnisse und mögliche Fehler je Datei. |
| `GET /api/v1/customer/business-plugins/{plugin_id}/records` | Eigene aktuelle Fachdatensätze; `page` blättert mit 25 Einträgen, `from`/`to` begrenzen nach Belegdatum. |
| `GET /api/v1/customer/business-plugins/{plugin_id}/analytics` | Bestätigte aktuelle Einkäufe nach Zeitraum, Artikel, Händler und Zahlungsgruppe. |

Schlüssel verwaltest du normalerweise im Kundenbereich. Für eine eigene Kontooberfläche gibt es außerdem `GET` und `POST /api/v1/account/api-keys` sowie `DELETE /api/v1/account/api-keys/{key_id}`. Diese verlangen eine angemeldete Kontositzung; Erstellen und Widerrufen brauchen zusätzlich den `X-CSRFToken`-Header. Ein API-Schlüssel allein reicht für die Schlüsselverwaltung nicht aus.

## 4. Beispiele vorbereiten

Die Beispiele verwenden `curl` in einer Bash-Shell. Setze die Adresse deiner SCFold-Installation. Der Schlüssel wird verdeckt abgefragt und erscheint dadurch nicht als Klartext im eingegebenen Befehl.

```bash
export SCFOLD_ORIGIN='https://scfold.io'
read -r -s -p 'SCFold API-Schlüssel: ' SCFOLD_API_KEY
export SCFOLD_API_KEY
```

Prüfe zuerst deinen Schlüssel:

```bash
curl --fail-with-body "$SCFOLD_ORIGIN/api/v1/customer/identity" \
  -H "Authorization: Bearer $SCFOLD_API_KEY"
```

Eine gültige Antwort sieht beispielsweise so aus:

```json
{"authenticated":true,"user_id":42}
```

Die Dateien und URLs in den nächsten Beispielen ersetzt du durch deine eigenen. Die Download-URLs müssen öffentlich erreichbar sein; geschützte Downloads mit zusätzlichen Anmeldedaten werden nicht unterstützt.

## 5. Einzeldatei hochladen oder per URL analysieren

Lade ein PNG, JPEG oder PDF hoch. Die Verbindung bleibt bis zur fertigen Antwort offen:

```bash
curl --fail-with-body "$SCFOLD_ORIGIN/api/v1/customer/invoke" \
  -H "Authorization: Bearer $SCFOLD_API_KEY" \
  -F 'file=@rechnung.png' -F 'full_detail=true'
```

Alternativ übergibst du eine Bild- oder PDF-URL als JSON:

```bash
curl --fail-with-body "$SCFOLD_ORIGIN/api/v1/customer/invoke" \
  -H "Authorization: Bearer $SCFOLD_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"url":"https://dein-dateihost.example/rechnung.png","full_detail":false}'
```

Übermittle genau eine Quelle: `file` oder `url`. Ohne `full_detail` erhältst du standardmäßig nur die gewünschten Werte:

```json
{"user_json":{"invoice_number":"00042","iban":null}}
```

`full_detail=true` ergänzt `analysis_json`, unter anderem mit Seiten und erkannten Regionen, Feldentscheidungen, Analysestatus und Versionsangaben. Führende Nullen bleiben in Strings erhalten. Ein fehlender Wert und ein technischer Analysefehler sind unterschiedlich: Ein technischer Fehler liefert einen Fehlerstatus, nicht nur leere Werte.

## 6. Mehrere Bilder als ZIP verarbeiten

Ein ZIP mit PNG-/JPEG-Bildern wird im Hintergrund verarbeitet. Auch ein ZIP mit nur einem Bild ist ein Auftrag. So lädst du ein Archiv hoch:

```bash
curl --fail-with-body "$SCFOLD_ORIGIN/api/v1/customer/invoke" \
  -H "Authorization: Bearer $SCFOLD_API_KEY" \
  -F 'file=@rechnungen.zip'
```

So übergibst du eine ZIP-URL:

```bash
curl --fail-with-body "$SCFOLD_ORIGIN/api/v1/customer/invoke" \
  -H "Authorization: Bearer $SCFOLD_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"url":"https://dein-dateihost.example/rechnungen.zip"}'
```

Die Antwort HTTP 202 bedeutet, dass der Auftrag angenommen wurde. Sie enthält `job_id`, `status`, `total`, `successful`, `failed`, Zeitpunkte sowie `status_url` und `results_url`. Die zurückgegebenen URLs sind Pfade, die du an deine SCFold-Adresse anhängst. Sie sind noch keine fertigen Erkennungsergebnisse.

Übernimm die zurückgegebene Job-ID und frage den Status beispielsweise alle zwei Sekunden ab:

```bash
export SCFOLD_JOB_ID='hier-die-zurueckgegebene-job-id-eintragen'
curl --fail-with-body "$SCFOLD_ORIGIN/api/v1/customer/jobs/$SCFOLD_JOB_ID" \
  -H "Authorization: Bearer $SCFOLD_API_KEY"
```

| Status | Bedeutung |
| --- | --- |
| `queued` | Der Auftrag wartet auf die Verarbeitung. |
| `running` | Die Bilder werden verarbeitet. |
| `completed` | Alle Dateien wurden erfolgreich verarbeitet. |
| `partially_failed` | Einige Dateien waren erfolgreich, andere haben Fehler. |
| `failed` | Keine Datei wurde erfolgreich verarbeitet. |

Beende das Polling bei einem der letzten drei Zustände. Rufe dann die Ergebnisse ab:

```bash
curl --fail-with-body "$SCFOLD_ORIGIN/api/v1/customer/jobs/$SCFOLD_JOB_ID/results?full_detail=true" \
  -H "Authorization: Bearer $SCFOLD_API_KEY"
```

Jeder Eintrag in `results` enthält Position, Dateiname, Status und sein eigenes `user_json`. Angelegte Analysen enthalten außerdem Dokument-/Analysekennung und Ergebnisrevision. Fehlgeschlagene Einträge haben ein `error` mit `code` und `message`. Mit `full_detail=true` erhältst du zusätzlich `analysis_json` je Eintrag. Eine fehlerhafte Datei verhindert nicht die Verarbeitung der übrigen gültigen Bilder.

Vor Abschluss liefert der Ergebnisabruf HTTP 409 `job_not_ready`; warte weiter auf einen Endzustand. Wiederholte Abrufe oder ein Wechsel von `full_detail` starten keine neue Analyse. Die gespeicherten Job-Ergebnisse bleiben die ursprüngliche maschinelle Fassung, auch wenn du das Dokument später im Konto korrigierst.

Wenn du Ergebnisse automatisch an deine Anwendung senden lassen möchtest, kannst du zusätzlich einen [Webhook im Kundenbereich einrichten](konten-rechte.md#ergebnisse-an-eine-eigene-anwendung-senden). Deine direkte API-Antwort und die hier beschriebenen Abrufe bleiben unabhängig vom Erfolg dieser Zustellung verfügbar.

## 7. Grenzen und Aufbewahrung

| Bereich | Grenze |
| --- | --- |
| Einzeldatei | PNG/JPEG/PDF, maximal 2.000.000 Bytes, zehn Seiten und 20 Millionen Pixel je Bild beziehungsweise Seite |
| ZIP | PNG/JPEG-Einträge; maximal 20 MB Archiv, 50 Dateien, 200 Verzeichniseinträge, 2 MB je Datei, 50 MB insgesamt entpackt und Expansionsfaktor 200 |
| Download per URL | Öffentliches HTTP/HTTPS auf Port 80/443, maximal drei Weiterleitungen, 20 Sekunden und 20 MB |
| Analyseanfragen | 60 Aufrufe des Invoke-Endpunkts je Konto und Stunde |
| API-Schlüssel | Höchstens 20 aktive Schlüssel je Konto |
| ZIP-Aufträge | Status und Ergebnisse sind 30 Tage ab Annahme verfügbar |

Leere, beschädigte oder verschlüsselte ZIPs sowie unsichere Pfade, Dateiverknüpfungen und doppelte Dateinamen werden abgelehnt. ZIPs dürfen keine weiteren ZIPs oder PDFs als Bilder enthalten. Private Netzwerkadressen und URLs mit Zugangsdaten oder Fragmenten werden nicht geladen; Weiterleitungen werden ebenfalls geprüft.

Nach Ablauf sind die Jobdaten nicht mehr abrufbar. Die zugehörigen Dokumente bleiben im Konto, bis du sie löschst. Wenn du ein Dokument löschst, ist auch sein gespeichertes Job-Ergebnis nicht mehr verfügbar. Andere Kunden können deine Jobs nicht lesen.

## 8. Fehler verstehen

Fehlerantworten enthalten `error.code` und `error.message`. Werte den HTTP-Status und den Code aus, statt dich auf den Wortlaut der Nachricht zu verlassen.

```json
{"error":{"code":"invalid_source","message":"Provide exactly one file or URL."}}
```

| HTTP-Status | Was du tun kannst |
| --- | --- |
| 400 | Quelle, Parameter, URL oder ZIP prüfen. `full_detail` muss `true` oder `false` sein. |
| 401 | Schlüssel prüfen; er kann fehlen, widerrufen oder ungültig sein. Auch ein inaktives Konto wird abgewiesen. |
| 403 | Prüfen, ob dein Konto die erforderliche Berechtigung hat. |
| 404 | Job-ID und verwendetes Konto prüfen. Fremde und nicht mehr vorhandene Jobs sind nicht zugänglich. |
| 409 | Bei `job_not_ready` weiter auf den Endzustand warten; bei `key_limit` einen alten Schlüssel widerrufen. |
| 410 | Der Auftrag ist abgelaufen; nach der Bereinigung erhältst du stattdessen 404. |
| 413 | Datei, ZIP-Größe, Dateianzahl oder Entpackumfang reduzieren. |
| 415 | PNG/JPEG/PDF oder ein ZIP mit PNG/JPEG-Bildern verwenden. |
| 422 | Datei auf Lesbarkeit und URL auf Erreichbarkeit prüfen. |
| 429 | Die stündliche Grenze ist erreicht. Später erneut versuchen. |
| 503 / 504 | Verarbeitung ist nicht verfügbar beziehungsweise hat zu lange gedauert. Status prüfen oder später erneut versuchen; bei anhaltenden Problemen den Support kontaktieren. |

Bewahre die Job-ID für Rückfragen auf und gib deinen vollständigen API-Schlüssel niemals an den Support weiter.

## WordPress-Integration

Das [WordPress-Plugin](wordpress.md) verbindet Mediathek-Bilder mit der Kunden-API und authentifizierten Webhooks. Mit der optionalen UUID `client_request_id` enthalten Direktantwort und Webhook ein identisches `integration`-Objekt samt revisionsgebundenem Klar-PNG-Pfad. Ohne diese Option bleibt die bisherige Ausgabe erhalten. Der Bildabruf verlangt einen gültigen API-Schlüssel desselben Kunden.

## Einkaufs-Plugin über die API nutzen

Aktiviere zuerst [Tägliche Einkäufe](fachplugins.md) im Konto. Ohne explizite Auswahl wird genau ein aktives automatisches Einkaufsziel gebunden. Mit mehreren Zielen sende `plugin_ids`: als JSON ein Array wie `["daily-shopping"]`, im Formular ein JSON-String, beispielsweise `-F 'plugin_ids=["daily-shopping"]'`. Es sind 1–20 eindeutige aktive Kennungen erlaubt. ZIP-Einträge behalten diese Auswahl und die Pluginversion vom Annahmezeitpunkt. Unverfügbare Ziele werden vor einem URL-Download abgewiesen.

Die Direktantwort behält `user_json` unverändert; mit `full_detail=true` enthält `analysis_json.business_plugins` zusätzlich die maschinellen Fachvorschläge und Quellen. Aktuelle korrigierte Fachwerte liest du über die Datensatzroute. Automatisch erfasste Bons sind zunächst Entwürfe; bestätige sie im Konto für die Auswertung.

Ersetze `{plugin_id}` in den beiden Abrufpfaden durch `daily-shopping`. `from=2026-10-01&to=2026-10-31` wählt inklusive Belegdatumsgrenzen. Die Auswertung beginnt ohne Parameter beim aktuellen Monat bis heute; die Datensatzroute liefert ohne Datumsfilter alle aktuellen Einträge. Beträge sind exakte Dezimalstrings, Währungen bleiben getrennt und jede Gruppe enthält ihre Datensatzkennungen. Die Abrufe benötigen denselben Kontoschlüssel und verbrauchen kein weiteres Kontingent.

Ein konfiguriertes Pluginangebot gilt auch für API- und ZIP-Verarbeitung: Dokumente und tatsächliche Gesamtseiten werden vor Analyse reserviert, erfolgreich verarbeitete Dokumente gebucht und technische Fehler freigegeben. HTTP 429 `quota_exceeded` bezeichnet eine erschöpfte Pluginmenge; HTTP 403 `plugin_not_entitled` eine fehlende Freigabe. ZIPs können zunächst HTTP 202 liefern und anschließend entsprechende Einzelfehler ausweisen.

## Tarifrechte, Zielplugin und Wiederholungen

Für neue API-Aufträge müssen API und Dokumentanalyse in deinem aktuellen Angebot freigegeben sein. Ein noch vorhandener Schlüssel ersetzt diese Freigabe nicht. Dokument- und Gesamtseitenkontingente werden gemeinsam mit dem Web-Upload geprüft. Details findest du unter [Tarif & Probemonat](tarife.md).

Bei mehreren erlaubten Plugins übergibst du `plugin_ids` als Liste mit den gewünschten Plugin-Kennungen. Für einen Multipart-Upload ist das beispielsweise `-F 'plugin_ids=["daily-shopping"]'`; bei JSON steht die Liste direkt im Anfrageobjekt. Ohne eindeutige Auswahl wird der Auftrag abgewiesen.

Für eine sichere Wiederholung kannst du `Idempotency-Key` mit einer eigenen eindeutigen Kennung von 1–128 Zeichen mitsenden. Verwende dieselbe Kennung nur für dieselben Dateiinhalte. Eine abgeschlossene Einzelanalyse wird erneut zurückgegeben; ein noch laufender Auftrag liefert einen Konflikt. Bei einem ZIP liefert eine Wiederholung denselben Job. Für eine bewusst neue Analyse verwendest du eine neue Kennung.
