Nordlet

← Dokumentation / Guider

API-konventioner

Anropsstruktur, behörighetsomfång, listfrågor, belopp, felhantering, idempotens och frekvensbegränsningar.

Anropsstruktur

Varje åtgärd är ett RPC-liknande POST-anrop:

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

Moduler: reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. Åtgärder är verb: create, get, update, delete, list, samt domänspecifika åtgärder som issue, register, match, apply-advance, generate.

Autentisering och behörighetsomfång (scopes)

Authorization: Bearer <api key>. Nycklar har behörighetsomfång som kontrolleras per åtgärd:

  • {module}:read - läs- och listningsåtgärder
  • {module}:write - ändringsåtgärder
  • {module}:* eller * - jokertecken

Saknat behörighetsomfång ger 403 forbidden. Saknad eller ogiltig nyckel ger 401 unauthorized.

Listfrågor

Alla list-åtgärder följer samma avtalsstruktur:

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

Filtreringsoperatorer: eq (lika med), ne (inte lika med), contains (skiftlägesokänslig textsökning, enbart textfält), gte (större än eller lika med), lte (mindre än eller lika med), in (vilket som helst av upp till 500 värden i en lista). Sök- och filtreringsbara fält är vitlistade per endpoint (se OpenAPI-specifikationen), och okända fält ger felkod 400. Lägg till totals: ["field", …] i anropet för att summera numeriska fält över alla matchande rader. När posterna har en valuta ger totalsByCurrency samma summor uppdelade per valutakod. Svarsformat: { rows, total, page, pageSize, totals?, totalsByCurrency? }.

Belopp och datum

Monetära värden anges som decimalsträngar med upp till 4 decimaler ("121.0000") och får aldrig hanteras som flyttal. Moms beräknas per rad med avrundning till närmaste heltal uppåt vid .5 (half-up). Datum anges i formatet YYYY-MM-DD, och tidsstämplar följer ISO 8601 i UTC.

Felhantering

Samma omslutande struktur används överallt:

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

Felkoder: validation (400/422, samt 413 om en uppladdad fil eller anropskropp är för stor), unauthorized (401), payment_required (402, provperioden eller det förbetalda saldot har löpt ut, meddelandet beskriver hur du går vidare), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). När meddelandet är ett fördefinierat standardmeddelande anger key meddelandets namn så att klienten kan visa sin egen översättning, och params innehåller de tillhörande värdena (till exempel { "period": "2026-09" } för en låst redovisningsperiod). Inkludera alltid requestId vid felrapportering.

Idempotens

Lägg till Idempotency-Key: <valfri sträng på max 255 tecken> för alla ändringsanrop:

  • Vid upprepade anrop med samma nyckel och payload spelas det lagrade svaret upp byte för byte med headern x-idempotent-replay: true.
  • Samma nyckel men med annan payload ger 422 idempotency_key_reuse.
  • Samtidiga dubbletter medan det första anropet bearbetas ger 409 idempotency_in_progress.
  • Nycklar är knutna till den API-nyckel eller användare som skickar dem inom det företag som anropet avser, vilket gör att två integrationer för samma företag kan använda samma nyckel. Anrop som görs innan ett företag existerar samt account/*-anrop sparar nycklar per användare, vilket innebär att upprepade anrop till account/companies/create endast skapar ett företag.
  • Ett lagrat svar returneras enbart efter att anroparen har klarat samma behörighetskontroller igen (behörighetsomfång, roll, företag och betalningsstatus). I annat fall returneras det aktuella felet.
  • Nycklar upphör att gälla efter 24 timmar. Även felsvar (4xx) spelas upp igen, medan 5xx-svar inte lagras så att nya försök kan utföras.

Frekvensbegränsningar (rate limits)

300 anrop per minut och API-nyckel (per angiven autentiseringsuppgift, ej autentiserade anrop begränsas per IP-adress). Vid statuskod 429 ska retry-after-headern respekteras. Headrarna x-ratelimit-* visar din aktuella kvot.

Webhooks

Händelser skrivs till en transaktionell utgående kö i samma databastransaktion som ändringen. Ett avbrutet dokument genererar aldrig någon händelse, och inga händelser går förlorade. Leverans:

  • POST till din URL med händelsens JSON-data
  • x-nordlet-timestamp: <unix-sekunder>, tidpunkten då leveransen signerades
  • x-nordlet-signature-v2: t=<timestamp>,v1=<hex-kodad HMAC-SHA256 av "<timestamp>.<raw body>"> med din prenumerationshemlighet
  • x-nordlet-signature: sha256=<hex-kodad HMAC-SHA256 av rådata>, bibehållen oförändrad för befintliga mottagare
  • x-nordlet-delivery innehåller leverans-id, vilket är samma för varje nytt försök av en specifik leverans
  • Ett svar som inte är 2xx eller en omdirigering gör att ett nytt försök görs efter 30 sekunder, 2 minuter, 10 minuter, 30 minuter, 1 timme, 3 timmar, 6 timmar och 12 timmar (totalt cirka 24 timmar) innan leveransen markeras som misslyckad
  • Varje leverans skickas av en server i taget, vilket gör att körning av flera API-instanser inte leder till dubbla utskick

Verifiera x-nordlet-signature-v2 med en konstanttidsjämförelse innan du litar på payloaden, och avvisa leveranser vars tidsstämpel avviker mer än 5 minuter från din klocka. Tidsstämpeln är en del av den signerade texten, vilket gör att en fångad leverans inte kan spelas upp vid ett senare tillfälle med en ny tidsstämpel. Spara de x-nordlet-delivery-id som du har bearbetat för att kunna ignorera upprepningar inom det tidsfönstret. Misslyckade leveranser kan skickas igen via webhooks/deliveries/redeliver.

Granskningslogg (audit)

Varje ändring loggas (actor, action, entity, diff) och kan sökas igenom via audit/list.

Redovisningsgarantier

  • Verifikatbokföringen är alltid balanserad - detta säkerställs av en uppskjuten databastrigg vid commit-tillfället, inte enbart av applikationskoden.
  • Verifikationsserier är lückenlösa per serie och år, och numrering sker på ett koherenssäkert sätt.
  • Låsta redovisningsperioder avvisar alla bokföringsdatum som infaller inom perioden (409).
  • Mjukt raderade dokument behåller sin spårbarhet i granskningsloggen, och bokförda eller registrerade dokument kan inte raderas.