Fortnox API (experimental)

Download OpenAPI specification:Download

Introduction

Welcome to Fortnox dedicated portal for Alpha and Beta APIs!

This space is designed to provide early access to our latest API developments, allowing you to explore, experiment, and provide valuable feedback that helps shape the future of our API offerings.

Happy coding!

Getting Started

Access and Authentication

To use these APIs, you need to follow specific steps for authentication and access.

Detailed instructions can be found in the respective sections for Alpha and Beta APIs.

Documentation: Each API is thoroughly documented with detailed descriptions, example requests and responses, error handling guidelines, and more to help you get started quickly

Giving Feedback

Your feedback is crucial for us to improve and enhance our APIs. Please use the feedback mechanisms provided within the portal to share your thoughts, report issues, or suggest new features. Your input directly influences the development and stability of our APIs.

Best Practices

While using Alpha and Beta APIs, the same best practices apply, including rate limiting and error handling, to ensure a smooth and efficient integration experience.

You can read more about this in our Developer documentation and the stable API documentation.

Support

We are here to help you make the most out of our Alpha and Beta APIs.

Please reach out to us from the Developer guide on fortnox.se https://www.fortnox.se/developer/support

Thank you for participating in our Alpha and Beta API development. We look forward to your innovative implementations and valuable feedback as we strive to build APIs that meet your needs and exceed your expectations.

Alpha endpoints

About Alpha APIs

Alpha APIs are our cutting-edge, experimental APIs that are in the early stages of development. These APIs are provided to gather feedback and insights on new features and functionalities. As a result, Alpha APIs are subject to change and may experience occasional instability.

We encourage you to use these APIs to experiment and provide feedback, but please be aware of their experimental nature and plan their integration accordingly.

Please check each API for the best way to give feedback!

Retrieve a list of articles

Retrieves a list of articles. The articles are returned sorted by article number with the lowest number appearing first.

query Parameters
filter
string
Enum: "active" "inactive"

possibility to filter supplier invoices

articlenumber
string

filter by article number

description
string

filter by description

ean
string

filter by ean

suppliernumber
string

filter by supplier number

manufacturer
string

filter by manufacturer

manufacturerarticlenumber
string

filter by manufacturerarticlenumber

webshop
string

filter by web shop

lastmodified
string

filter by lastmodified

sortby
string
Enum: "articlenumber" "quantityinstock" "reservedquantity" "stockvalue"

field to sort returned list

Responses

Response samples

Content type
application/json
{
  • "Articles": [
    ]
}

Create an article

The created article will be returned if everything succeeded, if there was any problems an error will be returned.

