Nordlet

← Základy / Sady SDK

Konvence API

Struktura požadavků, oprávnění, seznamové dotazy, peněžní částky, chyby, idempotence, limity počtu požadavků.

Struktura požadavků

Každá operace má podobu RPC požadavku typu POST:

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

Moduly: reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. Akce jsou slovesa: create, get, update, delete, list a dále doménové akce jako issue, register, match, apply-advance, generate.

Autentizace a oprávnění

Authorization: Bearer <api key>. Klíče obsahují oprávnění (scopes) kontrolovaná pro každou akce:

  • {module}:read - akce pro zobrazení a výpis
  • {module}:write - modifikace
  • {module}:* nebo * - zástupné znaky (wildcards)

Chybějící oprávnění vede na 403 forbidden. Chybějící nebo neplatný klíč vede na 401 unauthorized.

Seznamové dotazy

Všechny akce typu list sdílejí jednotný kontrakt:

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

Operátory filtru: eq (rovno), ne (nerovno), contains (vyhledávání textu bez ohledu na velikost písmen, pouze pro textová pole), gte (větší nebo rovno), lte (menší nebo rovno), in (libovolná hodnota ze seznamu až 500 hodnot). Pole, podle kterých lze řadit a filtrovat, jsou předem definována na jednotlivých koncových bodech (viz specifikace OpenAPI); neznámá pole vrací kód 400. Přidáním totals: ["field", …] do požadavku vyžádáte součet číselných polí přes všechny odpovídající řádky; pokud záznamy obsahují měnu, pole totalsByCurrency poskytne stejné součty rozdělené podle kódu měny. Odpovědi: { rows, total, page, pageSize, totals?, totalsByCurrency? }.

Peněžní částki a data

Peněžní hodnoty jsou desítkové řetězce s až 4 desetinnými místy ("121.0000") - nikdy se nepoužívají desetinná čísla s plovoucí řádkovou čárkou (floats). DPH se počítá na úrovni jednotlivých řádků za použití zaokrouhlení nahoru při polovině. Data jsou ve formátu YYYY-MM-DD; časová razítka odpovídají normě ISO 8601 v UTC.

Chyby

Jednotná obálka pro všechny chybové stavy:

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

Kódy: validation (400/422 a 413, pokud je nahrávaný soubor nebo tělo požadavku příliš velké), unauthorized (401), payment_required (402, zkušební období nebo předplacený kredit vypršel; zpráva obsahuje pokyny k dalšímu postupu), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). Pokud zpráva odpovídá jedné z pevných chybových hlášek, klíč key ji identifikuje, aby si klient mohl zobrazit vlastní překlad, a pole params obsahuje hodnoty, které se do ní dosadí (například { "period": "2026-09" } pro uzamčené účetní období). Při hlášení problémů vždy uveďte requestId.

Idempotence

Do jakéhokoli modifikačního volání přidejte hlavičku Idempotency-Key: <libovolný řetězec ≤255 znaků>:

  • Opakované volání se stejným klíčem a obsahem - uložená odpověď se přehraje přesně po bytech s hlavičkou x-idempotent-replay: true.
  • Stejný klíč, jiný obsah - vrátí se 422 idempotency_key_reuse.
  • Souběžný duplicitní požadavek, zatímco první ještě probíhá - vrátí se 409 idempotency_in_progress.
  • Klíče náleží API klíči nebo uživateli, který je odesílá, v rámci firmy, pro kterou je volání prováděno, takže dvě integrace jedné firmy mohou používat stejný klíč. Volání provedená před vznikem firmy a volání pod account/* drží klíče na úrovni uživatele, takže opakované volání account/companies/create vytvoří právě jednu firmu.
  • Uložená odpověď se vrátí až poté, co volající opětovně projde kontrolou oprávnění (scope, role, firma a stav fakturace); v opačném případě požadavek obdrží aktuální chybu.
  • Platnost klíčů vyprší po 24 hodinách. Chybové odpovědi (4xx) se přehrávají také; odpovědi 5xx se neukládají, takže opakované pokusy požadavek zopakují.

Limity počtu požadavků (Rate limits)

300 požadavků za minutu na jeden API klíč (podle předložených přihlašovacích údajů; neautentizované požadavky jsou limitovány podle IP adresy). Při chybě 429 respektujte hlavičku retry-after. Váš aktuální stav čerpání hlásí hlavičky x-ratelimit-*.

Webhooky

Události se zapisují do transakční odchozí fronty (outbox) v rámci stejné databázové transakce jako prováděná změna - vrácená (rolled-back) transakce nikdy nevyvolá událost a žádná událost se neztratí. Doručování:

  • POST požadavek na vaši URL adresu obsahující JSON události
  • x-nordlet-timestamp: <unix seconds>, čas, kdy byl podpis vytvořen
  • x-nordlet-signature-v2: t=<timestamp>,v1=<hexadecimální HMAC-SHA256 z řetězce "<timestamp>.<raw body>"> vypočtený pomocí vašeho tajného klíče předplatného
  • x-nordlet-signature: sha256=<hexadecimální HMAC-SHA256 z nezpracovaného těla>, zachováno bez změn pro stávající příjemce
  • x-nordlet-delivery obsahuje ID doručení, které zůstává stejné při každém opakovaném pokusu o doručení
  • Odpověď jiná než 2xx nebo přesměrování se opakuje po 30 sekundách, 2 minutách, 10 minutách, 30 minutách, 1 hodině, 3 hodinách, 6 hodinách a 12 hodinách (celkově přibližně 24 hodin), než je doručení označeno jako selhané
  • Každé doručení odesílá vždy pouze jeden server, takže provozování více instancí API nezpůsobí duplicitní odeslání

Před zpracováním obsahu ověřte x-nordlet-signature-v2 porovnáním v konstantním čase a odmítněte doručení, jehož časové razítko se liší od vašich hodin o více než 5 minut. Časové razítko je součástí podepsaného textu, takže zachycené doručení nelze později přehrát s novým časovým razítkem. Ukládejte si zpracovaná ID x-nordlet-delivery, abyste mohli ignorovat případné duplicity v daném časovém okně. Neúspěšné doručení lze znovu odeslat pomocí webhooks/deliveries/redeliver.

Audit

Každá modifikace se zaznamenává (actor, action, entity, diff) a lze ji vyhledávat prostřednictvím audit/list.

Účetní garance

  • Účetní zápisy jsou vždy vyrovnané - vynuceno opožděným databázovým triggrem při potvrzení transakce (commit), nikoli pouze aplikačním kódem.
  • Čísla dokladů jsou řadově souvislá bez mezer v rámci číselné řady a roku; alokace je bezpečná pro souběžný přístup (concurrency-safe).
  • Uzamčená účetní období odmítnou jakýkoliv účetní zápis s datem uvnitř tohoto období (409).
  • Měkce smazané (soft-deleted) doklady si zachovávají auditní stopu; vystavené nebo zaevidované doklady nelze smazat.