← Docs / Guides
Getting started
API keys, first calls, the full invoicing cycle, SDKs and webhooks.
Nordlet is an API-first accounting platform for the EU/EEA market, launching with full Lithuanian compliance. Everything the product does — invoicing, general ledger, bank reconciliation, i.SAF — is available over one JSON API.
1. Get an API key
Every request is authenticated with a Bearer API key scoped to one company:
Authorization: Bearer nl_...
For local development, bootstrap a company and key:
pnpm --filter @nordlet/db bootstrap:dev # empty company
pnpm --filter @nordlet/api seed:demo # company with demo data
Interactive API reference (OpenAPI spec at /openapi.json; a local instance serves the same reference at http://localhost:3001/docs).
Postman
Prefer Postman? Import the ready-made collection — every endpoint, grouped by module, with bearer auth pre-wired: Nordlet Postman collection. After importing, set the collection's bearerToken variable to your API key and every request is authenticated.
Sandbox companies
For integration testing, create a company with isSandbox: true (POST /v1/account/companies/create, or tick the sandbox checkbox during onboarding in the app). A sandbox company behaves exactly like a real one — same modules, same API, so you can push realistic transaction volume through it — but it is visibly badged as test data and deleting it purges everything immediately instead of after the 10-day retention window. Run any number of sandbox companies alongside your real one under the same account; the flag is immutable after creation, so real books can never be silently reclassified as test data.
2. First calls
Every operation is POST /v1/{module}/{resource}/{action} with a JSON body. Create a customer:
curl -X POST https://api.nordlet.com/v1/partners/create \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: partner-create-001" \
-d '{"name": "UAB Klientas", "code": "301111222", "vatCode": "LT100001112223"}'
Issue an invoice (amounts are decimal strings, never floats):
curl -X POST https://api.nordlet.com/v1/sales/invoices/create \
-H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
-d '{
"partnerId": "<partner id>",
"lines": [{"description": "Konsultacijos", "quantity": 4, "unitPriceExclVat": "75.0000", "vatClassifierCode": "PVM1"}]
}'
curl -X POST https://api.nordlet.com/v1/sales/invoices/issue \
-H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
-d '{"id": "<invoice id>", "issueDate": "2026-07-09"}'
Issuing allocates a gapless number (SF-1), checks the accounting period is open, and posts the balanced journal entry (D 2410 receivable / C 5001 revenue / C 4492 VAT) in the same transaction.
3. The full cycle
| Step | Call |
|---|---|
| Register a supplier bill | purchases/invoices/create → purchases/invoices/register |
| Import a bank statement | bank/statements/import (camt.053 XML) or bank/transactions/import (JSON) |
| Get match suggestions | bank/transactions/suggest-matches |
| Reconcile a payment | bank/transactions/match — posts the payment and updates paymentStatus |
| Pay suppliers | bank/payments/export — pain.001 SEPA file for your bank |
| Monthly VAT registers | declarations/lt/isaf/generate — i.SAF 1.2 XML for VMI |
| VAT return figures | declarations/lt/fr0600/compute — FR0600 fields reconciled against the registers |
| Ship goods with a waybill | transport/waybills/create → issue, then declarations/lt/ivaz/generate — i.VAZ XML for VMI |
4. TypeScript SDK
import { createNordletClient, idempotent } from '@nordlet/sdk'
const client = createNordletClient({
baseUrl: 'https://api.nordlet.com',
apiKey: process.env.NORDLET_API_KEY!,
})
const { data, error } = await client.POST('/v1/sales/invoices/create', {
body: {
partnerId,
lines: [{ description: 'Konsultacijos', quantity: 4, unitPriceExclVat: '75.0000' }],
},
...idempotent(`order-${orderId}`),
})
The SDK is generated from the live OpenAPI spec (pnpm --filter @nordlet/sdk generate), so every request and response is fully typed.
5. Webhooks
Subscribe to events instead of polling:
curl -X POST https://api.nordlet.com/v1/webhooks/subscriptions/create \
-H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
-d '{"url": "https://example.com/hooks/hyperion", "events": ["sale_invoice.issued", "sale_invoice.paid"]}'
Deliveries carry an HMAC signature (x-nordlet-signature: sha256=<hex> of the raw body with your subscription secret) and are retried with exponential backoff.
Current events: sale_invoice.issued, sale_invoice.paid, purchase_invoice.registered, purchase_invoice.paid.
See API conventions for list queries, error envelopes, idempotency semantics, and rate limits.