Nordlet

← Dokumentation / Leitfäden

API-Konventionen

Request-Struktur, Berechtigungen (Scopes), Listenabfragen, Geldbeträge, Fehler, Idempotenz, Rate Limits.

Aufbau der Requests

Jede Operation ist ein POST-Request im RPC-Stil:

POST /v1/{module}/{resource}/{action}

Module: reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. Aktionen (Actions) sind Verben: create, get, update, delete, list, sowie domänenspezifische Aktionen wie issue, register, match, apply-advance, generate.

Authentifizierung und Berechtigungen (Scopes)

Authorization: Bearer <api key>. Schlüssel verfügen über Berechtigungen (Scopes), die bei jeder Aktion geprüft werden:

  • {module}:read — Lese- und Listenabfragen (get/list)
  • {module}:write — Mutationen
  • {module}:* oder * — Platzhalter (Wildcards)

Fehlender Scope → 403 forbidden. Fehlender oder ungültiger Schlüssel → 401 unauthorized.

Listenabfragen

Alle list-Aktionen basieren auf einem einheitlichen Schema:

{
  "page": 1,
  "pageSize": 50,
  "sort": [{ "field": "createdAt", "dir": "desc" }],
  "filter": [{ "field": "paymentStatus", "op": "eq", "value": "unpaid" }]
}

Filteroperatoren: eq, neq, gt, gte, lt, lte, like, in. Sortier- und filterbare Felder sind pro Endpunkt über eine Whitelist definiert (siehe OpenAPI-Spezifikation); unbekannte Felder liefern einen Fehler 400. Antworten (Responses): { rows, total, page, pageSize }.

Geldbeträge und Datumsangaben

Geldbeträge werden als Dezimal-Strings mit bis zu 4 Nachkommastellen abgebildet ("121.0000") – niemals als Fließkommazahlen (Floats). Die Umsatzsteuer (VAT) wird pro Zeile berechnet und kaufmännisch gerundet (Half-Up Rounding). Datumsangaben folgen dem Format YYYY-MM-DD; Zeitstempel entsprechen ISO 8601 in UTC.

Fehler

Einheitliche Struktur (Envelope) für alle Fehler:

{
  "error": {
    "code": "validation",
    "message": "Request validation failed",
    "requestId": "k1x…",
    "fieldErrors": { "lines.0.unitPriceExclVat": ["Invalid value"] }
  }
}

Codes: validation (400/422), unauthorized (401), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). Bitte geben Sie bei der Meldung von Problemen immer die requestId an.

Idempotenz

Fügen Sie den HTTP-Header Idempotency-Key: <any string ≤255 chars> zu jedem mutierenden Aufruf hinzu:

  • Ein erneuter Versuch (Retry) mit demselben Schlüssel und Payload → die gespeicherte Antwort (Response) wird Byte für Byte wiederholt, versehen mit x-idempotent-replay: true.
  • Derselbe Schlüssel, aber unterschiedlicher Payload → 422 idempotency_key_reuse.
  • Ein gleichzeitiges Duplikat, während der erste Request noch verarbeitet wird → 409 idempotency_in_progress.
  • Schlüssel verfallen nach 24 Stunden. Fehlerantworten (4xx) werden ebenfalls wiederholt; 5xx-Antworten werden nicht gespeichert, sodass erneute Versuche die Ausführung neu anstoßen.

Rate Limits

300 Requests/Minute pro API-Schlüssel (pro angegebenem Anmeldedatensatz; nicht authentifizierte Anfragen werden pro IP limitiert). Bei einem Fehler 429 beachten Sie bitte den Header retry-after. Die x-ratelimit-*-Header geben Auskunft über Ihr verbleibendes Budget.

Webhooks

Ereignisse (Events) werden im Rahmen derselben Datenbanktransaktion wie die zugehörige Änderung in eine transaktionale Outbox geschrieben – ein zurückgerolltes (rolled-back) Dokument löst niemals ein Event aus, und kein Event geht verloren. Zustellung:

  • POST an Ihre URL mit dem Event-JSON
  • x-nordlet-signature: sha256=<hex HMAC-SHA256 of the raw body> unter Verwendung Ihres Subscription-Secrets
  • Erneute Zustellversuche (Retries) mit exponentiellem Backoff bei Nicht-2xx-Antworten

Verifizieren Sie Signaturen mittels zeitlich konstantem Vergleich (Constant-Time Comparison), bevor Sie dem Payload vertrauen.

Audit

Jede Mutation wird protokolliert (actor, action, entity, diff) und kann über audit/list abgefragt werden.

Buchhalterische Garantien

  • Journalbuchungen sind stets ausgeglichen (Soll-Haben-Gleichheit) – sichergestellt durch einen verzögerten (deferred) Datenbank-Trigger beim Commit und nicht nur durch die Anwendungsschicht.
  • Belegnummern sind pro Nummernkreis und Jahr lückenlos; die Zuweisung ist nebenläufigkeitssicher (concurrency-safe).
  • Geschlossene Buchungsperioden weisen jede Buchung ab, deren Datum in diesen Zeitraum fällt (409).
  • Soft-gelöschte Dokumente behalten ihren Prüfpfad (Audit Trail); ausgestellte oder registrierte Dokumente können nicht gelöscht werden.