@waltermedia/fortnox-client
v0.15.0
Published
TypeScript client for the Fortnox API with rate limiting, OAuth token management, and security hardening
Downloads
487
Maintainers
Readme
@waltermedia/fortnox-client
A TypeScript client for the Fortnox API — Sweden's leading cloud-based accounting platform. Built for reliability with built-in rate limiting, OAuth token refresh, input validation, and security hardening.
Features
- Rate limiting — Respects Fortnox API limits (1 concurrent request, 250ms minimum between requests)
- OAuth token management —
TokenManagerhandles refresh flows automatically - Full TypeScript support — Typed requests, responses, and parameters
- Security — Path injection prevention, sanitized error logging, no credential leakage
- Read-only operations — Vouchers, accounts, invoices, company info, SIE export
Installation
npm install @waltermedia/fortnox-clientOr with Yarn or pnpm:
yarn add @waltermedia/fortnox-client
pnpm add @waltermedia/fortnox-clientQuick Start
You need an OAuth access token from Fortnox. Obtain one via the Fortnox OAuth flow.
import { FortnoxClient } from '@waltermedia/fortnox-client';
const client = new FortnoxClient({
accessToken: 'your-access-token',
});
// Fetch vouchers
const vouchers = await client.getVouchers({
fromDate: '2023-01-01',
toDate: '2023-12-31',
limit: 100,
page: 1,
});
console.log(vouchers.Vouchers);
console.log(vouchers.MetaInformation['@TotalPages']);Usage
Vouchers
// List vouchers with filters
const vouchers = await client.getVouchers({
fromDate: '2023-01-01',
toDate: '2023-12-31',
financialYear: 7,
limit: 100,
page: 1,
});
// Get a single voucher by series and number
const voucher = await client.getVoucherDetails({
voucherSeries: 'A',
voucherNumber: 1,
financialYear: 7,
});Accounts
// List accounts
const accounts = await client.getAccounts({
limit: 100,
offset: 0,
financialYear: 7,
});
// Get account details
const account = await client.getAccountDetails({
accountNumber: 1920,
financialYear: 7,
});Invoices
const invoices = await client.getInvoices({
limit: 100,
filter: 'unpaid',
financialYear: 7,
});
const supplierInvoices = await client.getSupplierInvoices({
limit: 100,
filter: 'unpaid',
});Other
const companyInfo = await client.getCompanyInformation();
const financialYears = await client.getFinancialYears({ date: '2023-06-01' });
const sieExport = await client.getSIE({ type: '4', financialYear: 7 });Pagination
Collection responses include MetaInformation with pagination metadata:
interface MetaInformation {
'@TotalPages': number;
'@CurrentPage': number;
'@TotalResources': number;
}Example: fetch all vouchers across pages:
async function fetchAllVouchers() {
let currentPage = 1;
const results = [];
let hasMorePages = true;
while (hasMorePages) {
const response = await client.getVouchers({
fromDate: '2023-01-01',
toDate: '2023-12-31',
limit: 100,
page: currentPage,
});
results.push(...response.Vouchers);
hasMorePages = currentPage < response.MetaInformation['@TotalPages'];
currentPage++;
}
return results;
}Error Handling
API errors are wrapped in FortnoxError. Import it to check error type and access status/code:
import { FortnoxClient, FortnoxError } from '@waltermedia/fortnox-client';
try {
const vouchers = await client.getVouchers({ fromDate: '2023-01-01', toDate: '2023-12-31' });
} catch (error) {
if (error instanceof FortnoxError) {
console.error('Fortnox API Error:', error.message);
console.error('Status:', error.statusCode);
console.error('Code:', error.code);
// error.response contains sanitized status/data (no auth headers)
} else {
throw error;
}
}Token Management
Use TokenManager to handle OAuth token refresh:
import { TokenManager } from '@waltermedia/fortnox-client';
const tokenManager = new TokenManager(
'initial-access-token',
'initial-refresh-token',
new Date(/* expiration timestamp */),
'your-client-id',
'your-client-secret'
);
const { accessToken, refreshToken, expiresIn, expiresAt } = await tokenManager.getToken();Security: Store client credentials in environment variables. Never expose them in client-side code.
TypeScript Types
All response and parameter types are exported:
import type {
VoucherCollection,
DetailedVoucher,
AccountCollection,
DetailedAccount,
InvoiceCollection,
SupplierInvoicesCollection,
GetVouchersParams,
GetAccountParams,
// ... and more
} from '@waltermedia/fortnox-client';API Reference
| Method | Description |
|--------|-------------|
| getVouchers(params) | List vouchers with filters |
| getVoucherDetails(params) | Get single voucher by series/number |
| getAccounts(params) | List accounts |
| getAccountDetails(params) | Get single account |
| getInvoices(params) | List customer invoices |
| getSupplierInvoices(params) | List supplier invoices |
| getCompanyInformation() | Company info |
| getFinancialYears(params) | Financial years |
| getSIE(params) | SIE export (type "3" or "4") |
Security
This client includes:
- Path parameter validation — Voucher series, numbers, and account IDs are validated to prevent path injection
- Sanitized error logging — Tokens and credentials are never logged
- Safe error storage —
FortnoxError.responseexcludes auth headers
Publishing to npm
For maintainers. Ensure you're logged in (npm login) and have publish access to @waltermedia:
npm run release # patch: build → version → publish → push
npm run release-minor # minor: build → version → publish → pushOr manually:
npm run build
npm version patch # or minor/major
npm publish
git push && git push --tagsLicense
MIT © Walter Media AB