Request Body schema: */*

to create

object (fortnox_ArticleV2)

Responses

Response samples

Content type
application/json
{
  • "Article": {
    }
}

Calculate the prices of all included articles in a bundle

This is a helper method to calculate the prices for all sub items in a bundle. Several bundles can be included in the same request, as separate rows, and be calculated at the same time.

Some properties are required for the price calculation to work:

  • The bundle row (the top row) must have a Price. This is the price of the bundle, which the prices of the sub items will be calculated from. The goal of the calculation is to make the sum of the prices of the sub items equal to this price.
  • Each sub item row must have an AmountInBundle and a SalesPriceInBundle. These values are necessary in order to determine how large part of the bundle's value the sub item represents, and what the price of the sub item must be.
  • If a sub item row has UserPrice set to true, the Price property must also be set. The Price property of the sub items is normally not used as input, but if the UserPrice flag is set, the provided Price will be used as the price of the sub item and not calculated. This works in the same way as if a sub item had a fixed price in the bundle.

This method can also (optionally) calculate the price of the price adjustment row of a bundle. To have the price adjustment row price calculated, an additional sub row having the PriceAdjustment property set to true must be included in the request. If a price adjustment row is provided, in order for its price to be calculated, the following properties must be set (in addition to the properties specified above):

  • The Quantity on all rows, the bundle row and the sub rows.
  • The Discount on the bundle row (if the bundle should be sold with a discount).

This method will only calculate the prices of the sub rows and return these prices in the response. No modifications will be made to any entities in the database.

Example: To add a bundle to an invoice, first get the bundle article from the article registry. Here you will find the sub items included in the bundle, and how many of each there are in a bundle.

GET /3/articles-v2/toolbox

Response (simplified):


 {
     "Article": {
     .
     .
     "Bundle": {
             "Comment": "",
             "PriceAdjustmentRow": {
                 .
                 .
             },
             "SubItems": [
                 {
                     "ArticleNumber": "hammer",
                     "Quantity": "2",
                     "FixedPrice": false
                 },
                 {
                     "ArticleNumber": "wrench",
                     "Quantity": "3",
                     "FixedPrice": false
                 }
             ]
         }
     }
 }
 

Then lookup the sales price for each of the included articles in the price list you intend to use on the invoice. This should always be the sales price for 1 unit of the article, if an article has more than one price, choose the price where "FromQuantity" is equal to 1 or the closest value below 1.

GET /3/prices/sublist/A/hammer

Response (simplified):


 {
     "Prices": [
          {
              "ArticleNumber": "hammer",
              "FromQuantity": 0,
              "PriceList": "A",
              "Price": 200
          }
     ]
 }
 

GET /3/prices/sublist/A/wrench

Response (simplified):


 {
     "Prices": [
          {
              "ArticleNumber": "wrench",
              "FromQuantity": 0,
              "PriceList": "A",
              "Price": 300
          }
     ]
 }
 

Now we have all the information we need to calculate the prices for the bundle. Let's assume that we want to sell this bundle for 1100 SEK, and that the customer bought 2 bundles. We also want the price adjustment to be calculated. We create a bundle price calculation request with the following properties:


 {
     "BundlePriceCalculation": {
         "Rows": [
             {
                 "Price": 1100,    // The price we want to set on the bundle
                 "Quantity": 2,   // The number of bundles sold (only required since we want to calculate the price adjustment row)
                 "Bundle": {
                     "SubRows": [
                         {
                             "Quantity": 4, // The number of hammers on the invoice. The bundle contains 2, but we sold 2 bundles.
                             "BundleSubItem": {
                                 "AmountInBundle": 2, // The amount of hammers in a bundle
                                 "SalesPriceInBundle": 200 // The sales price of the hammer
                             }
                         },
                         {
                             "Quantity": 6,
                             "BundleSubItem": {
                                 "AmountInBundle": 3,
                                 "SalesPriceInBundle": 300
                             }
                         },
                         {
                             "Quantity": 1,
                             "BundleSubItem": {
                                 "PriceAdjustment": true
                             }
                         }
                     ]
                 }
             }
         ]
     }
 }
 

We do the calculation by calling the endpoint with the request above:

POST /3/articles-v2/calculatebundleprices

Response (simplified):


 {
     "BundlePriceCalculation": {
         "Rows": [
             {
                 "Price": 1100,
                 "Quantity": 2,
                 "Bundle": {
                     "SubRows": [
                         {
                             "Price": 169.23,  // The price that the hammer should have on the invoice
                             "Quantity": 4,
                             "BundleSubItem": {
                                 "AmountInBundle": 2,
                                 "SalesPriceInBundle": 200
                             }
                         },
                         {
                             "Price": 253.85, // The price that the wrench should have on the invoice
                             "Quantity": 6,
                             "BundleSubItem": {
                                 "AmountInBundle": 3,
                                 "SalesPriceInBundle": 300
                             }
                         },
                         {
                             "Price": -0.02,  // The price to set on the price adjustment row
                             "Quantity": 1,   // Quantity is always 1 on a price adjustment row
                             "BundleSubItem": {
                                 "AmountInBundle": 0,
                                 "PriceAdjustment": true,
                                 "SalesPriceInBundle": 0
                             }
                         }
                     ]
                 }
             }
         ]
     }
 }
 

And there we have it. When we create our invoice, the price of the hammer should be set to 169.23 SEK, the price of the wrench must be set to 253.85 SEK, and the price adjustment row must be set to -0.02 SEK. The closest we could get to the desired price of 1100 SEK was 1100.01 SEK (2 * 169.23 + 3 * 253.85 = 1100.01 SEK), so the price for one bundle needed to be adjusted by -0.01 SEK. Since we calculated the price for 2 bundles, the total adjustment was -0.02 SEK.

Worth noting is that the prices for the articles in a bundle is always calculated based on exactly 1.0 bundle, the prices of the articles is not effected by the number of bundles sold. However, as seen in this example, the price adjustment might be. The same goes for discount. If a bundle is sold with a discount, the discount will not affect the calculated prices of the individual sub articles in the bundle, but it might affect the price on the price adjustment row.

Request Body schema: */*

