Nordlet

← Podstawy / Pakiety SDK

Konwencje API

Struktura żądań, zakresy uprawnień, zapytania listujące, kwoty, błędy, idempotencja, limity zapytań.

Struktura żądań

Każda operacja ma postać wywołania POST w stylu RPC:

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

Moduły: reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. Akcje to czasowniki: create, get, update, delete, list, a także akcje dziedzinowe, takie jak issue, register, match, apply-advance, generate.

Uwierzytelnianie i zakresy uprawnień

Authorization: Bearer <api key>. Klucze posiadają zakresy uprawnień (scopes) sprawdzane dla każdej akcji:

  • {module}:read - akcje pobierania i listowania
  • {module}:write - modyfikacje danych
  • {module}:* lub * - symbole wieloznaczne (wildcards)

Brak zakresu uprawnień oznacza błąd 403 forbidden. Brak lub nieprawidłowy klucz oznacza błąd 401 unauthorized.

Zapytania listujące

Wszystkie akcje list opierają się na jednym kontrakcie:

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

Operatory filtrów: eq (równa się), ne (nie równa się), contains (dopasowanie tekstu bez uwzględniania wielkości liter, tylko dla pól tekstowych), gte (większe lub równe), lte (mniejsze lub równe), in (dowolna wartość z listy zawierającej do 500 elementów). Pola, po których można sortować i filtrować, są zdefiniowane na białej liście dla każdego punktu końcowego (zobacz specyfikację OpenAPI); nieznane pola powodują zwrócenie błędu 400. Dodaj totals: ["field", …] do żądania, aby zsumować pola numeryczne dla wszystkich pasujących wierszy; jeśli rekordy zawierają walutę, pole totalsByCurrency zwraca te same sumy w rozbiciu na kody walut. Odpowiedzi: { rows, total, page, pageSize, totals?, totalsByCurrency? }.

Kwoty pieniężne i daty

Wartości pieniężne są ciągami znaków reprezentującymi liczby dziesiętne z maksymalnie 4 miejscami po przecinku ("121.0000") - nigdy zmiennoprzecinkowymi. Podatek VAT jest obliczany dla każdej pozycji z zaokrągleniem w górę, jeśli końcówka wynosi co najmniej 0,5 (half-up). Daty mają format YYYY-MM-DD; znaczniki czasu (timestamps) używają formatu ISO 8601 UTC.

Błędy

Jednolita koperta błędów dla wszystkich odpowiedzi:

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

Kody błędów: validation (400/422 oraz 413, gdy przesyłany plik lub treść żądania są zbyt duże), unauthorized (401), payment_required (402, okres próbny lub środki przedpłacone dobiegły końca; komunikat zawiera informacje o sposobie kontynuacji), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). Gdy komunikat jest jednym ze stałych komunikatów, pole key identyfikuje go, aby klient mógł wyświetlić własne tłumaczenie, a pole params zawiera wartości wstawiane do komunikatu (na przykład { "period": "2026-09" } dla zablokowanego okresu rozliczeniowego). Dołączaj identyfikator requestId podczas zgłaszania problemów.

Idempotencja

