Webhooks (Beta)

❗️

Sandbox beta not operational

Webhooks is currently in beta stage and only exist in our Sandbox environment. Therefore, this functionality is subject to change at any time and we do not guarantee any backwards compability at this time. Please try this functionality out, if you have any questions or feedback, don't hesitate to let us know at [email protected].

Webhooks are no longer operational in Sandbox and you will be informed on this page if or when new information is available.

Webhooks will let your subscribe to events in Visma eAccounting, notifying you whenever a event is triggered within your subscription. We will send a HTTP POST payload to the URL configured in your subscription.

With webhooks we will inform you when customer data changes so you don't have to poll us anymore. It will increase the efficiency and make your apps upp to date, in real time!

Events

Our events are represented by the most used entities in Visma eAccounting:

Event name

Description

Article

Triggered whenever a article is created, changed or deleted

Customer

Triggered whenever a customer is created, changed or deleted

CustomerInvoice

Triggered whenever a customer invoice is created or changed

CustomerInvoiceDraft

Triggered whenever a customer invoice draft is created, changed or deleted

Order

Triggered whenever an order is created, changed or deleted

Supplier

Triggered whenever a supplier is created, changed or deleted

SupplierInvoiceDraft

Triggered whenever a supplier invoice draft is created, changed or deleted

Quote

Triggered whenever a quote is created, changed or deleted

Voucher

Triggered whenever a voucher is created, changed or deleted

WebshopOrder

Triggered whenever a web shop order is created, changed or deleted

Account

Triggered whenever a bookkeeping Account is\ created, changed or deleted

FiscalYear

Triggered whenever a fiscal year is\ created, changed or deleted

CostCenter

Triggered whenever a cost center is\ created, changed or deleted

CostCenterItem

Triggered whenever a cost center item is\ created, changed or deleted

..more to come

..more to come

Webhooks And Subscriptions

As a third party application provider, you generally have more than one customer. The webhook and its subscriptions are in the context of a single Visma eAccounting customer, heres a illustration of how a multiple customer webhook setup looks like:

This setup allows you to set up your webhooks and subscriptions however you like. If you want one webhook per subscription - fine! If you want one webhook per customer with all subscriptions gathered under the same webhook - also fine!

As of the time being, webhooks and subscriptions are managed through the eAccounting API, within the /v2/webhooks endpoints. The following endpoints are available:

URL

Description

GET /v2/webhooks

Gets all webhooks for the authenticated company with standard pagination

GET /v2/webhooks/{webhookId}

Gets a single webhook

POST /v2/webhooks

Posts a webhook with subscriptions.

PUT /v2/webhooks/{webhookId}

Updates a single webhook with subscriptions

DELETE /v2/webhooks/{webhookId}

Deletes a single webhook with subscriptions

The request payload when posting or replacing a webhook with subscription looks like this:

Name

Description

Required

Read Only

Data Type

Identifier

Unique Identifier of the entity in the notification

false

true

Guid

Endpoint

Callback URL that we will post subscribed events to. HTTPS is required

true

false

String (With URL validation)

Description

Internal description for you

false

false

string

ClientId

Your Client Id

false

true

string

AuthenticationKey

If you want authentication on your notifications, provide header name here

false

false

string

AuthenticationValue

If you want authentication on your notifications, provide header value here

false

false

string

SigningKey

If provided, we will sign the payload with this key

false

false

string

Active

Set this to true if you want to activate this webhook and its subscriptions. If false, it will be saved and prepared but inactive. Default is false

false

false

bool

Subscriptions

Your webhook subscriptions. List each entity you want to subscribe to

true

false

Array

CreatedUtc

Timestamp when webhook was created

false

true

DateTime

ModifiedUtc

Timestamp when webhook was latest modified

false

true

DateTime

