Skip to content

Connect Fortnox to ChatGPT: Manage Invoicing and Customer Data

Learn how to connect Fortnox to ChatGPT using an auto-generated MCP server to automate invoicing, customer management, and ERP workflows.

Uday Gajavalli Uday Gajavalli · · 10 min read
Connect Fortnox to ChatGPT: Manage Invoicing and Customer Data

If you need to connect Fortnox to ChatGPT to automate accounting workflows, manage invoices, or sync customer data, you need a Model Context Protocol (MCP) server. This server acts as the translation layer between ChatGPT's JSON-RPC tool calls and the Fortnox REST API. You can either build, host, and maintain this complex infrastructure yourself, or use a managed integration platform like Truto to dynamically generate a secure, authenticated MCP server URL.

If your team uses Claude, check out our guide on connecting Fortnox to Claude or explore our broader architectural overview on connecting Fortnox to AI Agents.

Giving a Large Language Model (LLM) read and write access to a core financial system like Fortnox is a serious engineering task. You have to handle deeply nested line-item payloads, localized data schemas, and strict rate limits. Every time Fortnox updates an endpoint or your finance team alters a custom field, a custom-built MCP server must be updated, redeployed, and tested to prevent AI hallucinations.

This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for Fortnox, connect it natively to ChatGPT, and execute complex billing workflows using natural language.

Stop writing boilerplate API integration code. Let Truto generate secure, managed MCP servers for your AI agents in seconds. :::

The Engineering Reality of the Fortnox API

A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools, implementing it against an ERP like Fortnox is exceptionally painful.

If you decide to build a custom MCP server for Fortnox, you own the entire API lifecycle. Here are the specific integration challenges that break standard CRUD assumptions when working with Fortnox:

Nested Payloads and Strict Schema Validation

Fortnox invoices are not flat records. An invoice requires a CustomerNumber, an InvoiceDate, and heavily nested InvoiceRows representing individual line items. Each line item has specific tax rules, account numbers, and article references. If an LLM attempts to generate a payload without an exact JSON schema definition, it will hallucinate field names (e.g., using TaxRate instead of the Fortnox-specific VAT codes) or omit required fields, resulting in HTTP 400 Bad Request errors. Your MCP server must dynamically fetch and enforce these exact schemas before passing the request upstream.

Localized Data Structures

Unlike standardized US-centric CRM systems, Fortnox uses localized terminology and data structures that confuse general-purpose LLMs. Customers and suppliers are tracked by CustomerNumber and SupplierNumber (strings, not integers), while corporate identities rely on OrganisationNumber. Addresses are split into VisitAddress, VisitCity, and VisitZipCode. If your MCP tool descriptions do not explicitly guide the LLM to map standard terms to these specific fields, the AI will fail to retrieve or update records accurately.

Specific Pagination and Sorting Mechanics

When listing records like customers or articles, Fortnox relies on strict offset/limit mechanics and often defaults to sorting by the lowest record number first. A naive MCP implementation might dump a massive array of records into ChatGPT's context window, immediately overflowing it. A production-grade MCP server must automatically inject limit and next_cursor parameters into the tool schema, instructing the LLM to fetch data in manageable chunks.

Fortnox to ChatGPT Quickstart Guide

If you want the fastest path from a fresh Truto account to ChatGPT successfully calling the Fortnox API, follow these steps.

What you need:

  • A Truto account with API access.
  • A Fortnox admin account to approve the OAuth consent.
  • A ChatGPT Plus, Team, Enterprise, or Pro account with Developer mode enabled.

Step 1: Connect Fortnox as an Integrated Account

In the Truto dashboard, navigate to Integrated Accounts -> New Integrated Account, select Fortnox, and run through the OAuth flow. Truto securely stores the refresh token and automatically refreshes access tokens before they expire. ChatGPT will never interact with an expired credential.

Copy your integrated_account_id from the dashboard.

Step 2: Generate the Fortnox MCP Server

Truto dynamically generates MCP servers based on the connected account's active integration documentation. You can create this server in two ways.

Method A: Via the Truto UI

  1. Navigate to the integrated account page for your Fortnox connection.
  2. Click the MCP Servers tab.
  3. Click Create MCP Server.
  4. Select your desired configuration (e.g., restrict methods to read or specific tags like invoicing).
  5. Click save and copy the generated MCP server URL.

Method B: Via the API Make a single POST call to scope an MCP endpoint to your integrated account. This creates a secure, hashed token in the Edge Key-Value store.

curl -X POST https://api.truto.one/integrated-account/$INTEGRATED_ACCOUNT_ID/mcp \
  -H "Authorization: Bearer $TRUTO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Fortnox ERP Tools for ChatGPT",
    "config": {
      "methods": ["read", "write"],
      "tags": ["customers", "invoices", "articles"]
    }
  }'

The response returns a url field formatted as https://api.truto.one/mcp/<token>. Treat this URL as a highly sensitive secret, as it contains both routing instructions and authentication.

Step 3: Connect the MCP Server to ChatGPT

Now, you must register the MCP server with your local or web-based ChatGPT client.

