Younium - Fortnox connector

Overview

The Fortnox integration connects Younium to Fortnox, a Swedish accounting system. It supports bidirectional synchronization of accounts, products, payment terms, currencies, exchange rates, cost centers, projects, and financial accounts, as well as automated invoice posting from Younium into Fortnox when invoices are posted.


Authentication

OAuth 2.0 (Standard Authorization)

The integration uses Fortnox's standard OAuth 2.0 authorization workflow. When activated, Younium requests access to the following Fortnox scopes:

  • Article
  • Customer
  • CostCenter
  • Currency
  • Settings
  • Bookkeeping
  • Invoice
  • Payment
  • Order
  • Price
  • Project

The OAuth flow works as follows:

  1. Younium builds an authorization URI using the configured Fortnox Client ID and a redirect URI pointing back to the Younium API (/api/fortnox/callback).
  2. The user is redirected to Fortnox to approve access.
  3. Fortnox redirects back to Younium with a one-time authorization code.
  4. Younium exchanges the authorization code for an access token and a refresh token.
  5. The access token expiration and refresh token expiration are stored. The access token is refreshed automatically before it expires (with a 5-minute buffer). The refresh token is treated as expiring after 31 days.

Activation and Deactivation

Activating the Integration

During activation, Younium performs the following setup steps automatically:

  • Creates a custom field on Account named Fortnox Customer Number (type: Text).
  • Creates a custom field list on Account named Fortnox Delivery Method populated with all available DefaultDeliveryType enum values.
  • Creates a custom field on Product named Fortnox Product Number (type: Text).
  • Creates a custom field on Charge named Fortnox Product Number (type: Text).
  • Creates a custom field on OrderProductCharge named Fortnox Product Number (type: Text).
  • Creates a custom field on Invoice named Fortnox Invoice Number (type: Text).
  • Creates a custom field on Country named Fortnox country (type: Text).
  • Creates a custom field list on Account named Fortnox Account VAT Type populated with the values: SEVAT, SEREVERSEDVAT, EUREVERSEDVAT, EUVAT, EXPORT.

The integration also subscribes or unsubscribes from the following application events depending on the settings configured:

  • InvoicePosted → triggers the fortnox-post-invoice action (controlled by the Post Invoices setting).

Deactivating the Integration

Deactivation removes the stored Fortnox settings and unsubscribes from both the InvoicePosted events.


Synchronization Jobs

All synchronization operations are available as scheduled background jobs. Each job checks that the integration is activated (access token is present) before running.

Job Display NameDirectionMinimum Repeat Interval
Import Fortnox accountsFortnox → YouniumNot set (no minimum)
Export Younium accounts to FortnoxYounium → Fortnox30 minutes
Import Fortnox productsFortnox → YouniumNot set
Import Fortnox cost centersFortnox → YouniumNot set
Import Fortnox projectsFortnox → YouniumNot set
Import Fortnox payment termsFortnox → YouniumNot set
Import Fortnox chart of accountsFortnox → YouniumNot set
Import Fortnox currenciesFortnox → Younium30 minutes
Import Fortnox exchange ratesFortnox → Younium30 minutes

All import jobs use incremental synchronization based on a LastModified timestamp stored in the Fortnox settings, querying Fortnox for records modified after LastModified - 1 day. Jobs that do not use LastModified filtering (currencies, exchange rates) always fetch the full list.


Importing Accounts (Fortnox → Younium)

Fetches all Fortnox customers modified since the last account sync date. For each customer, Younium retrieves the full customer record from Fortnox.

Behavior rules:

  • Inactive Fortnox customers that do not already exist in Younium are skipped entirely.
  • If the setting Synchronize Only New Entities is enabled, existing Younium accounts are not updated.
  • If a customer's currency does not exist in Younium, the import for that customer fails with a logged error and processing continues with the next customer.

Account Field Mapping (Fortnox → Younium)