the bundle price calculation to perform

object (fortnox_BundlePriceCalculation)

Responses

Response samples

Content type
application/json
{
  • "BundlePriceCalculation": {
    }
}

Delete an article

Deletes the article permanently.

You need to supply the unique article number that was returned when the article was created or retrieved from the list of articles.

path Parameters
ArticleNumber
required
integer <int32>

identifies the article

Responses

Response samples

Content type
application/json
{
  • "ErrorInformation": {
    }
}

Retrieve an article

Retrieves the details of an article. You need to supply the unique article number that was returned when the article was created or retrieved from the list of articles.

path Parameters
ArticleNumber
required
integer <int32>

identifies the article

Responses

Response samples

Content type
application/json
{
  • "Article": {
    }
}

Update an article

Updates the specified article with the values provided in the properties. Any property not provided will be left unchanged. You need to supply the unique article number that was returned when the article was created or retrieved from the list of articles. Note that even though the article number is writeable you can not change the number of an existing article.

path Parameters
ArticleNumber
required
integer <int32>

identifies the article

Request Body schema: */*

to update

object (fortnox_ArticleV2)

Responses

Response samples

Content type
application/json
{
  • "Article": {
    }
}

Retrieve a list of invoices

query Parameters
filter
string
Enum: "cancelled" "fullypaid" "unpaid" "unpaidoverdue" "unbooked"

possibility to filter invoices

costcenter
string
customername
string
customernumber
string
label
string
documentnumber
string
fromdate
string
todate
string
fromfinalpaydate
string
tofinalpaydate
string
lastmodified
string
notcompleted
string
ocr
string
ourreference
string
project
string
sent
string
externalinvoicereference1
string
externalinvoicereference2
string
yourreference
string
invoicetype
string
articlenumber
string
articledescription
string
currency
string
accountnumberfrom
string
accountnumberto
string
yourordernumber
string
credit
string
sortby
string
Enum: "customername" "customernumber" "documentnumber" "invoicedate" "ocr" "total"

field to sort returned list on

Responses

Response samples

Content type
application/json
{
  • "Invoices": [
    ]
}

Create an invoice

An endpoint for creating an invoice. While it is possible to create an invoice without rows, we encourage you to add them if you can. Omitted values in the payload will be supplied by Predefined values which can be edited in the Fortnox account settings. Note that Predefined values will always be overwritten by values provided through the API.

Should you have EasyVat enabled, it is mandatory to provide an account in the request should you use a custom VAT rate.

This endpoint can produce errors, some of which may only be relevant for EasyVat. Refer to the table below.

Errors that can be raised by this endpoint.
Error Code HTTP Code Description Solution
2004167 400 An account must be provided when using a custom VAT rate and EasyVat has been enabled. Supply each row which has a custom VAT rate with an account.

Note: The EuQuarterlyReport property will become obsolete at 2021-12-01. This property is currently used by the Quarterly report as one of the conditions that determine if an invoice should be included in the report or not. A new version of the Quarterly report is released at 2021-12-01. In the new report, this property will not be used when determining if an invoice should be included in the report or not, with one exception: if the invoice is created before 2021-12-01, and this property is false, the invoice will be excluded from the report. For invoices created 2021-12-01 and later, this property will have no effect.

Request Body schema: */*

payload

object (fortnox_InvoicePayloadV2)

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Retrieve a single invoice

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Update an invoice

Note that there are two approaches for updating the rows on an invoice.

If RowId is not specified on any row, the rows will be mapped and updated in the order in which they are set in the array. All rows that should remain on the invoice needs to be provided.