Method A: Via the ChatGPT UI

  1. Open ChatGPT and navigate to Settings -> Apps -> Advanced settings.
  2. Enable Developer mode.
  3. Under MCP servers / Custom connectors, click Add a new server.
  4. Set the Name to "Fortnox ERP".
  5. Paste your Truto MCP URL into the Server URL field.
  6. Click Save.

Method B: Via Manual Config File If you are running a local client or orchestration framework that relies on the standard MCP configuration file, you can register the server using the SSE transport adapter:

{
  "mcpServers": {
    "fortnox_erp": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-sse",
        "--url",
        "https://api.truto.one/mcp/<your_token_here>"
      ]
    }
  }
}

Restart your client. ChatGPT will execute an initialize handshake, and Truto will dynamically construct the tool schemas from the Fortnox integration and return them to the model.

sequenceDiagram
    participant ChatGPT as ChatGPT Client
    participant TrutoMCP as Truto Edge MCP
    participant Fortnox as Fortnox API
    ChatGPT->>TrutoMCP: JSON-RPC tools/list
    TrutoMCP->>TrutoMCP: Validate Token & Fetch Schemas
    TrutoMCP-->>ChatGPT: Return Fortnox Tool Definitions
    ChatGPT->>TrutoMCP: JSON-RPC tools/call (create_a_fortnox_invoice)
    TrutoMCP->>Fortnox: POST /3/invoices (Normalized Payload)
    Fortnox-->>TrutoMCP: 200 OK (Invoice JSON)
    TrutoMCP-->>ChatGPT: JSON-RPC Result

Fortnox Hero Tools for AI Agents

Truto automatically maps Fortnox API endpoints into snake_case, LLM-friendly MCP tools. Below are the highest-leverage tools for invoicing and customer management.

create_a_fortnox_invoice

Creates a highly structured invoice for a specific customer. This tool requires the LLM to pass a customer_number, an invoice_date, and an array of invoice_rows detailing the articles being billed. Because Truto injects the full JSON schema into the tool definition, ChatGPT knows exactly how to format the line items to satisfy Fortnox's strict validation.

"Draft a new invoice for customer number 1045. Set the invoice date to today, and add two line items: 5 hours of 'Consulting Services' (article number 100) at 1500 SEK each, and 1 'Software License' (article number 200) at 5000 SEK."

get_single_fortnox_invoice_by_id

Retrieves the complete payload of a specific invoice. This is critical for auditing invoice statuses, checking totals, or retrieving line-item details before processing a refund or sending a payment reminder.

"Pull up the details for invoice number 5590. I need to know the total amount due and if there are any outstanding balances."

list_all_fortnox_invoices

Lists all invoices in the system. Truto automatically injects pagination cursors (limit and next_cursor) so ChatGPT can safely iterate through massive financial ledgers without blowing up its context window.

"List the 10 most recent invoices created in Fortnox. Group them by customer number and summarize the total value."

create_a_fortnox_customer

Generates a new customer record in the Fortnox database. This tool handles the localized Swedish data structures, ensuring the LLM correctly maps standard company information into fields like OrganisationNumber and VisitAddress.

"Create a new customer profile for 'Acme Corp'. Their organization number is 556036-0793, and their main contact email is billing@acmecorp.com."

list_all_fortnox_customers

Retrieves the directory of active and inactive customers. This tool supports query filtering, allowing the agent to search by email, name, city, or customernumber.

"Search our Fortnox customer directory for any active clients located in Stockholm, and give me a list of their names and emails."

list_all_fortnox_articles

Fetches the inventory of billable articles (products or services) stored in Fortnox. ChatGPT can use this to look up correct article numbers before drafting an invoice, preventing 400 errors from invalid line items.

"List the available articles in Fortnox. I need to find the exact article number for our 'Monthly Retainer' service before I draft the next batch of invoices."

list_all_fortnox_suppliers

Retrieves the list of vendors and suppliers. This is heavily used by AI agents automating Accounts Payable workflows, allowing them to verify supplier details like SupplierNumber and VATNumber.

"Get the list of our active suppliers. Look for a vendor named 'TechSupply AB' and retrieve their supplier number and VAT ID."

To view the complete inventory of Fortnox API resources, methods, and schemas supported by Truto, visit the Fortnox integration page.

Workflows in Action

Individual tools are powerful, but the true value of an MCP server is orchestrating multi-step workflows. Here is how ChatGPT utilizes the Truto MCP server to automate complex Fortnox tasks.

Scenario 1: New Client Onboarding and Initial Billing

An operations manager needs to add a new client to the system and immediately bill them for an upfront onboarding fee.

"We just signed a new client, 'Nordic Logistics'. Create a new customer record for them using the email finance@nordiclogistics.se. Once they are created, look up the article number for 'Onboarding Fee', and generate an invoice for them for 1 unit of that article."

How the agent executes this:

  1. Calls create_a_fortnox_customer with the provided name and email. It extracts the resulting CustomerNumber from the response.
  2. Calls list_all_fortnox_articles to search the inventory and identifies that 'Onboarding Fee' corresponds to Article ID 55.
  3. Calls create_a_fortnox_invoice using the newly acquired CustomerNumber and inserting Article ID 55 into the invoice_rows array.

