API-Dokumentation

Ein Endpunkt, um Belege direkt aus einem ERP- oder Buchhaltungssystem prüfen zu lassen, ohne die Web-Oberfläche zu nutzen. Ab dem Pro-Tarif verfügbar.

Authentifizierung

API-Keys werden im Profil erstellt und als X-API-Key-Header mitgeschickt. Keys werden nur einmal im Klartext angezeigt und ausschließlich als Hash gespeichert.

Endpunkt POST

POST /api/v1/check
X-API-Key: <dein-api-key>
Content-Type: application/json

Format wird automatisch erkannt (EDIFACT, XRechnung/Peppol-XML, ZUGFeRD/Factur-X). Body-Varianten:

{ "content": "UNB+UNOC:3+...'", "content_base64": false, "filename": "bestellung-2026-07.edi" }

Für vollständige PDF/A-3-Dateien (ZUGFeRD/Factur-X mit eingebettetem XML) content_base64: true setzen und den Base64-kodierten PDF-Inhalt übergeben. filename ist optional (nur für Historie/Webhook-Payload) - ohne Angabe wird ein generischer Dateiname verwendet.

Beispiel: cURL

curl -X POST https://ihre-instanz.example/api/v1/check \ -H "X-API-Key: ev_live_xxx" \ -H "Content-Type: application/json" \ -d '{"content": "UNB+UNOC:3+ABSENDER...", "content_base64": false}'

Antwort (EDIFACT-Beispiel)

{ "format": "EDIFACT", "message_type": "ORDERS", "check_id": 4821, "errors": [ {"line": "12", "msg": "Pflichtfeld fehlt", "severity": "error", "fix": "..."} ], "warnings": [ {"line": "18", "msg": "Ungewöhnlicher Wert", "fix": "..."} ], "technical_issues": [] }

check_id identifiziert die Prüfung in der Historie und im Webhook-Payload (siehe unten).

Limits & Status-Codes

CodeBedeutung
200Prüfung erfolgreich durchgeführt (kann trotzdem Fehler/Warnungen im Beleg enthalten)
400Ungültige Anfrage (z.B. leerer Inhalt, ungültiges Base64)
401Ungültiger oder fehlender API-Key
413Inhalt überschreitet die maximale Größe
422Beleg konnte nicht als unterstütztes Format erkannt/verarbeitet werden
500Interner Verarbeitungsfehler

Rate-Limit: 60 Anfragen/Minute je API-Key.

Webhooks Max-Tarif

Statt auf die Antwort von /api/v1/check zu warten oder die Historie zu pollen, kann Edivera jedes Prüfergebnis aktiv an ein von dir hinterlegtes System senden. Einrichtung unter Webhooks verwalten. Nur für Prüfungen über die REST-API (nicht für Uploads über die Weboberfläche).

Event-Typen

EventAuslöser
check.completedEine Prüfung über /api/v1/check wurde abgeschlossen (unabhängig davon, ob Fehler gefunden wurden)
pingNur beim manuellen "Test-Webhook senden" - kein echtes Prüfergebnis

Beispiel-Payload

{ "event": "check.completed", "delivery_id": "3f2a9e1c-...-8b7d", "created_at": "2026-07-03T09:15:22Z", "data": { "check_id": 4821, "kind": "edifact", "message_type": "ORDERS", "filename": "bestellung-2026-07.edi", "document_number": "ORD20260703001", "error_count": 2, "warning_count": 1 } }

HTTP-Header

HeaderBedeutung
X-Edivera-EventEvent-Typ (siehe oben)
X-Edivera-Delivery-IdEindeutige ID dieser Zustellung - zur Deduplizierung speichern, falls dieselbe ID erneut ankommt (z.B. nach einem Retry)
X-Edivera-SignatureFormat t=<Unix-Zeitstempel>,v1=<HMAC-SHA256-Hex> - siehe Signaturprüfung unten

Signaturprüfung (Pflicht für den produktiven Einsatz)

Die Signatur wird über "{timestamp}.{raw_body}" mit HMAC-SHA256 und deinem Webhook-Secret berechnet (Secret einmalig beim Anlegen/Rotieren sichtbar, siehe Webhooks verwalten). Immer den rohen, unveränderten Request-Body verwenden (nicht erst parsen und neu serialisieren) und den Zeitstempel gegen ein Toleranzfenster prüfen (empfohlen: 5 Minuten) - das verhindert, dass ein aufgezeichneter, alter Request erneut abgespielt werden kann (Replay-Angriff).

Python

import hmac, hashlib, time def verify_edivera_signature(secret, header_value, raw_body, tolerance=300): parts = dict(p.split("=", 1) for p in header_value.split(",")) timestamp, received_sig = int(parts["t"]), parts["v1"] if abs(time.time() - timestamp) > tolerance: return False # zu alt -> moeglicher Replay signed_payload = f"{timestamp}.{raw_body}" expected_sig = hmac.new(secret.encode(), signed_payload.encode(), hashlib.sha256).hexdigest() return hmac.compare_digest(expected_sig, received_sig) # zeitkonstanter Vergleich

Node.js

const crypto = require("crypto"); function verifyEdiveraSignature(secret, headerValue, rawBody, toleranceSeconds = 300) { const parts = Object.fromEntries(headerValue.split(",").map(p => p.split("="))); const timestamp = parseInt(parts.t, 10); if (Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false; const signedPayload = `${timestamp}.${rawBody}`; const expected = crypto.createHmac("sha256", secret).update(signedPayload).digest("hex"); return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1)); }

Zustellung, Wiederholungsversuche & Sicherheit

AspektVerhalten
Zeitüberschreitung5 Sekunden
Retry-Verhalten4xx: kein Retry (Anfrage aktiv abgelehnt). 5xx/Timeout/Verbindungsfehler: bis zu 3 automatische Wiederholungen nach 5 / 30 / 120 Minuten
Weiterleitungen (3xx)werden nicht automatisch verfolgt (Sicherheitsmaßnahme) - Ziel-URL muss direkt antworten
Ziel-URL-Anforderungausschließlich https://, keine privaten/internen Adressen (localhost, 10.x, 172.16-31.x, 192.168.x, Link-Local/Metadata-Adressen)
Manuelles Nachsendenfehlgeschlagene Zustellungen können jederzeit einzeln erneut ausgelöst werden (siehe Zustellprotokoll unter Webhooks verwalten)
Rate-Limit20 neue Webhooks bzw. Secret-Rotationen pro Stunde, 30 Test-/Nachsende-Aktionen pro Stunde
AufbewahrungZustellprotokolle (inkl. Kopie des gesendeten Payloads) werden nach 90 Tagen automatisch gelöscht
Hinweis: API und Webhooks decken Einzelprüfungen inklusive aktiver Rückmeldung ab. Für SFTP-Ordnerüberwachung gibt es aktuell bewusst keine Lösung (siehe Begründung im Konzept) - bei Bedarf bitte Kontakt aufnehmen.
← Zurück