Key takeaways
- There is no native link between a Fortnox invoice and a HubSpot deal β you build the join yourself, on customer, value, and a date window.
- Marketplace connectors (e.g. Cloudify's Fortnox app, Resultify's) work well when the deal creates the invoice; less well when invoices already exist independently in Fortnox.
- A DIY API match needs an explicit HubSpot-company-to-Fortnox-customer-number mapping and a defined date/amount tolerance β both manual, both needing upkeep.
- Watch for partial and credit invoices, multi-currency amounts, and one-to-many deal/invoice relationships; a naive one-to-one join will silently misreport these.
- Whatever produces the final reconciled figure should be an explicit, re-runnable query β not a manually eyeballed spreadsheet.
Why the two records don't line up automatically
Fortnox invoices are accounting records: fields like customer number, invoice number, and balance, retrieved through the Fortnox API's Invoices resource. You can search on fields such as customer name, or filter by state β for example filter=unpaid for open invoices, combined with date-range parameters like fromdate and todate.
HubSpot deals carry commercial fields instead: deal name, deal stage, amount, and close date, linked to companies and contacts through an associations object. Amount is a deal property, but it is not required to create a deal β plenty of deals exist with no amount set at all.
HubSpot's own default deal properties include amount, currency, close date, and calculated fields like total contract value β but nothing for an external invoice number or a Fortnox customer reference.
The two systems simply share no common key out of the box. Whatever ties an invoice to a deal has to be built, not assumed.
Two ways teams actually build the match
Path A β a marketplace connector. Cloudify's "Fortnox β Accounting App for HubSpot", listed on HubSpot's own Marketplace, creates invoices and orders in Fortnox directly from HubSpot deals, syncs customers and products bidirectionally, and surfaces invoice and order status inside HubSpot. A comparable option, Resultify's Fortnox-to-HubSpot app, is listed in Fortnox's own integration directory. These work well when the deal is the source of the invoice β you generate the invoice from the deal. They work less well when invoices already exist independently in Fortnox (subscription billing, a different sales channel, manual entries) and need to be matched after the fact.
Path B β a scheduled matching workflow. Pull invoices from Fortnox's API, filtered by something like lastmodified or a fromdate/todate range, and pull deals from HubSpot's API with their company associations. Then join the two on a key you define yourself β typically the customer's name or organization number plus a value and a date tolerance, since there is no shared identifier to join on directly.
The workflow in practice β and its limits
A concrete version of Path B: (1) pull closed-won deals for the period, with their associated company and amount; (2) pull Fortnox invoices for the same period, with customer number, balance, and invoice number; (3) join on a customer-number match β mapped once, manually, from HubSpot company to Fortnox customer β combined with a value and date tolerance (say, invoice issued within 30 days of close date, amount within a defined margin); (4) output three lists: matched, deals with no invoice, and invoices with no deal.
Several things break this quietly if you don't name them upfront. Currency and rounding: a deal amount in HubSpot's deal currency won't necessarily equal the invoiced value in SEK once multi-currency accounts or line-item discounts are involved. Timing: an invoice can be issued weeks after a deal closes, or before it (deposit invoices), which breaks a fixed date window. Partial and credit invoices: a Fortnox invoice's balance and its cancelled status need explicit handling, or they read as false mismatches. Many-to-many relationships: one deal can map to several invoices (instalments), or one invoice can cover several deals β a naive one-to-one join misses both. And the weakest link is usually the mapping table itself: the manual HubSpot-company-to-Fortnox-customer-number list has to be built once and then kept current as customers change names or get merged.
Checklist before you trust the reconciled number
Confirm which HubSpot deal properties are actually populated on your deals β amount and currency are optional, not guaranteed.
Decide, explicitly, whether you're matching against invoice balance, invoice total, or a net-of-credit figure in Fortnox β these are not interchangeable.
Set a deliberate date tolerance between deal close and invoice issue, and write down why you chose it.
Build and version the HubSpot-company-to-Fortnox-customer mapping as its own artifact, not a one-off lookup buried in a script.
Always output the unmatched lists β deals without invoices and invoices without deals β as part of the result, not as a discarded byproduct.
Re-run the match on a schedule if the number is used more than once; a spreadsheet built once goes stale the day a customer record changes.
When a two-system match stops being enough
The moment you also need this reconciliation checked against a third source β bank payments, another CRM, a second invoicing system β or you want the same match to run weekly and land somewhere others can inspect, a script gluing two APIs together turns into brittle infrastructure that someone has to remember to run and fix. That's usually the point where teams look for a shared, governed home for the mapping and the join logic rather than another private script.
Ronja's Data Foundation is built around connecting existing systems like Fortnox and HubSpot without replacing them, and keeping the resulting mapping, modelling, and metrics as inspectable tables and queries rather than one-off code. Any financial figure it reports should come from an explicit query or program run against real data, checked against that engine's own output, not asserted. That said, connecting both systems changes nothing about the underlying work: you still need source permissions on each side, a defined mapping between customer records, and reconciliation logic that names its own assumptions β none of that becomes automatic just because both systems are connected to the same platform. This is a representative pattern, not a specific customer's measured result.
Sources
- Fortnox Developer β Parameters
- HubSpot Developers β Deals API guide
- HubSpot Knowledge Base β Default deal properties
- HubSpot Marketplace β Fortnox app by Cloudify
- Fortnox β Resultify integration listing
- Ronja β Data Foundation
- Ronja Docs β Deterministic by design
- Ronja News β Fortnox integration
Frequently asked questions
Can HubSpot store the Fortnox invoice number automatically?
Not by default. HubSpot's standard deal properties don't include an external invoice reference field. You'd add a custom property and populate it yourself via the API, or use one of the marketplace integrations that write Fortnox invoice data back onto the HubSpot record.
Can I filter Fortnox invoices to just the unpaid ones through the API?
Yes β the Invoices resource supports a filter parameter (for example filter=unpaid) alongside date-range parameters like fromdate and todate, so you can pull exactly the slice you need rather than the full invoice history.
Is the Amount field on a HubSpot deal reliable for matching against an invoice total?
Treat it as a starting point, not a guarantee. Amount isn't required when a deal is created, and where line items or multiple currencies are in use, it can diverge from properties like total contract value. Check which field your team actually populates before using it to validate reconciled totals. A monetary amount is not a reliable record-matching key.