Result: The user receives confirmation that the customer was created (Customer #1089) and an invoice (Invoice #6002) was successfully drafted in Fortnox, all in a single prompt.

Scenario 2: Accounts Payable Auditing

A finance associate needs to verify supplier data against recent system entries to ensure compliance.

"Audit our supplier list. Pull the latest 10 suppliers, check if they have valid VAT numbers on file, and flag any active suppliers that are missing an email address."

How the agent executes this:

  1. Calls list_all_fortnox_suppliers with a limit parameter of 10.
  2. Parses the JSON array returned by Truto.
  3. Analyzes the VATNumber, Email, and Active properties for each supplier object in its own context.

Result: ChatGPT returns a formatted table highlighting two active suppliers missing email addresses, allowing the finance team to follow up and update the records.

Security and Access Control

Giving an LLM direct access to an ERP requires strict governance. Truto's MCP architecture enforces security at the token level, ensuring the AI can only execute what you explicitly permit.

  • Method Filtering: By defining config.methods: ["read"] during server creation, you can physically prevent the MCP server from generating create, update, or delete tools. The LLM simply will not know those endpoints exist.
  • Tag Filtering: You can restrict the server's scope by functional area. Setting tags: ["invoices"] ensures the agent can manage billing data but cannot access supplier or payroll records.
  • Require API Token Auth: Enabling require_api_token_auth on the server forces the connecting client to provide a valid Truto API token in the Authorization header, preventing unauthorized access if the MCP URL is leaked.
  • Time-to-Live (Expires At): You can set an expires_at ISO datetime when generating the token. Once the timestamp passes, an edge scheduler automatically deletes the token and terminates access, perfect for short-lived autonomous agent runs.

Handling Rate Limits and Edge Architecture

Fortnox, like all enterprise ERPs, enforces strict rate limits to protect its database. When building automated workflows, handling HTTP 429 (Too Many Requests) errors is a core requirement.

Factual note on rate limits: Truto does not retry, throttle, or apply backoff on rate limit errors. When Fortnox returns an HTTP 429, Truto passes that error directly to the caller. Truto normalizes the upstream rate limit information into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF specification.

If you are writing a custom orchestration script or using an agent framework, your client code is responsible for inspecting the ratelimit-reset header, applying a backoff strategy, and retrying the MCP tool call. Do not assume the infrastructure will magically absorb these errors.

flowchart TD
    A["Agent Calls Tool"] --> B["Truto MCP Router"]
    B --> C["Fortnox API"]
    C -- "HTTP 429 Too Many Requests" --> D["Truto Normalizes Headers"]
    D --> E["Pass 429 to Client"]
    E --> F["Client Parses 'ratelimit-reset'"]
    F --> G["Client Applies Backoff & Retries"]

Behind the scenes, Truto's MCP implementation is completely stateless at the edge. The token you provide is hashed and checked against a globally distributed Key-Value store, and tool schemas are built dynamically by cross-referencing Fortnox's API definitions with your specific filtering rules.

Moving to Production

Connecting ChatGPT to Fortnox manually is a great way to prototype workflows, but it doesn't scale to a multi-tenant B2B application.

If you are building an AI product that requires accessing your customers' Fortnox accounts, you cannot ask them to manually configure MCP servers in their own ChatGPT interfaces. You need to embed the authentication flow into your app, capture their OAuth credentials, and orchestrate the tool calls programmatically via an LLM framework (like LangChain or LlamaIndex) connected to a fleet of isolated MCP servers.

Truto handles the entire lifecycle - from the white-labeled OAuth consent screens to the secure storage of refresh tokens, to the dynamic generation of scoped MCP URLs.

Stop writing custom API wrappers and fighting with nested ERP schemas. Use Truto to instantly generate production-ready MCP tools for Fortnox and 100+ other enterprise APIs.

FAQ

Can I restrict ChatGPT to only read data from Fortnox?
Yes. When generating the MCP server in Truto, you can configure method filtering by passing `"methods": ["read"]`. This restricts the AI agent to only "get" and "list" operations, preventing it from creating or modifying records.
How does Truto handle Fortnox API rate limits?
Truto does not automatically retry or throttle rate limit errors. If Fortnox returns an HTTP 429, Truto passes the error back to the client while normalizing the rate limit headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) according to IETF specs. The caller is responsible for implementing retry and backoff logic.
How do I secure the MCP server URL?
Treat the generated MCP URL as a secret. For added security, you can enable `require_api_token_auth`, which forces the client to pass a valid Truto API token in the Authorization header. You can also configure an `expires_at` timestamp for temporary access.
Does ChatGPT need to know the specific Fortnox data schemas?
No. Truto dynamically translates Fortnox's API documentation into JSON-RPC schemas and injects them into the MCP tool definitions. ChatGPT reads these schemas to understand exactly what fields (like OrganisationNumber or InvoiceRows) are required.

More from our Blog