Fortnox FieldYounium Field
NameAccount.Name
WWWAccount.Domain
VATNumberAccount.TaxRegistrationNumber
OrganisationNumberAccount.OrganizationNumber
CustomerNumberCustom field: Fortnox Customer Number
TermsOfPaymentAccount.DefaultPaymentTermId (matched by payment term Name)
OurReferenceAccount.SalesReference
YourReferenceAccount.YourReference
EmailInvoiceAccount.InvoiceEmailAddress
CurrencyAccount.CurrencyId (matched by currency Code)
Active (inverted)Account.Inactive
VATTypeCustom field: Fortnox Account VAT Type (see VAT type mapping below)
DefaultDeliveryTypes.InvoiceCustom field: Fortnox Delivery Method
AccountTypeAlways set to Customer

Invoice Address Field Mapping (Fortnox → Younium)

Fortnox FieldYounium Address Field
NameAddress.Name
Address1Address.Street
Address2Address.Street2
CityAddress.City
ZipCodeAddress.Zip
CountryCode (two-alpha ISO code)Address.CountryId (matched by Country.TwoAlphaCode)
Country (Fortnox country name string)Custom field Fortnox country on the matched Country record

The invoice address is always created or updated. It is set as Account.DefaultInvoiceAddress.

Delivery Address Field Mapping (Fortnox → Younium)

The delivery address is only created or updated if DeliveryAddress1 is not empty in Fortnox.

Fortnox FieldYounium Address Field
DeliveryNameAddress.Name
DeliveryAddress1Address.Street
DeliveryAddress2Address.Street2
DeliveryCityAddress.City
DeliveryZipCodeAddress.Zip
DeliveryCountryCode (two-alpha ISO code)Address.CountryId (matched by Country.TwoAlphaCode)
DeliveryCountry (Fortnox country name string)Custom field Fortnox country on the matched Country record

The delivery address, when created/updated, is set as Account.DefaultDeliveryAddress.

VAT Type Mapping

Younium AccountVatTypesFortnox CustomerVATType
SEVATSE_VAT
SEREVERSEDVATSE_ReversedVAT
EUREVERSEDVATEU_ReversedVAT
EUVATEU_VAT
EXPORTExport

Exporting Accounts (Younium → Fortnox)

Exports Younium accounts to Fortnox as customers. Only accounts where AccountType is not Prospect and Inactive is false are exported. If LastExportAccountSync is set, only accounts (or accounts with addresses) modified after that date are included.

Requirements: Each account must have a DefaultPaymentTerm and a Currency assigned. If either is missing the account is skipped with a logged error.

Behavior:

  • If the account does not yet have a value in the Fortnox Customer Number custom field, it is created as a new Fortnox customer and the returned CustomerNumber is written back to the custom field.
  • If the account already has a Fortnox Customer Number, it is updated in Fortnox.
  • When updating an existing customer, any field that is null or empty in Younium is sent to Fortnox as API_BLANK (a special sentinel value that instructs the Fortnox API to clear that field).
  • When creating a new customer, null/empty fields are sent as-is (not replaced with API_BLANK).

Account Field Mapping (Younium → Fortnox)