If RowId is specified on one or more rows the following goes: Corresponding row with that id will be updated. The rows without RowId will be interpreted as new rows. If a row should not be updated but remain on the invoice then specify only RowId like { "RowId": 123 }, otherwise it will be removed. Note that new RowIds are generated for all rows every time an invoice is updated.

Note: The EuQuarterlyReport property will become obsolete at 2021-12-01. This property is currently used by the Quarterly report as one of the conditions that determine if an invoice should be included in the report or not. A new version of the Quarterly report is released at 2021-12-01. In the new report, this property will not be used when determining if an invoice should be included in the report or not, with one exception: if the invoice is created before 2021-12-01, and this property is false, the invoice will be excluded from the report. For invoices created 2021-12-01 and later, this property will have no effect.

path Parameters
DocumentNumber
required
string

identifies the invoice

Request Body schema: */*

payload

object (fortnox_InvoicePayloadV2)

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Bookkeep an invoice

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Cancel an invoice

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Credit an invoice

The created credit invoice will be referenced in the property CreditInvoiceReference.

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Send an invoice as e-invoice

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Send an invoice as email

You can use the properties in the EmailInformation to customize the e-mail message on each invoice.

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Send an invoice as e-print

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Set an invoice as sent

Use this endpoint to set invoice as sent, without generating an invoice.

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Preview an invoice

The difference between this and the print-endpoint is that property Sent is not set to TRUE.

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Print an invoice

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Print an invoice as reminder

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Set an invoice as done

Used for marking a document as ready in the warehouse module. DeliveryState needs to be set to "delivery".

path Parameters
DocumentNumber
required
string

identifies the invoice

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Retrieve a list of offers

query Parameters
filter
string
Enum: "cancelled" "expired" "completed" "notcompleted" "ordercreated" "ordernotcreated"

possibility to filter offers

customername
string

filter by customer name

customernumber
string

filter by customer number

documentnumber
string

filter by document number

costcenter
string

filter by cost center

label
string

filter by label

fromdate
string

filter by from date

todate
string

filter by to date

project
string

filter by project

sent
boolean

filter by sent

notcompleted
boolean

filter by not completed

ourreference
string

filter by our reference

yourreference
string

filter by your reference

lastmodified
string

filter by last modified

sortby
string
Enum: "customerName" "id" "transactionDate" "total"

sort returned list of offers

Responses

Response samples

Content type
application/json
{
  • "Offers": [
    ]
}

Create an offer

An endpoint for creating an offer.

Should you have EasyVat enabled, it is mandatory to provide an account in the request should you use a custom VAT rate.

This endpoint can produce errors, some of which may only be relevant for EasyVat. Refer to the table below.

Errors that can be raised by this endpoint.
Error Code HTTP Code Description Solution
2004167 400 An account must be provided when using a custom VAT rate and EasyVat has been enabled. Supply each row which has a custom VAT rate with an account.

Request Body schema: */*

to create

object (fortnox_OfferPayloadV2)

Responses

Response samples

Content type
application/json
{
  • "Offer": {
    }
}

Retrieve a single offer

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Response samples

Content type
application/json
{
  • "Offer": {
    }
}

Update an offer

Note that there are two approaches for updating the rows on an offer.

If RowId is not specified on any row, the rows will be mapped and updated in the order in which they are set in the array. All rows that should remain on the offer needs to be provided.

If RowId is specified on one or more rows the following goes: Corresponding row with that id will be updated. The rows without RowId will be interpreted as new rows. If a row should not be updated but remain on the offer then specify only RowId like { "RowId": 123 }, otherwise it will be removed. Note that new RowIds are generated for all rows every time an offer is updated.

path Parameters
DocumentNumber
required
string

identifies the offer

