← Dokumentation / Guides
API-konventioner
Forespørgselsstruktur, godkendelsesscopes, listeforespørgsler, beløb, fejl, idempotens, hastighedsgrænser.
Forespørgselsstruktur
Enhver handling er et RPC-lignende POST-kald:
POST /v1/{module}/{resource}/{action}
Moduler: reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. Handlinger er verber: create, get, update, delete, list samt domænespecifikke handlinger som issue, register, match, apply-advance, generate.
Godkendelse og scopes
Authorization: Bearer <api key>. Nøgler indeholder scopes, der kontrolleres pr. handling:
{module}:read- hent- og listeforespørgsler{module}:write- ændringer{module}:*eller*- wildcards
Manglende scope giver 403 forbidden. Manglende eller ugyldig nøgle giver 401 unauthorized.
Listeforespørgsler
Alle list-handlinger deler den samme kontrakt:
{
"page": 1,
"pageSize": 50,
"sort": [{ "field": "createdAt", "dir": "desc" }],
"filter": [{ "field": "paymentStatus", "op": "eq", "value": "unpaid" }]
}
Filteroperatorer: eq (lig med), ne (ikke lig med), contains (tekstsøgning, der ikke skelner mellem store og små bogstaver, kun for tekstfelter), gte (større end eller lig med), lte (mindre end eller lig med), in (enhver værdi fra en liste med op til 500 værdier). Felter, der kan sorteres og filtreres efter, er whiteliste-godkendte pr. endpoint (se OpenAPI-specifikationen); ukendte felter returnerer 400. Tilføj totals: ["field", …] til forespørgslen for at summere numeriske felter på tværs af alle matchende rækker; når posteringerne har en tilknyttet valuta, giver totalsByCurrency de samme summer fordelt pr. valutakode. Svar: { rows, total, page, pageSize, totals?, totalsByCurrency? }.
Beløb og datoer
Pengebeløb er decimaltal som strenge med op til 4 decimaler ("121.0000"), aldrig flydende kommatal. Moms beregnes pr. linje med afrunding væk fra nul ved halve værdier (half-up rounding). Datoer er i formatet YYYY-MM-DD; tidsstempler er ISO 8601 UTC.
Fejl
Samme envelope alle steder:
{
"error": {
"code": "validation",
"message": "Request validation failed",
"requestId": "k1x…",
"key": "request_invalid",
"fieldErrors": { "lines.0.unitPriceExclVat": ["Invalid value"] }
}
}
Koder: validation (400/422 samt 413, når en uploadet fil eller forespørgselskrop er for stor), unauthorized (401), payment_required (402, prøveperioden eller forudbetalte kreditter er udløbet; meddelelsen forklarer, hvordan du fortsætter), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). Når meddelelsen er en af de faste standardmeddelelser, angiver key denne, så en klient kan vise sin egen oversættelse, og params indeholder de værdier, der indsættes (f.eks. { "period": "2026-09" } for en låst regnskabsperiode). Inkluder altid requestId, når du indberetter fejl.
Idempotens
Tilføj Idempotency-Key: <enhver streng på maks. 255 tegn> til alle kald, der ændrer data:
- Gentag med samme nøgle og payload -> det gemte svar afspilles byte for byte med
x-idempotent-replay: true. - Samme nøgle, anden payload -> 422
idempotency_key_reuse. - Samtidig dublet, mens det første kald er i gang -> 409
idempotency_in_progress. - Nøgler knytter sig til den API-nøgle eller bruger, der sender dem, inden for den virksomhed, som kaldet udføres for, så to integrationer i samme virksomhed kan bruge den samme nøgle. Kald, der foretages, før en virksomhed eksisterer, samt
account/*-kald, bevarer nøgler pr. bruger, så et gentagetaccount/companies/create-kald kun opretter én virksomhed. - Et gemt svar returneres først, når afsenderen igen består de samme rettighedskontrol (scope, rolle, virksomhed og betalingsstatus); ellers modtager kaldet den aktuelle fejl.
- Nøgler udløber efter 24 timer. Fejlsvar (4xx) afspilles også; 5xx-svar gemmes ikke, så gentagne forsøg udføres på ny.
Hastighedsgrænser (Rate limits)
300 forespørgsler/minut pr. API-nøgle (pr. angivet legitimationsoplysning; uauthentificerede forespørgsler begrænses pr. IP-adresse). Ved 429 skal du overholde retry-after-headeren. x-ratelimit-*-headere viser din aktuelle kvote.
Webhooks
Hændelser gemmes i en transaktionel udgående kø (outbox) i samme databasetransaktion som ændringen - et dokument fra en rullet-tilbage-transaktion udløser aldrig en hændelse, og ingen hændelser går tabt. Levering:
POSTtil din URL med hændelsens JSON-datax-nordlet-timestamp: <unix-sekunder>, det tidspunkt hvor leveringen blev signeretx-nordlet-signature-v2: t=<timestamp>,v1=<hex HMAC-SHA256 af "<timestamp>.<raw body>">ved brug af dit abonnementshemmelighed (subscription secret)x-nordlet-signature: sha256=<hex HMAC-SHA256 af rå indhold>, bevaret uændret for eksisterende modtagerex-nordlet-deliveryindeholder leverings-id'et, som er det samme ved hvert gentaget forsøg på en levering- Et svar, der ikke er 2xx, eller en omdirigering forsøges igen efter 30 sekunder, 2 minutter, 10 minutter, 30 minutter, 1 time, 3 timer, 6 timer og 12 timer, i alt ca. 24 timer, før leveringen markeres som fejslet
- Hver levering sendes af én server ad gangen, så kørsel af flere API-instanser sender den ikke to gange
Verificér x-nordlet-signature-v2 med en konstant-tids-sammenligning (constant-time comparison), før du stoler på payloaden, og afvis leveringer, hvis tidsstempel afviger mere end 5 minutter fra dit systems ur. Tidsstemplet er en del af den signerede tekst, så en opsnappet levering kan ikke afspilles igen senere med et nyt tidsstempel. Gem de x-nordlet-delivery-id'er, du allerede har behandlet, for at ignorere dubletter inden for det tidsvindue. En fejlet levering kan sendes igen via webhooks/deliveries/redeliver.
Audit
Enhver ændring registreres (actor, action, entity, diff) og kan forespørges via audit/list.
Regnskabsgarantier
- Bogføringsposter er altid i balance - dette håndhæves af en udskudt databasetrigger ved commit-tidspunktet, ikke kun i applikationskoden.
- Dokumentnumre har ingen huller i nummerserien pr. serie/år; tildelingen er konkurrencedygtig og sikker (concurrency-safe).
- Låste regnskabsperioder afviser alle posteringer med datoer inden for perioden (409).
- Blødt slettede (soft-deleted) dokumenter beholder deres audit-log; udstedte eller registrerede dokumenter kan ikke slettes.