Implementing common use cases

Home  ⫽ Examples

Posting a sales invoice

One of the most common use cases for Procountor API is posting sales invoices from an external system to Procountor. Assuming you have acquired an access token as described on the Getting started page, you can make requests to our endpoints listed on the API reference page.

The API reference shows which fields in the invoice model are optional. This example presents a minimalistic sales invoice with bank transfer as payment method. To that model, you can add optional fields according to your needs.

First, make sure you have set up a bank account in your Procountor environment. As we know, sales invoices with bank transfer as payment method require a bank account the buyer will pay the invoice to. The bank account can be set in Procountor by using the guided onboarding tool or navigating directly to the page called Bank account information. Regarding sales invoices, we refer to the buyer as the counter party of the invoice.

Request body

As can be seen in the documentation, the following JSON model represents a simple sales invoice:

  "type": "SALES_INVOICE",
  "status": "UNFINISHED",
  "date": "2017-05-01",
  "counterParty": {
    "counterPartyAddress": {
      "name": "Buyer name"
  "paymentInfo": {
    "paymentMethod": "BANK_TRANSFER",
    "currency": "EUR",
    "dueDate": "2017-05-26",
    "currencyRate": 1,
    "bankAccount": {
        "accountNumber" : "FI5542345670000081"
  "extraInfo": {
    "accountingByRow": false,
    "unitPricesIncludeVat": false
  "discountPercent": 0,
  "invoiceRows": [
      "product": "Coffee cup",
      "quantity": 2,
      "unit": "PIECE",
      "unitPrice": 3.5,
      "discountPercent" : 0,
      "vatPercent": 24
  "invoiceChannel": "NO_SENDING",
  "language" : "FINNISH"

Notice that every value of the invoice fields is validated. For example, value of the accountNumber field must represent a valid and existing bank account. In addition to that and general format validation rules, some validations depend on the settings of the current environment. In this example, that means the value of the vatPercent field must match the VAT (Value Added Tax) settings of your environment which in turn reflect the VAT regulations in your country.

Request headers

As stated on the General information page, requests to the API endpoints must be equipped with appropriate headers, including your access token. Now include the following headers to your request, with the access token replaced with our own:

Content-Type: application/json
Authorization: Bearer <access token>

Making the request

Make sure your HTTP request type is POST as reads in the documentation.


A response with HTTP status code 200 indicates a successful request. The response body contains the invoice model that was saved into Procountor database. Practically, you will receive the original invoice with a couple of ID fields added: invoiceId and ledgerreceiptId.

Posting a journal (ledger receipt)

Another common use for Procountor API is posting journals containing accounting data. As a prerequisite for using this feature, basic knowledge of accounting is assumed. For instance, choosing the correct vatStatus and the choice between CREDIT and DEBIT depends on the case.

Note that correct ledger accounts must be known before making the request. The chart of accounts for the current environment can be fetched by using the GET /coa endpoint.

Request body

The following represents a simple journal type ledger receipt (as of API v4):

  "type": "JOURNAL",
  "status": "UNFINISHED",
  "name": "Example journal",
  "receiptDate": "2017-03-20",
  "vatType": "PURCHASE",
  "vatStatus": 1,
  "transactions": [
      "transactionType": "REVERSING_ENTRY",
      "account": "1900",
      "accountingValue": -44,
      "vatPercent": 0
      "transactionType": "ENTRY",
      "account": "4000",
      "accountingValue": 44,
      "vatPercent": 0

Request headers and method

As with sales invoice. Supply the Content-type and Authorization headers and use the POST method.

Content-Type: application/json
Authorization: Bearer <access token>


The response with HTTP status code 200 will contain the assigned receiptId as well as other details, such as version timestamp, generated in Procountor. Should you like to add an attachment to the journal, use the invoiceId provided for linking as described in the API reference.

Adding an attachment to an invoice

Procountor API allows to attach files to certain resources, such as invoices and ledger receipts. These attachments can be accessed through the API or on the UI. The target resource must exist in Procountor prior to posting the attachment. In this example, let us assume we have an invoice with id 1234 and a JPG file named picture.jpg.

Request body

The request contains two parts: the file as file parameter value and the meta data as meta parameter value. The latter can be formatted as follows:

  "name": "Example picture.jpg",
  "referenceType": "INVOICE",
  "referenceId": 1234

Here are two things to notice. First, make sure you include the correct file extension to the attachment name. Otherwise, the attachment will not be shown correctly on the UI. Second, the mimeType field listed in the reference is determined based on the file extension. It is thus ignored when posting the attachment, but present in the response and when getting a particular attachment.

Request headers

As can be seen in the reference, the Content-Type for POST /attachments is multipart/form-data.

Content-Type: multipart/form-data
Authorization: Bearer <access token>

Making the request

The exact way of making this kind of request depends on the framework used for API calls. However, the example below presents how the request can be made with cURL:

curl -H "Authorization: Bearer <access token>" \
-F 'meta={"name": "Example picture.jpg", "referenceType": "INVOICE", "referenceId": 1234 } \
;type=application/json' \
-F "file=@picture.jpg" \

Type of the meta data (application/json) must be set for the request to work. CURL automatically sets the Content-Type of the request to multipart/form-data when using the -F option.


A successful request will result in a response with HTTP status code 200. The response contains both the meta data and the file sent. In addition to the fields posted, the meta data now includes an attachmentId generated by Procountor and the mimeType determined from the file extension.

Defining accounting information for invoices

To define accounting information such as ledger accounts, dimensions and VAT status for an invoice, first create an invoice as shown by the earlier example. The invoice returned by the server contains the ledgerreceiptId for the ledger receipt that was automatically generated to hold the accounting information of the invoice. To modify that accounting information, update the ledger receipt as follows:

Get the ledger receipt

Using the ledgerreceiptId, make a GET request to the /ledgerreceipts/{ledgerreceiptId} endpoint to get the ledger receipt in its current form.

Modify the ledger receipt

Modify the ledger receipt as required. For instance, you may add a vatStatus field to it or change the values of account fields in its transaction objects. Furthermore, transactions allow defining a value for dimensionItemValues field to assign dimension items and their values to a particular transaction:

"dimensionItemValues" : [
        "dimensionId": 12345,
        "itemId" : 678901,
        "value" : -7

Supply the modified ledger receipt

Use PUT /ledgerreceipts/{ledgerreceiptId} to supply the updated ledger receipt. Remember to include the original version timestamp to the request.

Calculating invoice sum

Procountor does not store separate "total sum" information for invoices. Always when a total sum is needed, it is calculated from invoice rows. Clients using the API must implement total sum calculation by themselves if they need the information.


The formula for calculating invoice row sums depends on the setting "unit prices include VAT". The corresponding property in ExtraInfo data model is unitPricesIncludeVat. In the formulas below, the round function rounds its argument to two decimal places.

Unit prices include VAT

The sum of an invoice row is calculated as follows:

Sum(InvoiceRow_n) = round(quantity * unitPrice * (1 - discountPercent / 100))

Unit prices do not include VAT

To calculate the sum of an invoice row:

  1. Calculate the row sum without VAT and round the sum to two decimal places.
  2. Calculate the amount of VAT based on the previous sum and round the amount to two decimal places.
  3. Add the amount of VAT to the row sum without VAT.

To formulate the steps above:

Sum(InvoiceRow_noVAT_n) = round(quantity * unitPrice * (1 - discountPercent / 100))
Sum(InvoiceRow_VAT_n) = round(Sum(InvoiceRow_n_noVAT) * (vatPercent / 100))

Sum(InvoiceRow_total_n) = Sum(InvoiceRow_noVAT_n) + Sum(InvoiceRow_VAT_n)

Invoice sum

The total sum of an invoice is the sum over all (rounded) invoice row sums:

Sum(Invoice) = Sum(InvoiceRow_total_1) + ... + Sum(InvoiceRow_total_N)

Calculating ledger receipt sum

As with invoices, Procountor does not store separate "total sum" information for ledger receipts. Always when a total sum is needed, it is calculated from receipt transaction rows. Clients using the API must implement total sum calculation by themselves if they need the information.


The sum of a ledger receipt transaction is calculated as follows:

Sum(Transaction_n) = round(accountingValue * (1 + vatPercent * 100))

Above, the round function rounds the sum to two decimal places. The total sum of the ledger receipt is the sum over all rounded transaction sums:

Sum(Receipt) = Sum(Transaction_1) + ... + Sum(Transaction_N)

In most cases, this sum should equal zero. Otherwise, the receipt does not reconcile and possibly requires a reconciliation row.

Receipt accounting value

The accounting value of a ledger receipt is defined as the sum of all positive rounded transaction sums.