Younium FieldFortnox Field
Account.NameCustomer.Name
Account.DefaultInvoiceAddress.StreetCustomer.Address1
Account.DefaultInvoiceAddress.Street2Customer.Address2
Account.DefaultInvoiceAddress.ZipCustomer.ZipCode
Account.DefaultInvoiceAddress.CityCustomer.City
Account.DefaultInvoiceAddress.Country.TwoAlphaCodeCustomer.CountryCode
Account.DefaultDeliveryAddress.StreetCustomer.DeliveryAddress1
Account.DefaultDeliveryAddress.Street2Customer.DeliveryAddress2
Account.DefaultDeliveryAddress.ZipCustomer.DeliveryZipCode
Account.DefaultDeliveryAddress.CityCustomer.DeliveryCity
Account.DefaultDeliveryAddress.Country.TwoAlphaCodeCustomer.DeliveryCountryCode
Account.InvoiceEmailAddressCustomer.EmailInvoice
Account.InvoiceEmailCcAddressesCustomer.EmailInvoiceCC
Account.DefaultPaymentTerm.NameCustomer.TermsOfPayment
Account.SalesReferenceCustomer.OurReference
Account.YourReferenceCustomer.YourReference
Account.TaxRegistrationNumberCustomer.VATNumber
Account.OrganizationNumberCustomer.OrganisationNumber
Account.Currency.CodeCustomer.Currency
Account.Inactive (inverted)Customer.Active
Custom field Fortnox Account VAT TypeCustomer.VATType (see VAT type mapping above)
Custom field Fortnox Delivery MethodCustomer.DefaultDeliveryTypes.Invoice
Always CompanyCustomer.Type

Delivery Method fallback: If the account does not have the Fortnox Delivery Method custom field set, the export falls back to mapping Younium's native InvoiceDeliveryMethod field as follows:

Younium InvoiceDeliveryMethodFortnox DefaultDeliveryType
EmailEmail
PrintPrint
ElectronicInvoiceElectronicInvoice
ExternalPrintPrintService

Importing Products (Fortnox → Younium)

Fetches all active Fortnox articles modified since the last product sync. Each article is matched to a Younium product by the custom field Fortnox Product Number.

Behavior:

  • If no matching product exists, a new product is created with a single default charge plan and a single default charge.
  • If a matching product exists, the product, its first charge plan, and the first charge on that charge plan are updated.
  • If a product previously synced from Fortnox is no longer present in the active articles list, its EndOfNewSalesDate is set to today's date.
  • The Fortnox Product Number custom field is set on both the Product and the Charge.
  • The ProductType is always set to Simple.
  • EndOfNewSalesDate is always cleared (set to null) when the product is active in Fortnox.

Product Field Mapping (Fortnox → Younium)

Fortnox FieldYounium Field
ArticleNumberCustom field Fortnox Product Number on Product and Charge
DescriptionProduct.Name, ChargePlan.Name, Charge.Name

Importing Payment Terms (Fortnox → Younium)

Fetches all Fortnox terms of payment modified since the last payment term sync.

Payment Term Field Mapping (Fortnox → Younium)

Fortnox FieldYounium FieldNotes
CodePaymentTerm.NameUsed as the unique match key
DescriptionPaymentTerm.Description 
Code (parsed as integer)PaymentTerm.DaysParsed as an integer; defaults to 0 if not parseable
Always NetDaysPaymentTerm.TermType 

Existing payment terms are updated if the description or days value differs.


Importing Chart of Accounts (Fortnox → Younium)

Fetches all Fortnox accounts modified since the last chart of accounts sync and creates or updates Younium financial accounts.

Financial Account Field Mapping (Fortnox → Younium)

Fortnox FieldYounium FieldNotes
NumberFinancialAccount.CodeUsed as the unique match key; accounts without a number are skipped
DescriptionFinancialAccount.NameUpdated if changed

Importing Currencies (Fortnox → Younium)

Fetches all currencies from Fortnox (no LastModified filter). New currencies not already present in Younium (matched by Code, case-insensitive) are created.

Currency Field Mapping (Fortnox → Younium)

Fortnox FieldYounium Field
CodeCurrency.Code
DescriptionCurrency.Description

Importing Exchange Rates (Fortnox → Younium)

Fetches all currencies from Fortnox and uses the BuyRate and Date fields on each currency to create exchange rate records in Younium. The base currency (configured in Younium) is skipped. Exchange rates are always stored as conversions to SEK.