Dodaj nagłówek Idempotency-Key: <dowolny ciąg znaków o długości do 255 znaków> do każdego wywołania modyfikującego dane:

  • Ponowne wywołanie z tym samym kluczem i ładunkiem danych powoduje odtworzenie zapisanego żądania bajt po bajcie wraz z nagłówkiem x-idempotent-replay: true.
  • Ten sam klucz, ale inny ładunek danych - błąd 422 idempotency_key_reuse.
  • Równoczesne zduplikowane żądanie, gdy pierwsze jest w trakcie przetwarzania - błąd 409 idempotency_in_progress.
  • Klucze należą do klucza API lub użytkownika, który je wysyła, w ramach firmy, w imieniu której wykonywane jest wywołanie, dzięki czemu dwie integracje jednej firmy mogą używać tego samego klucza. Wywołania wykonane przed utworzeniem firmy oraz wywołania account/* przypisują klucze do użytkowników, co sprawia, że wielokrotne wywołanie account/companies/create utworzy tylko jedną firmę.
  • Zapisana odpowiedź jest zwracana tylko wtedy, gdy wywołujący ponownie przejde pomyślnie weryfikację uprawnień (zakres, rola, firma i status rozliczeniowy); w przeciwnym razie wywołanie otrzyma bieżący błąd.
  • Klucze wygasają po 24 godzinach. Odpowiedzi zawierające błędy (4xx) również są odtwarzane; odpowiedzi 5xx nie są zapisywane, dzięki czemu ponowne próby powodują ponowne wykonanie operacji.

Limity zapytań (Rate limits)

300 żądań na minutę dla jednego klucza API (w przeliczeniu na podane poświadczenia; żądania bez uwierzytelniania są limitowane według adresu IP). W przypadku błędu 429 należy uwzględnić nagłówek retry-after. Nagłówki x-ratelimit-* informują o dostępnym budecie zapytań.

Webhooki

Wydarzenia są zapisywane w transakcyjnej tabeli wyjściowej (outbox) w ramach tej samej transakcji bazy danych co modyfikacja - wycofany dokument nigdy nie wygeneruje wydarzenia, a żadne wydarzenie nie zostanie utracone. Dostarczanie:

  • Żądanie POST wysłane pod wskazany adres URL z treścią wydarzenia w formacie JSON
  • x-nordlet-timestamp: <sekundy unixowe> - czas podpisania doręczenia
  • x-nordlet-signature-v2: t=<timestamp>,v1=<szesnastkowy HMAC-SHA256 z ciągu „<timestamp>.<raw body>”> przy użyciu sekretu subskrypcji
  • x-nordlet-signature: sha256=<szesnastkowy HMAC-SHA256 z surowego ciała żądania>, zachowany bez zmian dla istniejących odbiorców
  • x-nordlet-delivery zawiera identyfikador doręczenia, taki sam przy każdej ponownej próbie tego samego doręczenia
  • Odpowiedź inna niż z zakresu 2xx lub przekierowanie skutkuje ponowną próbą po 30 sekundach, 2 minutach, 10 minutach, 30 minutach, 1 godzinie, 3 godzinach, 6 godzinach i 12 godzinach, czyli łącznie po około 24 godzinach, zanim doręczenie zostanie oznaczone jako nieudane
  • Każde doręczenie jest wysyłane przez jeden serwer naraz, więc uruchomienie wielu instancji API nie spowoduje podwójnego wysłania

Zweryfikuj nagłówek x-nordlet-signature-v2 za pomocą porównania w stałym czasie przed zaufaniem ładunkowi danych i odrzuć doręczenie, którego znacznik czasu różni się od zegara systemu o więcej niż 5 minut. Znacznik czasu jest częścią podpisanego tekstu, dzięki czemu przechwycone doręczenie nie może zostać ponowione później ze świeżym znacznikiem czasu. Zapisuj przetworzone identyfikatory x-nordlet-delivery, aby ignorować powtórzenia w tym oknie czasowym. Nieudane doręczenie można wysłać ponownie za pomocą punktu końcowego webhooks/deliveries/redeliver.

Audyt

Każda modyfikacja jest rejestrowana (zawiera pola actor, action, entity, diff) i można ją wyszukiwać za pomocą audit/list.

Gwarancje księgowe

  • Zapisy na kontach księgowych muszą się bilansować - egzekwowane przez odroczony wyzwalacz bazy danych w momencie zatwierdzenia transakcji (commit), a nie tylko przez kod aplikacji.
  • Numery dokumentów są ciągłe w ramach serii lub roku; przydzielanie numerów jest bezpieczne pod względem współbieżności.
  • Zablokowane okresy rozliczeniowe odrzucają wszelkie zapisy z datą przypadającą w ich obrębie (409).
  • Dokumenty usunięte logicznie (soft-deleted) zachowują ścieżkę audytu; dokumenty zatwierdzone lub zarejestrowane nie mogą zostać usunięte.