by Magnus-Gille
Provides a command‑line interface and Model Context Protocol server for interacting with Fortnox to manage invoices, customers, suppliers, bookkeeping, VAT, payroll and related automation.
Noxctl offers a unified CLI and MCP server that talks directly to the Fortnox REST API. It enables accountants, bookkeepers, developers and AI assistants to list, create, update and process invoices, customers, suppliers, vouchers, payroll, tax reports and many other accounting entities without needing a custom backend.
npm install --global noxctl or use the on‑the‑fly command npx noxctl <command>.noxctl init (or npx noxctl init) and follow the interactive wizard to supply your Fortnox developer‑app client‑id, secret and OAuth scopes. Credentials are stored securely in the OS keychain.--profile <name> or the noxctl profile commands.noxctl invoices list --filter unpaid or pipe JSON output: noxctl -o json invoices list | jq ..noxctl serve (or npx noxctl serve). AI agents that understand MCP can then invoke any operation as a tool.--yes and --dry-run previews.fortnox_create_invoice).noxctl/embedded package in Node.js applications to call Fortnox operations without exposing the CLI or keychain.salary scope, keeping employee personal data protected.Q: Do I need a Fortnox developer app?
A: Yes. Noxctl works with a “bring‑your‑own‑app” model; you create the app in Fortnox, enable the required scopes and authorize it via noxctl init.
Q: Can I run Noxctl without installing it globally?
A: Absolutely. Use npx noxctl <command> to execute any CLI command or start the server.
Q: How are credentials stored?
A: On macOS they live in the login or a dedicated YubiKey‑locked keychain, on Linux via secret-tool, and on Windows via DPAPI‑protected user store.
Q: What if I get a 403 error?
A: The error will name the missing scope. Enable the corresponding permission in your Fortnox app and re‑run noxctl init.
Q: How do I enable optional scopes like Orders, Payroll or Archive?
A: Add the scopes in the Fortnox app and re‑authorize with the appropriate flag, e.g. noxctl init --with-orders or set FORTNOX_WITH_SALARY=1.
Q: Is there a way to test commands without affecting data?
A: Use the --dry-run flag (CLI) or dryRun: true (MCP) to preview the request payload without sending it.
Q: How do I start the MCP server for an AI assistant?
A: Run noxctl serve (or npx noxctl serve). The server reads the active profile (or --profile) and listens on the default MCP port for tool calls.
Q: What happens if the active profile pointer is corrupted?
A: The server refuses to start, forcing you to repair the pointer with noxctl profile use or noxctl doctor.
Q: Can I use Noxctl on Windows? A: Yes. Credentials are stored via DPAPI and the CLI works on any platform supported by Node.js 22.12+.
Fortnox from the terminal — or from an MCP-compatible AI assistant.
noxctl is a command-line interface (CLI) and Model Context Protocol (MCP) server for invoices, customers, suppliers, bookkeeping, VAT, payroll, and more. Fortnox operations share the same CLI and MCP command surface, so you can use noxctl interactively, in scripts, or through tools such as Claude Code.
You bring your own Fortnox developer app. Credentials stay in your operating system's secure store, and requests go directly from your machine to the Fortnox API — there is no shared credential and no backend operated by this project.
[!IMPORTANT] noxctl is an independent, unofficial open-source project. It is not affiliated with, endorsed by, or certified by Fortnox AB. You remain responsible for reviewing every operation and complying with applicable terms and accounting, tax, payroll, and privacy rules. See the full Disclaimer.
--dry-run / dryRun previews.noxctl tracks the complete published Fortnox operation inventory in an opaque, privacy-safe implementation manifest. Every family is classified as complete, partial, excluded, or blocked, and implemented families are verified against actual operation exports, discovered MCP tools, and CLI commands.
The open-source core deliberately excludes separate product domains such as warehouse management, partner onboarding/KYC, integration-marketplace administration, and the standalone time-reporting API. Shared reference/configuration resources are read-first: their reads are supported, while writes are explicitly excluded from the v1 core. Remote URL attachment connections are also excluded because they introduce a separate remote-fetch trust boundary. These are product-boundary decisions, not hidden gaps.
You need Node.js 22.12+, a Fortnox account with API access, and your own Fortnox
developer app. Linux also requires secret-tool for secure credential storage.
npm install --global noxctl
noxctl init # interactive setup wizard
noxctl company info # verify the connection
Then explore from the terminal:
noxctl customers list # list customers
noxctl invoices list --filter unpaid # unpaid invoices
noxctl -o json invoices list | jq . # JSON output for scripting/AI
Prefer not to install globally? Skip the install command and run CLI commands as npx noxctl <command> instead.
Documentation: full setup · profiles · commands and MCP tools · mutation safety · embedded runtimes · troubleshooting · contributing
Fortnox product plans, API activation requirements, and integration licensing can change. Verify the current Fortnox requirements before publishing or relying on this setup for business-critical work.
noxctl is a thin client over the Fortnox REST API (v3) at https://api.fortnox.se/3. It uses a bring-your-own-app model — there is no shared backend and no middleman:
noxctl init).So you control the credentials, the scopes, and which company is connected end to end. The three steps below set this up.
Tip: Run
npx noxctl init(npx is a tool included with npm, the Node Package Manager) for an interactive setup wizard that guides you through all of these steps.
Go to developer.fortnox.se and click Integrationer / Integrations
Create a new app (integration)
On the OAuth (Open Authorization) tab:
http://localhost:9876/callbackOn the Integration tab, enable these scopes under Behörigheter / Permissions:
| Scope | Swedish (SV) | English (EN) | Fortnox licence needed | Needed for |
|---|---|---|---|---|
article |
Artikel | Article | Order or Kundfaktura | Articles |
bookkeeping |
Bokföring | Bookkeeping | Bokföring or Kundfaktura | Vouchers, accounts, financial reports, financial years |
companyinformation |
Företagsinformation | Company Information | Any | Company info |
connectfile |
— | File Connection | Bokföring/Anläggning/Arkivplats | Attaching uploaded files to vouchers |
costcenter |
Kostnadsställe | Cost Center | Bokföring, Order or Kundfaktura | Cost centers |
customer |
Kund | Customer | Kundfaktura or Order | Customers |
inbox |
— | Inbox | Any | Uploading receipt/attachment files |
invoice |
Faktura | Invoice | Order or Kundfaktura | Invoices, tax reductions |
payment |
Betalning | Payment | Bokföring, Order or Kundfaktura | Invoice payments, supplier invoice payments |
price |
Priser | Price | Order or Kundfaktura | Price lists, prices |
project |
Projekt | Project | Bokföring, Order or Kundfaktura | Projects |
settings |
Inställningar | Settings | Any | Locked period |
supplier |
Leverantör | Supplier | Bokföring | Suppliers |
supplierinvoice |
Leverantörsfaktura | Supplier Invoice | Bokföring | Supplier invoices |
offer |
Offert | Offer | Order | Offers — opt-in, see below |
order |
Order | Order | Order | Orders — opt-in, see below |
salary |
Lön | Salary | Lön | Payroll: employees, salary/attendance/absence transactions, schedule times — opt-in, see below |
archive |
Arkivplats | File Archive | Arkivplats | Attaching files to customer invoices — opt-in, see below |
Enable every non-opt-in scope. noxctl requests that exact set at authorize time, and
Fortnox rejects the whole authorization if the app has not been granted a scope that
is asked for — so a partially-enabled app fails at noxctl init rather than at first
use. noxctl init prints the same list.
Missing scopes surface as 403 Forbidden with a hint naming the scope (e.g.
Missing "payment" scope); match that token against the Scope column above.
Two scope groups are opt-in, because they depend on a Fortnox licence the default set does not require. Requesting a scope the company is not licensed for fails the whole authorization, so asking for these unconditionally would lock out companies that simply do not have the module:
noxctl init --with-orders (or FORTNOX_WITH_ORDERS=1).noxctl init --with-salary (or FORTNOX_WITH_SALARY=1).noxctl init --with-archive (or FORTNOX_WITH_ARCHIVE=1). Only
needed for noxctl invoices attach — voucher and supplier-invoice attachments
use the inbox/connectfile scopes instead and don't need it.All three can be combined. The granted scope set is remembered per profile, so token refreshes keep working.
Save the integration
You are creating and authorizing your own Fortnox app here. noxctl does not ship shared Fortnox credentials and does not bypass Fortnox's authorization model.
Run the interactive setup wizard:
npx noxctl init
If running from a local clone:
npm run build
node dist/cli.js init
The wizard will prompt for your Client ID and Client Secret (masked input), run the OAuth flow, verify the connection, and optionally register the MCP server with Claude Code.
After authorization, credentials are stored in the OS (Operating System) secure store:
security)secret-toolToken management is automatic after setup — no environment variables needed going forward.
TenantId — no refresh tokens to manage. The tenant ID is fetched automatically during setup.If you use Claude Desktop or claude.ai, register the MCP server so those environments can access Fortnox. Claude Code can use the CLI directly, so this step is optional there.
claude mcp add fortnox -- npx noxctl serve
If you are running from a local clone instead of npm:
claude mcp add fortnox -- node /absolute/path/to/noxctl/dist/cli.js serve
noxctl company info
If running from source:
node dist/cli.js company info
You should see your company name, organisation number, and address. If this works, you're all set.
noxctl supports multiple Fortnox tenants from a single installation — useful if you bookkeep for several companies, or want to keep a sandbox tenant separate from production. Each profile has its own OAuth credentials in the OS secure store (macOS Keychain / Linux Secret Service / Windows DPAPI), keyed by profile name.
Three ways to pick the profile, in precedence order (highest wins):
--profile <name> flag — explicit, per-commandNOXCTL_PROFILE environment variable — scoped to a shell session~/.fortnox-mcp/active-profile, set by noxctl profile useIf none of these is set, noxctl uses the default profile (what existing users have been using all along — no opt-in required).
noxctl init --profile staging # authorize a second tenant
noxctl --profile staging invoices list # one-off against staging
NOXCTL_PROFILE=staging noxctl company info # shell-scoped
noxctl profile use staging # sticky — persists to the pointer
noxctl profile current # show resolved profile + source
noxctl profile list # list known profiles
When launched by Claude Desktop / claude.ai, the MCP server resolves the profile from NOXCTL_PROFILE and the active pointer at startup, and binds for the session. When launched via noxctl --profile <name> serve, the CLI forwards the flag.
To run multiple MCP servers (one per tenant) in parallel, register them with distinct names and scoped environments:
claude mcp add fortnox-prod -- npx noxctl serve
claude mcp add fortnox-staging -e NOXCTL_PROFILE=staging -- npx noxctl serve
Applications that supply their own authenticated Fortnox tenant context can use the supported noxctl/embedded package entry point. It provides an isolated client, typed operation set, and MCP server factory without exporting the local profile, keychain, or CLI startup APIs. See the embedded runtime API and host responsibility boundary.
Non-default sessions print a [profile: <name>] stderr banner on startup and prefix every Fortnox API error and token-refresh failure with the same tag so mis-bound sessions are diagnosable from a single error line.
If the active pointer becomes unreadable or corrupt and no explicit --profile flag or NOXCTL_PROFILE is set, noxctl serve refuses to start rather than silently falling back to default. This prevents a corrupted pointer from routing production MCP sessions to the wrong tenant. The CLI's doctor and profile use commands are exempt — they can still run against a broken pointer so you can repair it.
Credential diagnostics use the same four states in doctor, keychain status,
and MCP status: available, missing, locked, and inaccessible. Only
missing means no registered profile or credential was found. inaccessible
means noxctl cannot safely determine whether credentials exist in the current
execution context; it will not recommend or start OAuth replacement from that
state.
Use this recovery flow when a sandboxed agent and your terminal disagree:
# Run these in a normal, unsandboxed terminal.
noxctl keychain status
noxctl keychain unlock # only when the dedicated keychain is locked
noxctl --profile <name> doctor
noxctl --profile <name> company info
Do not re-run noxctl init while the state is locked or inaccessible.
Resolve access first, then retry with an explicit profile. An MCP server is
pinned to the profile selected when that process starts; changing the active
pointer does not retarget it. Restart the MCP server after correcting profile
selection or unlocking credentials.
By default, credentials live in your macOS login keychain, which unlocks automatically when you log in. That's convenient, but it means an AI agent (or anything running as you) can read the tokens without a per-session gesture from you.
The optional dedicated keychain moves credentials into a separate, lock-on-sleep keychain whose password is derived from your YubiKey via HMAC-SHA1 challenge-response. You unlock it once per session with a single tap; it re-locks when your Mac sleeps. The keychain password is never typed or stored — it only exists on the YubiKey.
This is opt-in and macOS-only. It does not change how credentials are stored on Linux or Windows.
Program OTP slot 2 for challenge-response (requires touch). This writes only the empty OTP slot 2 — FIDO2, PIV, OATH, OpenPGP, and slot 1 are untouched, and it is reversible with ykman otp delete 2.
brew install ykman # if not already installed
ykman otp chalresp --generate --touch 2 # program slot 2
noxctl keychain init # generate challenge, tap to derive the password,
# create the locked keychain, copy existing creds in
init uses copy-and-keep: your existing login-keychain credentials are copied into the new keychain but left in place as a rollback. Once you've confirmed the new flow works, remove the originals:
noxctl keychain seal # delete the login-keychain copies (irreversible)
Until you seal, the login copies remain readable without a tap — so the per-session protection isn't fully in effect.
noxctl keychain unlock # tap your YubiKey — open until the Mac next sleeps
noxctl keychain status # mode, lock state, ykman/YubiKey presence
noxctl keychain lock # lock immediately
When the keychain is locked, any command that needs credentials fails fast with a message telling you to run noxctl keychain unlock — it never pops a macOS password dialog (the challenge-response password can't be typed into one).
The keychain password lives only on the key, so a lost or re-programmed key means the dedicated keychain can't be unlocked. As long as you have not run seal, your credentials are still in the login keychain — delete the dedicated keychain and challenge file to fall back:
security delete-keychain ~/Library/Keychains/fortnox-mcp.keychain-db
rm ~/.fortnox-mcp/keychain-challenge
If you have sealed, re-run noxctl init to re-authenticate from scratch.
Every operation is available both as a CLI command and as an MCP tool. The CLI is the primary interface; the MCP server exposes the same operations to AI agents. All mutations — every row labeled (mutation) — prompt for confirmation on a TTY and require --yes (CLI) or confirm: true (MCP) when piped. See Mutation safety.
| CLI | MCP tool | Description |
|---|---|---|
noxctl customers list [--search <term>] |
fortnox_list_customers |
List/search customers |
noxctl customers get <number> |
fortnox_get_customer |
Get a single customer |
noxctl customers create --name <name> |
fortnox_create_customer |
Create a customer (mutation) |
noxctl customers update <number> --input <file> |
fortnox_update_customer |
Update a customer (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl suppliers list [--search <term>] |
fortnox_list_suppliers |
List/search suppliers |
noxctl suppliers get <number> |
fortnox_get_supplier |
Get a single supplier |
noxctl suppliers create --name <name> |
fortnox_create_supplier |
Create a supplier (mutation) |
noxctl suppliers update <number> --input <file> |
fortnox_update_supplier |
Update a supplier (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl articles list [--search <term>] |
fortnox_list_articles |
List/search articles |
noxctl articles get <number> |
fortnox_get_article |
Get a single article |
noxctl articles create --description <text> |
fortnox_create_article |
Create an article (mutation) |
noxctl articles update <number> --input <file> |
fortnox_update_article |
Update an article (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl invoices list [--filter <status>] [--customer <number>] |
fortnox_list_invoices |
List/filter invoices. Filters: cancelled, fullypaid, unpaid, unpaidoverdue, unbooked |
noxctl invoices get <docNumber> |
fortnox_get_invoice |
Get a single invoice |
noxctl invoices create --customer <number> --input <file> |
fortnox_create_invoice |
Create an invoice (mutation) |
noxctl invoices update <docNumber> --input <file> |
fortnox_update_invoice |
Update an invoice that has not been bookkeept (mutation) |
noxctl invoices send <docNumber> [--method email|print|einvoice] [--subject <s>] [--body <s>] [--bcc <email>] |
fortnox_send_invoice |
Send via email (default), print, or e-invoice (mutation) |
noxctl invoices pdf <docNumber> [--file <path>|-] [--mark-sent] |
fortnox_invoice_pdf |
Download the invoice PDF (via /preview, no side effect). --mark-sent also flags it as sent afterwards (mutation) |
noxctl invoices bookkeep <docNumber> |
fortnox_bookkeep_invoice |
Bookkeep an invoice (mutation) |
noxctl invoices credit <docNumber> |
fortnox_credit_invoice |
Credit an invoice (mutation) |
noxctl invoices attach <docNumber> <file...> [--no-include-on-send] |
fortnox_attach_invoice_files |
Upload receipt/underlag files and attach them to a customer invoice (mutation; needs the Fortnox archive scope — noxctl init --with-archive) |
noxctl invoices attachments <docNumber> |
fortnox_list_invoice_attachments |
List files currently attached to a customer invoice |
| CLI | MCP tool | Description |
|---|---|---|
noxctl invoice-payments list [--invoice <number>] / alias noxctl ip list |
fortnox_list_invoice_payments |
List invoice payments |
noxctl invoice-payments get <number> |
fortnox_get_invoice_payment |
Get a single invoice payment |
noxctl invoice-payments create --invoice <n> --amount <a> --date <date> |
fortnox_create_invoice_payment |
Register a payment against an invoice (mutation) |
noxctl invoice-payments bookkeep <number> |
— | Bookkeep an invoice payment (mutation) |
noxctl invoice-payments delete <number> |
fortnox_delete_invoice_payment |
Delete an invoice payment (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl supplier-invoices list [--filter <status>] [--supplier <number>] / alias si list |
fortnox_list_supplier_invoices |
List/filter supplier invoices |
noxctl supplier-invoices get <givenNumber> |
fortnox_get_supplier_invoice |
Get a single supplier invoice |
noxctl supplier-invoices create --supplier <n> --input <file> |
fortnox_create_supplier_invoice |
Create a supplier invoice (mutation) |
noxctl supplier-invoices bookkeep <givenNumber> |
fortnox_bookkeep_supplier_invoice |
Bookkeep a supplier invoice (mutation) |
noxctl supplier-invoices attachments <givenNumber> |
fortnox_list_supplier_invoice_attachments |
List files (e.g. the scanned/received invoice) attached to a supplier invoice — works for unbooked/authorizepending invoices too, read-only, default scopes only |
noxctl supplier-invoices file <fileId> [-f <path>] |
fortnox_get_supplier_invoice_file |
Download a file attached to a supplier invoice (get fileId from supplier-invoices attachments) — read-only, default scopes only |
| CLI | MCP tool | Description |
|---|---|---|
noxctl supplier-invoice-payments list [--invoice <number>] / alias sip list |
fortnox_list_supplier_invoice_payments |
List supplier invoice payments |
noxctl supplier-invoice-payments get <number> |
fortnox_get_supplier_invoice_payment |
Get a single supplier invoice payment |
noxctl supplier-invoice-payments create --invoice <n> --amount <a> --date <date> |
fortnox_create_supplier_invoice_payment |
Register a payment against a supplier invoice (mutation) |
noxctl supplier-invoice-payments delete <number> |
fortnox_delete_supplier_invoice_payment |
Delete a supplier invoice payment (mutation) |
Requires the
offerscope, which is opt-in and needs the Fortnox Order licence. Runnoxctl init --with-orders(or setFORTNOX_WITH_ORDERS=1), which requestsofferandordertogether. Without it, these endpoints return403 Forbidden. See Setup.
| CLI | MCP tool | Description |
|---|---|---|
noxctl offers list [--filter <status>] [--customer <number>] |
fortnox_list_offers |
List/filter offers. Filters: cancelled, expired, ordercreated, invoicecreated |
noxctl offers get <docNumber> |
fortnox_get_offer |
Get a single offer |
noxctl offers create --customer <number> --input <file> |
fortnox_create_offer |
Create an offer (mutation) |
noxctl offers update <docNumber> --input <file> |
fortnox_update_offer |
Update an offer (mutation) |
noxctl offers create-invoice <docNumber> |
fortnox_create_invoice_from_offer |
Convert offer → invoice (mutation) |
noxctl offers create-order <docNumber> |
fortnox_create_order_from_offer |
Convert offer → order (mutation) |
Requires the
orderscope, which is opt-in and needs the Fortnox Order licence. Runnoxctl init --with-orders(or setFORTNOX_WITH_ORDERS=1), which requestsofferandordertogether. Without it, these endpoints return403 Forbidden. See Setup.
| CLI | MCP tool | Description |
|---|---|---|
noxctl orders list [--filter <status>] [--customer <number>] |
fortnox_list_orders |
List/filter orders. Filters: cancelled, invoicecreated, invoicenotcreated |
noxctl orders get <docNumber> |
fortnox_get_order |
Get a single order |
noxctl orders create --customer <number> --input <file> |
fortnox_create_order |
Create an order (mutation) |
noxctl orders update <docNumber> --input <file> |
fortnox_update_order |
Update an order (mutation) |
noxctl orders create-invoice <docNumber> |
fortnox_create_invoice_from_order |
Convert order → invoice (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl vouchers list [--series <s>] [--from <date>] [--to <date>] |
fortnox_list_vouchers |
List vouchers, optionally filtered by series and date range |
noxctl vouchers get <series> <number> |
fortnox_get_voucher |
Get a single voucher with rows |
noxctl vouchers create --input <file> |
fortnox_create_voucher |
Create a voucher with debit/credit rows (mutation) |
noxctl vouchers attach <series> <number> <file...> [--year] |
fortnox_attach_voucher_files |
Upload receipt/underlag files and link them to a voucher (mutation; needs the Fortnox archive scope) |
noxctl vouchers attachments <series> <number> [--year] |
fortnox_list_voucher_attachments |
List files (receipts/underlag) already attached to a voucher — read-only, default scopes only |
noxctl vouchers file <fileId> [-f <path>] |
fortnox_get_voucher_file |
Download a file attached to a voucher (get fileId from vouchers attachments) — read-only, default scopes only |
noxctl general-ledger list --from <date> --to <date> [--year] [--account] [--series] / alias ledger list |
fortnox_general_ledger |
Bookkeeping transactions with amounts for a date range, one row per posting — reads Fortnox's SIE export instead of walking vouchers one by one, so it stays fast for a full year. Read-only, default scopes only |
noxctl accounts list [--search <term>] |
fortnox_list_accounts |
View chart of accounts, search by name or number |
| CLI | MCP tool | Description |
|---|---|---|
noxctl reports income [--year <n>] [--from <date>] [--to <date>] / alias reports resultat |
fortnox_income_statement |
Income statement (resultaträkning) |
noxctl reports balance [--year <n>] [--to <date>] / alias reports balans |
fortnox_balance_sheet |
Balance sheet (balansräkning) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl tax report --from <date> --to <date> |
fortnox_tax_report |
Informational VAT summary for a period. Reconcile against Fortnox before filing. Dates in YYYY-MM-DD format |
| CLI | MCP tool | Description |
|---|---|---|
noxctl tax-reductions list [--filter <type>] |
fortnox_list_taxreductions |
List tax reductions (ROT/RUT) |
noxctl tax-reductions get <id> |
fortnox_get_taxreduction |
Get a single tax reduction |
noxctl tax-reductions create --reference <n> --type <rot|rut> --document-type <type> --customer-name <name> --amount <öre> |
fortnox_create_taxreduction |
Create a ROT/RUT tax reduction (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl projects list |
fortnox_list_projects |
List projects |
noxctl projects get <number> |
fortnox_get_project |
Get a single project |
noxctl projects create --description <text> |
fortnox_create_project |
Create a project (mutation) |
noxctl projects update <number> --input <file> |
fortnox_update_project |
Update a project (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl costcenters list |
fortnox_list_costcenters |
List cost centers |
noxctl costcenters get <code> |
fortnox_get_costcenter |
Get a single cost center |
noxctl costcenters create --code <code> --description <text> |
fortnox_create_costcenter |
Create a cost center (mutation) |
noxctl costcenters update <code> --input <file> |
fortnox_update_costcenter |
Update a cost center (mutation) |
noxctl costcenters delete <code> |
fortnox_delete_costcenter |
Delete a cost center (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl pricelists list |
fortnox_list_pricelists |
List price lists |
noxctl pricelists get <code> |
fortnox_get_pricelist |
Get a single price list |
noxctl pricelists create --code <code> --description <text> |
fortnox_create_pricelist |
Create a price list (mutation) |
noxctl pricelists update <code> --input <file> |
fortnox_update_pricelist |
Update a price list (mutation) |
noxctl prices list --pricelist <code> [--article <number>] |
fortnox_list_prices |
List prices within a price list |
noxctl prices get --pricelist <code> --article <number> |
fortnox_get_price |
Get a specific price |
noxctl prices update --pricelist <code> --article <number> --input <file> |
fortnox_update_price |
Update a price (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl contracts list [--filter active|inactive|finished] |
fortnox_list_contracts |
List/filter contracts |
noxctl contracts get <number> |
fortnox_get_contract |
Get a single contract |
noxctl contracts create --customer <number> --input <file> |
fortnox_create_contract |
Create a contract (mutation) |
noxctl contracts update <number> --input <file> |
fortnox_update_contract |
Update a contract (mutation) |
noxctl contracts finish <number> |
fortnox_finish_contract |
Finish a contract (mutation) |
noxctl contracts create-invoice <number> |
fortnox_create_invoice_from_contract |
Create the next invoice now (mutation) |
noxctl contracts increase-invoice-count <number> |
fortnox_increase_contract_invoice_count |
Extend by one invoice (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl financial-years list [--date <date>] |
fortnox_list_financialyears |
List financial years (räkenskapsår) |
noxctl financial-years get <id> |
fortnox_get_financialyear |
Get a single financial year |
noxctl financial-years locked-period |
fortnox_get_lockedperiod |
Show through which date bookkeeping is locked |
The following command groups expose list and, where Fortnox provides it, get in
both CLI and MCP: currencies, units, modes-of-payments,
terms-of-deliveries, terms-of-payments, ways-of-delivery, voucher-series,
predefined-voucher-series, account-charts, predefined-accounts, and
customer-references.
noxctl currencies list
noxctl terms-of-payments get 30
noxctl account-charts list
| CLI group | MCP tool prefix | Operations |
|---|---|---|
noxctl invoice-accruals |
fortnox_*_invoice_accrual |
list, get, create, update, delete |
noxctl supplier-invoice-accruals |
fortnox_*_supplier_invoice_accrual |
list, get, create, update, delete |
noxctl contract-accruals |
fortnox_*_contract_accrual |
list, get, create, update, delete |
Every mutation supports confirmation and dry-run preview. Nested accrual rows are strict and validated before any request is sent.
| CLI group | MCP surface | Purpose |
|---|---|---|
noxctl archive |
fortnox_*_archive* |
List/download, multipart upload, delete path/entry |
noxctl inbox |
fortnox_*_inbox* |
List, multipart upload, safe download, delete |
noxctl attachments |
fortnox_*_document_attachment* |
Attach/list/count/validate/update/detach for invoices, offers, orders, and contracts |
Voucher and supplier-invoice file connections additionally expose get/connect/detach
commands under their existing CLI groups. Binary downloads default to a private
temporary directory, use mode 0600, refuse symlink targets and accidental overwrite,
and only replace an existing regular file when --overwrite is explicit.
Requires the
salaryscope, which is opt-in. Enable the Lön permission on your Fortnox app, then runnoxctl init --with-salary(or setFORTNOX_WITH_SALARY=1in non-interactive setups). Without it, these endpoints return403 Forbidden. See Setup.
| CLI | MCP tool | Description |
|---|---|---|
noxctl employees list |
fortnox_list_employees |
List employees |
noxctl employees get <employeeId> |
fortnox_get_employee |
Get a single employee |
noxctl employees create --first-name <n> --last-name <n> --email <e> [--employment-form <f> --personel-type <t> --salary-form <f>] |
fortnox_create_employee |
Create an employee (mutation). --employment-form/--personel-type/--salary-form are required unless the company has a default employment agreement — otherwise Fortnox rejects with a ftgavtalid error |
noxctl employees update <employeeId> --input <file> |
fortnox_update_employee |
Update an employee (mutation) |
noxctl salary-transactions list [--employee <id>] [--date <date>] |
fortnox_list_salarytransactions |
List salary transactions |
noxctl salary-transactions get <salaryRow> |
fortnox_get_salarytransaction |
Get a single salary transaction |
noxctl salary-transactions create --employee <id> --salary-code <code> --date <date> [--amount <n>] |
fortnox_create_salarytransaction |
Create a salary transaction (mutation) |
noxctl salary-transactions delete <salaryRow> |
fortnox_delete_salarytransaction |
Delete a salary transaction (mutation) |
noxctl attendance-transactions list [--employee <id>] [--date <date>] |
fortnox_list_attendancetransactions |
List attendance (närvaro) transactions |
noxctl attendance-transactions get <id> |
fortnox_get_attendancetransaction |
Get a single attendance transaction |
noxctl attendance-transactions create --employee <id> --cause-code <code> --date <date> [--hours <n>] |
fortnox_create_attendancetransaction |
Create an attendance transaction (mutation) |
noxctl attendance-transactions delete <id> |
fortnox_delete_attendancetransaction |
Delete an attendance transaction (mutation) |
noxctl absence-transactions list [--employee <id>] [--date <date>] |
fortnox_list_absencetransactions |
List absence (frånvaro) transactions |
noxctl absence-transactions get <id> |
fortnox_get_absencetransaction |
Get a single absence transaction |
noxctl absence-transactions create --employee <id> --cause-code <code> --date <date> [--hours <n>] [--extent <n>] |
fortnox_create_absencetransaction |
Create an absence transaction (mutation) |
noxctl absence-transactions delete <id> |
fortnox_delete_absencetransaction |
Delete an absence transaction (mutation) |
noxctl schedule-times get <employeeId> <date> |
fortnox_get_scheduletime |
Get the schedule for an employee on a date |
noxctl schedule-times update <employeeId> <date> --input <file> |
fortnox_update_scheduletime |
Update a day's schedule (mutation) |
noxctl schedule-times reset-day <employeeId> <date> --input <file> |
fortnox_reset_scheduletime_day |
Update a day's schedule and reset the day (mutation) |
| CLI | MCP tool | Description |
|---|---|---|
noxctl analytics overdue |
fortnox_overdue_invoices |
Overdue invoices summary |
noxctl analytics unpaid |
fortnox_unpaid_totals |
Outstanding receivables, with overdue split |
noxctl analytics top-customers [--period <period>] |
fortnox_top_customers |
Top customers by invoiced amount |
noxctl analytics vat --period <period> |
fortnox_vat_summary |
VAT summary with net VAT position |
noxctl dashboard |
— | At-a-glance: outstanding, overdue, recent invoices, monthly revenue |
| CLI | MCP tool | Description |
|---|---|---|
noxctl company info |
fortnox_company_info |
Company name, org number, address, and settings |
| CLI | MCP tool | Description |
|---|---|---|
noxctl init |
— | Interactive setup wizard — connects to Fortnox, stores credentials, optionally registers MCP server |
noxctl doctor |
fortnox_status |
Validate setup: Node version, credentials, token status, API connectivity, and scopes |
noxctl logout |
— | Remove stored credentials from the OS keychain |
noxctl profile use <name> |
— | Set the active profile (writes ~/.fortnox-mcp/active-profile) |
noxctl profile current |
— | Show the currently resolved profile and where it came from |
noxctl profile list |
— | List known profiles from the index |
noxctl completion <bash|zsh|fish> |
— | Generate a shell completion script |
By default, noxctl uses table output on interactive terminals and JSON when piped or redirected. Override with -o:
noxctl invoices list # table on terminal, JSON when piped
noxctl -o json invoices list # force JSON (JavaScript Object Notation)
noxctl -o table invoices list # force table
noxctl invoices list | jq . # auto-JSON (piped)
JSON output has a stable envelope: list commands wrap under the plural resource key ({"Invoices": [...], "MetaInformation": {...}}) and single-resource commands under the singular key ({"Invoice": {...}}), so scripted callers can rely on a fixed accessor. Failures in JSON mode are emitted to stderr as a structured envelope:
{ "error": { "status": 400, "message": "...", "source": "fortnox-api" } }
Natural date periods are accepted wherever --from/--to work, via --period: Q1, 2025-Q3, march/mars, this-quarter, last-quarter, this-month, last-month, ytd, this-year, last-year, or a bare year. Periods are calendar-year based (broken fiscal years are not yet considered).
When running from a local clone instead of an installed binary, replace noxctl with node dist/cli.js.
Mutating commands require confirmation before executing. On interactive terminals, the CLI prompts with [y/N]. In non-interactive contexts (piped input, CI), pass --yes explicitly or the command will fail safely.
CLI:
noxctl invoices send 1001 # prompts: "Send invoice 1001 via email. Continue? [y/N]"
noxctl invoices send 1001 --yes # skip prompt (scripting/AI)
noxctl invoices send 1001 --dry-run # preview without sending
noxctl invoices pdf 1001 # read-only, no prompt
noxctl invoices pdf 1001 --mark-sent # prompts: also flags the invoice as sent
noxctl customers update 42 --input customer.json # prompts for confirmation
noxctl vouchers create --input voucher.json --dry-run # preview payload
MCP tools:
confirm: truedryRun: true to preview a request without sending itincludeRaw: trueincludeRaw: true can expose more accounting and personal data to AI transcripts, logs, and terminals than the summarized default outputIf you use noxctl through Claude, MCP clients, or other AI tooling, customer, supplier, invoice, and bookkeeping data may leave the local Fortnox UI context and enter third-party systems.
includeRaw off unless you truly need the full payloadSee PRIVACY.md for the project-specific privacy notes.
noxctl can help you inspect Fortnox data and submit operations you choose to confirm. It does not make legal judgments for you.
Ask Claude naturally — works in both Swedish and English:
"stdin is not a TTY. Set FORTNOX_CLIENT_ID and FORTNOX_CLIENT_SECRET env vars to run non-interactively"
noxctl init is normally interactive — it prompts for the Client ID and Secret. In CI or other non-TTY contexts it falls back to reading them from environment variables:
export FORTNOX_CLIENT_ID=<your-id>
export FORTNOX_CLIENT_SECRET=<your-secret>
export FORTNOX_SERVICE_ACCOUNT=1 # optional, enables service account mode
noxctl init
Once authorized, the tokens are stored in the OS keychain. No env vars are needed afterwards — only for re-running init non-interactively.
"Not authenticated. Run noxctl init"
This message is emitted only when the credential state is missing. Re-run the
setup step. If the message instead says locked or inaccessible, do not
replace the credentials: follow the
sandbox/automation recovery flow.
On Linux, an inaccessible store can also mean that secret-tool is unavailable
(sudo apt install libsecret-tools).
403 Forbidden from Fortnox API
Your app is missing one or more scopes. The error message names the specific scope needed (e.g. Missing "supplier" scope). Go to developer.fortnox.se, open your app, and enable the matching permission under Behörigheter / Permissions — see the full table in Setup → Create a Fortnox app. Then re-run noxctl init.
"Token refresh failed"
Your refresh token may have expired or been revoked. Re-run setup to re-authenticate.
Port 9876 already in use
Another process is using the OAuth callback port. Close it or wait for a previous setup attempt to finish, then try again.
npm ci # reproducible install; does not rewrite package-lock.json
npm run build # compile TypeScript
npm test # run tests
npm run test:watch # watch mode
npm run lint # ESLint with typescript-eslint
npm run format # format
npm run check:api # refresh the git-ignored OpenAPI cache and detect API drift
npm run audit:schemas # inventory and recursively audit every mutating MCP input
npm run audit:api-coverage # verify the full operation inventory and implementation evidence
See ARCHITECTURE.md for details.
statedryRun| Abbreviation | Full term |
|---|---|
| AI | Artificial Intelligence |
| API | Application Programming Interface |
| BCC | Blind Carbon Copy — an email field that sends a copy to someone without other recipients seeing it |
| CLI | Command Line Interface — a text-based way to interact with software by typing commands |
| DPAPI | Data Protection API — a Windows feature for encrypting stored credentials |
| JSON | JavaScript Object Notation — a widely used format for structured data |
| MCP | Model Context Protocol — a standard that lets AI assistants use external tools and data sources |
| MIT | Massachusetts Institute of Technology — refers to a permissive open-source software license |
| npm | Node Package Manager — a tool for installing and managing JavaScript packages |
| npx | A tool included with npm for running packages without installing them globally |
| OAuth | Open Authorization — a standard protocol for granting apps limited access to accounts without sharing passwords |
| OS | Operating System — the software that runs your computer (e.g. macOS, Windows, Linux) |
| SEK | Swedish Krona — the currency of Sweden |
| URI | Uniform Resource Identifier — an address that identifies a resource (similar to a web link) |
| VAT | Value Added Tax — a consumption tax added at each stage of production |
noxctl is an independent, unofficial open-source project — not affiliated with, endorsed by, or certified by Fortnox AB. "Fortnox" is a trademark of Fortnox AB, used here only to describe interoperability.
No warranty, no liability. noxctl is provided "as is", without warranty of any kind, express or implied. The author and contributors accept no responsibility and no liability whatsoever for anything arising from its use — including, without limitation: incorrect, incomplete, or lost bookkeeping; erroneous invoices, payments, payroll, or tax filings; exposure or loss of data; service downtime; financial loss; or any breach of Fortnox's terms. You use it entirely at your own risk. (See the MIT License below — the same limitation applies in full.)
You are responsible for everything you do with it. Under Swedish law (Bokföringslagen), the company owner or board bears full responsibility for the correctness of all accounting and payroll records, regardless of the tools used. noxctl only executes the instructions you give it — review entries before confirming, especially with --yes / confirm: true, and reconcile against Fortnox and your own records.
Privacy / personal data. noxctl can move accounting and personal data out of Fortnox — customer/supplier details and, via the payroll commands, employee personal data such as Swedish personal identity numbers (personnummer), salaries, and absence records. When using it with AI assistants or MCP hosts, that data may enter third-party systems. Keep includeRaw: false unless full payloads are necessary, and ensure your use complies with GDPR, processor/data-processing agreements, and any required transfer assessments. See PRIVACY.md.
Tax note: The VAT report is an informational summary only. Reconcile it against Fortnox and your accounting records before submitting anything to Skatteverket.
Fortnox API access requires your own Fortnox account, developer app, and credentials. You must comply with the applicable Fortnox developer terms. noxctl ships no shared credentials, redistributes no Fortnox-owned code or data (not even Fortnox's OpenAPI spec — only opaque drift-detection hashes), and routes nothing through any server operated by the author — it calls the Fortnox API directly from your machine.
When you register a Fortnox developer app to use noxctl, you (not the noxctl author) accept Fortnox's Developer Agreement and are the contracting party. In particular:
MIT
Please log in to share your review and rating for this MCP.
Explore related MCPs that share similar capabilities and solve comparable challenges
by stripe
Provides SDKs and tools to integrate Stripe's billing and API services with large language models, agent frameworks, and token‑metering for AI‑powered products and businesses.
by goat-sdk
Enables AI agents to send and receive payments, purchase goods and services, execute investment strategies, tokenize assets, and obtain financial insights by leveraging blockchains, stablecoins, and wallets.
by financial-datasets
Provides access to income statements, balance sheets, cash flow statements, stock prices, market news, and cryptocurrency data through MCP tools for AI assistants.
by alpacahq
Enables large language models to trade stocks and options, retrieve real‑time and historical market data, and manage portfolios using plain English commands through a local or remote MCP server.
by stefanoamorelli
Provides an MCP server that connects AI models to SEC EDGAR filings, enabling real‑time retrieval of company filings, financial statements, and insider‑trading data with exact XBRL precision and verifiable filing references.
by imbenrabi
Provides AI assistants with direct access to Financial Modeling Prep data, including real‑time stock quotes, company fundamentals, financial statements, market indexes, news, and alternative data sets via the Model Context Protocol.
by ariadng
Enables AI LLMs to execute trades on the MetaTrader 5 platform through the Model Context Protocol.
by XeroAPI
Provides a bridge between the Model Context Protocol and Xero's API, enabling standardized access to Xero accounting and business features.
by kukapay
Provides a comprehensive set of cryptocurrency technical analysis indicators and ready‑to‑use trading strategies through an MCP interface, enabling AI agents and applications to generate buy, hold, or sell signals.
{
"mcpServers": {
"noxctl": {
"command": "npx",
"args": [
"noxctl",
"serve"
],
"env": {}
}
}
}claude mcp add noxctl npx noxctl serve