Behavior:

  • If an open (no EffectiveToDate) exchange rate already exists for the same currency pair and the Fortnox date is more recent, the existing rate is closed (its EffectiveToDate is set to the day before the Fortnox date) and a new rate is created from the Fortnox date.
  • If no open rate exists, the system checks for the most recently closed rate and creates a new rate starting from the Fortnox date (or the day after the last closed rate's end date, whichever is later).
  • If no rates exist at all for the currency, a new rate is created starting from the Fortnox date.

Exchange Rate Field Mapping (Fortnox → Younium)

Fortnox FieldYounium Field
CodeCurrencyExchangeRate.FromCurrency (matched by code)
Always SEKCurrencyExchangeRate.ToCurrency
BuyRateCurrencyExchangeRate.Rate
DateCurrencyExchangeRate.EffectiveFromDate

Importing Cost Centers (Fortnox → Younium)

Fetches all Fortnox cost centers modified since the last cost center sync. Only active cost centers are imported. Cost centers are stored as items in a custom field list shared between a configured invoice custom field and invoice line custom field. New cost centers are added only if their Code does not already exist in the list (case-insensitive match).

Prerequisite: The settings must have both CostCenterCustomField (for invoices) and InvoiceLineCostCenterCustomField (for invoice lines) configured, and both must point to the same underlying custom field list.

Cost Center Field Mapping (Fortnox → Younium)

Fortnox FieldCustom Field List Item Field
CodeKey
DescriptionValue

Importing Projects (Fortnox → Younium)

Fetches all Fortnox projects modified since the last project sync. Projects are stored as items in a custom field list shared between a configured invoice custom field and invoice line custom field. New projects are added only if their ProjectNumber does not already exist in the list (case-insensitive match).

Prerequisite: The settings must have both ProjectCustomField (for invoices) and InvoiceLineProjectCustomField (for invoice lines) configured, and both must point to the same underlying custom field list.

Project Field Mapping (Fortnox → Younium)

Fortnox FieldCustom Field List Item Field
ProjectNumberKey
DescriptionValue

Invoice Posting (Younium → Fortnox)

When an invoice is posted in Younium (the InvoicePosted event fires) and the Post Invoices setting is enabled, the invoice is automatically sent to Fortnox.

Prerequisites:

  • The invoice's account must have a value in the Fortnox Customer Number custom field. If this is missing, the posting fails with an error: "Invoice account is not present in Fortnox. Please check if the account is synched from Fortnox into Younium."
  • The invoice must have 2000 or fewer invoice rows after expansion. If it exceeds this limit, the posting fails.

Invoice Field Mapping (Younium → Fortnox)

Younium FieldFortnox Invoice Field
Custom field Fortnox Customer Number on AccountCustomerNumber
Invoice.TotalAmount.CurrencyCodeCurrency
Invoice.InvoiceDateInvoiceDate
Invoice.DueDateDueDate
Invoice.Notes (see remarks logic below)Remarks
Invoice.YourReferenceYourReference
Invoice.OurReferenceOurReference
Invoice.YourOrderNumberYourOrderNumber
Invoice.InvoiceAddress.StreetAddress1
Invoice.InvoiceAddress.Street2Address2
Invoice.InvoiceAddress.CityCity
Invoice.InvoiceAddress.ZipZipCode
Custom field Fortnox country on Invoice.InvoiceAddress.CountryCountry
Invoice.DeliveryAddress.NameDeliveryName
Invoice.DeliveryAddress.StreetDeliveryAddress1
Invoice.DeliveryAddress.Street2DeliveryAddress2
Invoice.DeliveryAddress.CityDeliveryCity
Invoice.DeliveryAddress.ZipDeliveryZipCode
Custom field Fortnox country on Invoice.DeliveryAddress.CountryDeliveryCountry
Order custom field deliverydate (case-insensitive)DeliveryDate
Invoice.Id (as string)ExternalInvoiceReference1

After successful creation in Fortnox, the Fortnox DocumentNumber is written back to the Fortnox Invoice Number custom field on the Younium invoice, and also stored in Invoice.ExternalERPId.

Remarks / Notes Logic

The Remarks field in Fortnox is populated from Invoice.Notes. If the Map Renewal Text On Invoice setting is enabled and the invoice has an associated order that is auto-renewed, termed, active, and has an EffectiveEndDate, the following text is appended to the remarks (with a newline separator if notes already exist):

The current subscription term ends on YYYY-MM-DD

The subscription is automatically renewed at the end of the subscription period.

EU Quarterly Report

If the Map EU Quarterly Report setting is enabled, the integration fetches the full Fortnox customer record and sets EUQuarterlyReport = true on the invoice if the customer's VATType is EU_ReversedVAT.

Invoice Line Ordering

Invoice lines are sent to Fortnox in the following fixed order, regardless of any other sorting:

  1. All recurring and usage charge lines, ordered by OrderProduct.ProductLineNumber ascending, then by OrderProductCharge.ChargeNumber ascending.
  2. All one-off charge lines, ordered by OrderProduct.ProductLineNumber ascending, then by OrderProductCharge.ChargeNumber ascending.

Invoice Row Field Mapping (Younium → Fortnox)

For each invoice line, Fortnox invoice rows are created as follows:

Standard Invoice Row

Younium FieldFortnox InvoiceRow Field
Custom field Fortnox Product Number on OrderProductChargeArticleNumber
InvoiceLine.ChargeDescriptionDescription
Calculated quantity (see pricing logic)DeliveredQuantity
Calculated unit price (see pricing logic)Price
Calculated discount percent (see pricing logic)Discount
Always PercentDiscountType
Sum of TaxItems.TaxRate × 100, cast to integerVAT
Resolved project key (see project/cost center below)Project
Resolved cost center key (see project/cost center below)CostCenter

Tiered Charge Line Handling

If an invoice line's OrderProductCharge has CreateInvoiceLinesPerTier = true and ChargeModel = Tiered, the line is expanded into separate rows per tier:

  • Only tiers where FromQuantity <= absolute(InvoiceLine.Quantity) are included, ordered by Tier ascending.
  • If the summed tiered amount equals InvoiceLine.Subtotal.Amount, one row per applicable tier is created with:
    • DeliveredQuantity = tier quantity
    • Description = {ChargeDescription}, {tier.Description}
    • Price = tier.Price.Amount × discountPercent
    • No Discount or DiscountType fields set.
  • If the summed tiered amount does not equal InvoiceLine.Subtotal.Amount, a single fallback row is created with:
    • DeliveredQuantity = 1
    • Price = InvoiceLine.Subtotal.Amount

Automatic Description Row

After each invoice line's main row(s), an additional description-only row is added (with no price, quantity, or article number) except for one-off charges with ChargeModel = Quantity. The description row contains:

  • The formatted quantity (formatted as 0.##, removing trailing zeros) if present, followed by a space.
  • The unit of measure DisplayName if present, followed by a space.
  • If both a service period start and end date exist: appended as YYYY-MM-DD to YYYY-MM-DD (preceded by , if a quantity was also present).

This row is only added if either a quantity or a service period is present.

Notes Rows

If the invoice line has a Notes value, additional description-only rows are appended after the description row. The notes are split on newline characters (\\n), and each resulting line is further split into chunks of 255 characters (the maximum Fortnox accepts per row description). Each chunk becomes a separate invoice row with only a Description field set.

Project and Cost Center on Invoice Lines

If the Use Project setting is enabled, the integration resolves the project for each invoice line as follows:

  1. Reads the custom field on the invoice line named by the setting InvoiceLineProjectCustomField.
  2. Looks up the custom field list item whose Value matches the custom field's value, within the list referenced by that field's configuration (LookupReference).
  3. Uses the list item's Key as the Project value on the Fortnox invoice row.

If the Use Cost Center setting is enabled, the same process is applied using InvoiceLineCostCenterCustomField, and the resolved Key is used as CostCenter on the invoice row.

Project and Cost Center on the Invoice Header

If the Use Project setting is enabled, the integration also resolves a project for the invoice header using the same lookup logic but against the invoice-level custom field named by the setting ProjectCustomField. The resolved Key is set on fortnoxInvoice.Project.

If the Use Cost Center setting is enabled, the same applies using CostCenterCustomField, setting fortnoxInvoice.CostCenter.


Invoice Accrual (Fortnox Accrual)

If the Use Fortnox Accrual setting is enabled, the integration creates a Fortnox invoice accrual (InvoiceAccrual) after successfully creating the invoice in Fortnox.

Important: If accrual creation fails, the invoice already created in Fortnox is cancelled automatically.

Eligibility

Only invoice lines where the associated OrderProductCharge.RevenueRecognitionRule.RevenueRecognitionMethod equals MonthlyRecognitionOverTime are included in the accrual.

If no eligible lines exist, no accrual is created.

Requirements

  • All eligible invoice lines must have the same project dimension value (if Use Project is enabled). If they differ, the posting fails before the invoice is created in Fortnox.
  • All eligible invoice lines must have the same cost center dimension value (if Use Cost Center is enabled). If they differ, the posting fails before the invoice is created in Fortnox.
  • Each eligible line's OrderProductCharge must have both a DeferredRevenue.Code and a RecognizedRevenue.Code. Both codes must be parseable as numeric-only values (no alphabetic characters); Fortnox does not accept alphabetic account codes.

Accrual Calculation

  • Accrual amount: Sum of Subtotal.Amount across all eligible lines, converted to SEK using the Fortnox invoice's CurrencyRate (defaulting to 1 if not provided). Rounded to 2 decimal places using MidpointRounding.AwayFromZero.
  • Start date: First day of the month containing the earliest ServicePeriodStartDate across eligible lines.
  • End date: Last day of the month containing the latest ServicePeriodEndDate across eligible lines.
  • Monthly amount: accrualAmount ÷ number of months between start and end date. Rounded to 2 decimal places using MidpointRounding.AwayFromZero.
  • Period: Always MONTHLY.

Accrual Field Mapping (Younium → Fortnox)

ValueFortnox InvoiceAccrual Field
DeferredRevenue.Code (as long integer)AccrualAccount
RecognizedRevenue.Code (as long integer)RevenueAccount
First day of month of min ServicePeriodStartDateStartDate
Last day of month of max ServicePeriodEndDateEndDate
Sum of eligible line subtotals × CurrencyRateTotal
Fortnox DocumentNumberInvoiceNumber
Always MONTHLYPeriod
"Periodisering av kundfaktura {DocumentNumber} från Younium"Description

Two InvoiceAccrualRow entries are created:

RowAccountDebitCreditCostCenterProject
Accrual rowAccrualAccountmonthlyAmount0Resolved cost center keyResolved project key
Revenue rowRevenueAccount0monthlyAmountResolved cost center keyResolved project key

Custom Fields Created by the Integration

The following custom fields are created automatically when the integration is set up. They should not be renamed or deleted, as they are referenced by name in the integration logic.

EntityCustom Field NameTypeNotes
AccountFortnox Customer NumberTextStores the Fortnox customer number
AccountFortnox Delivery MethodListPopulated with Fortnox delivery type values
AccountFortnox Account VAT TypeListPopulated with: SEVAT, SEREVERSEDVAT, EUREVERSEDVAT, EUVAT, EXPORT
ProductFortnox Product NumberTextStores the Fortnox article number
ChargeFortnox Product NumberTextStores the Fortnox article number
OrderProductChargeFortnox Product NumberTextUsed when creating invoice rows
InvoiceFortnox Invoice NumberTextWritten back after successful posting
CountryFortnox countryTextStores the Fortnox country name string (used on invoice addresses, as Fortnox does not accept country codes on invoices)

Related to