If you POST or PUT a webhook with Active set to true, we'll make a test request towards your registered endpoint. If you don't reply with a status code in the 200-299 range, we'll reply with a Bad Request (400). Therefore, you should have your webhook endpoint ready before posting it.

Authentication and Signing

We strongly recommend you to provide authentication and signing key to bump up the security on your webhook traffic. The AuthenticationKey represents the header name. The standard name "Authorization" works prefectly fine, but if you want to provide a header name of your own, feel free to do so. AuthenticationValue represents the header value.

We also offer the possibility for you to provide a signing key. Before sending the webhook, we combine the notification properties Action, Entity, Identifier, ModifiedUtc and Url with a delimiter consisting of a under score (_) into a string and use SHA-256 with your provided cryptographic signing key to generate a hash signature.

Here's a example of how the raw string combination looks like:

Update_Article_4584be5b-71a7-41e4-b181-c2d775a132ac_2035-05-15T11:24:25.3052213Z_https://eaccountingapi.vismaonline.com/v2/articles/4584be5b-71a7-41e4-b181-c2d775a132ac

We send that hash signature in a header named X-Hub-Signature with a value of sha1=[hash].

When receiving the webhook on your end, save the signature. Create the same string as shown above based on the property values of the incoming webhook. Use the same SHA-256 cryptography to calculate a hash on your own. Compare each byte in the array with the one we provide. If each byte is alike, your data is untouched and safe. Here's a code example on how to verify the signature in C#:

using System;
using System.Security.Cryptography;
using System.Text;

namespace Example
{
  public class VerifySignature
  {
    private const string signingKeyString = "ThisIsABadKey";
      
    public void Verify(WebHookDto webHook, string signatureHeaderValue)
    {
      string stringToVerify = $"{webHook.Action}_{webHook.Entity}_{webHook.Identifier}_{webHook.ModifiedUtc}_{webHook.Url}";
      
      UTF8Encoding encoding = new UTF8Encoding(false);
      byte[] signingKeyByteArray = encoding.GetBytes(signingKeyString);
      byte[] signature = Convert.FromBase64String(signatureHeaderValue);
      byte[] hash;
      
      using (HMACSHA256 hmac = new HMACSHA256(signingKeyByteArray))
      {
        hash = hmac.ComputeHash(encoding.GetBytes(stringToVerify));
      }
      
      for (int i = 0; i < hash.Length; i++)
      {
        if (hash[i] != signature[i])
        {
      	  throw new Exception("Invalid payload");
        }
      }
    }
  }
}

Notifications

When you have a active webhook with subscriptions, we'll notify you when that entity is changed in Visma eAccounting. A notification look like this:

Name

Description

Data Type

Identifier

Unique Notification Id provided by eAccounting

Guid

VismaCustomerId

Unique Visma Customer Id provided by eAccounting

Guid

Entity

Name of the entity

String

Action

Type of action (Created/Changed/Deleted)

String

Url

eAccounting API URL to fetch entity changes

String

ModifiedUtc

Unique time stamp of the notification

DateTime

RetryAttempt

Attempt number. Starts with 0

Int

Retry Policy

We understand that services can be unresponsive some times. Our retry policy takes care of that for you. If you don't reply to our notification requests with a status code in the 200-299 range, we'll interpret that as a failed request. We will try to send the notification again, incrementing the RetryAttempt property once. We will make five attempts on each notification before deleting it. Each attempt will be delayed according to this schedule:

Retry Attempt

Delay Added In Seconds

Information

1

1

2

17

3

300

4

5000

5

86400

Notification will be deleted after this attempt and webhook will be disabled.

The best way to make sure you don't lose any notifications is to store them in a local queue directly, reply to us with a successful statuscode, then have code listening to the queue and act accordingly. This means your main service could be having downtime, but as long as your queue endpoint is responding, you'll have all your notifications on your end. If you don't respond after all our retries, the webhook will be inactivated automatically. If this was unintentional from your end, just activate the webhook again and it's up and running!