Request Body schema: */*

to update

object (fortnox_OfferPayloadV2)

Responses

Response samples

Content type
application/json
{
  • "Offer": {
    }
}

Cancels given offer

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Response samples

Content type
application/json
{
  • "Offer": {
    }
}

Create invoice out of given offer

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Create order out of given offer

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Response samples

Content type
application/json
{
  • "Order": {
    }
}

Send given offer as email

You can use the properties in the EmailInformation to customize the e-mail message on each offer.

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Response samples

Content type
application/json
{
  • "Offer": {
    }
}

Set given offer as sent

Use this endpoint to set offer as sent, without generating an offer.

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Response samples

Content type
application/json
{
  • "Offer": {
    }
}

Preview given offer

The difference between this and the print-endpoint is that property Sent is not set to TRUE.

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Print given offer

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Retrieve a list of orders

query Parameters
filter
string
Enum: "cancelled" "expired" "invoicecreated" "invoicenotcreated"

possibility to filter orders

customername
string

filter by customer name

customernumber
string

filter by customer number

label
string

filter by label

documentnumber
string

filter by document number

externalinvoicereference1
string

filter by external invoice reference 1

externalinvoicereference2
string

filter by external invoice reference 2

fromdate
string

filter by from date

todate
string

filter by to date

costcenter
string

filter by cost center

project
string

filter by project

sent
boolean

filter by sent

notcompleted
boolean

filter by not completed

ourreference
string

filter by ourreference

yourreference
string

filter by your reference

lastmodified
string

filter by lastmodified

ordertype
string

filter by order type

sortby
string
Enum: "customername" "customernumber" "orderdate" "documentnumber" "total"

field to sort returned list

Responses

Response samples

Content type
application/json
{
  • "Orders": [
    ]
}

Create a new order

An endpoint for creating an order.

Should you have EasyVat enabled, it is mandatory to provide an account in the request should you use a custom VAT rate.

This endpoint can produce errors, some of which may only be relevant for EasyVat. Refer to the table below.

Errors that can be raised by this endpoint.
Error Code HTTP Code Description Solution
2004167 400 An account must be provided when using a custom VAT rate and EasyVat has been enabled. Supply each row which has a custom VAT rate with an account.

Request Body schema: */*

order to create

object (fortnox_OrderPayloadV2)

Responses

Response samples

Content type
application/json
{
  • "Order": {
    }
}

Retrieve a single order

path Parameters
DocumentNumber
required
string

identifies the order

Responses

Response samples

Content type
application/json
{
  • "Order": {
    }
}

Update an order

Note that there are two approaches for updating the rows on an order.

If RowId is not specified on any row, the rows will be mapped and updated in the order in which they are set in the array. All rows that should remain on the order needs to be provided.

If RowId is specified on one or more rows the following goes: Corresponding row with that id will be updated. The rows without RowId will be interpreted as new rows. If a row should not be updated but remain on the order then specify only RowId like { "RowId": 123 }, otherwise it will be removed. Note that new RowIds are generated for all rows every time an order is updated.

path Parameters
DocumentNumber
required
string

identifies the order

Request Body schema: */*

order to update

object (fortnox_OrderPayloadV2)

Responses

Response samples

Content type
application/json
{
  • "Order": {
    }
}

Cancels given order

path Parameters
DocumentNumber
required
string

identifies the order

Responses

Response samples

Content type
application/json
{
  • "Order": {
    }
}

Create invoice out of given order

path Parameters
DocumentNumber
required
string

identifies the order

Responses

Response samples

Content type
application/json
{
  • "Invoice": {
    }
}

Send given order as email

You can use the properties in the EmailInformation to customize the e-mail message on each order.

path Parameters
DocumentNumber
required
string

identifies the order

Responses

Response samples

Content type
application/json
{
  • "Order": {
    }
}

Set given order as sent

Use this endpoint to set order as sent, without generating an order.

path Parameters
DocumentNumber
required
string

identifies the order

Responses

Response samples

Content type
application/json
{
  • "Order": {
    }
}

Preview given offer

The difference between this and the print-endpoint is that property Sent is not set to TRUE.

path Parameters
DocumentNumber
required
string

identifies the offer

Responses

Print given order

path Parameters
DocumentNumber
required
string

identifies the order

Responses

Beta endpoints

About Beta APIs

Beta APIs represent a more stable state than Alpha APIs and are nearing completion for full production use. While they are still subject to changes based on user feedback and final adjustments, Beta APIs offer more reliability and completeness compared to their Alpha counterparts.

We highly value your feedback during this phase to fine-tune these APIs before they become part of our stable API suite.

Please check each API for the best way to give feedback!