Working with Webhooks in Dynamics 365 Business Central

Webhooks is the way to get notified if an entity changes in Dynamics 365 Business Central. For general information about webhooks, see Push notifications via webhooks in Microsoft REST API Guidelines.

In the following replace the URL prefix for Dynamics 365 Business Central depending on environment following the guideline.

Register a webhook subscription

Using webhooks requires the client/subscriber to perform a handshake with Dynamics 365 Business Central to register the webhook subscription.

POST https://{businesscentralPrefix}/api/v2.0/subscriptions 
Content-type: application/json
{
  "notificationUrl": "https://{notificationUrl}",
  "resource": "/api/v2.0/companies(f64eba74-dacd-4854-a584-1834f68cfc3a)/customers",
  "clientState": "optionalValueOf2048"
}

Once the POST is issued against the subscription API to create the subscription, Dynamics 365 Business Central will issue a request to the notificationUrl, passing a validationToken parameter on the query string. Subscriber needs to perform the handshake by returning validationToken in the response body and provide status code 200.

If Dynamics 365 Business Central receives the response containing the validationToken, the subscription is registered and webhook notifications will be sent to the notificationUrl.

Important

Handshake is mandatory when creating a subscription and renewing a subscription. In both cases the client has to return the validationToken in the body with response code 200 OK.

Client state

Optionally clientState can be provided in the POST and PATCH requests bodies. clientState is included in the body of a webhook notification and can be used as an opaque token; a shared secret, enabling the subscriber to verify notifications.

Renewing the subscription

Subscriptions will expire after 3 days, if not renewed before. Subscriptions are renewed by issuing a PATCH request to the subscription.

PATCH https://{businesscentralPrefix}/api/v2.0/subscriptions({id}) 

PATCH requests a handshake, just like POST requests, meaning that a subscription cannot be renewed unless the client returns the validationToken in the body.

Subscription expiration time is listed in expirationDateTime property of the subscription.

Notifications and change types

Valid subscriptions push the notifications on every entity update.

Each notification sent to the subscriber (notificationUrl) can contain multiple notifications from different subscriptions. Here is a sample notification payload:

{
  "value": [
    {
      "subscriptionId": "webhookItemsId",
      "clientState": "someClientState",
      "expirationDateTime": "2018-10-29T07:52:31Z",
      "resource": "api/v2.0/companies(b18aed47-c385-49d2-b954-dbdf8ad71780)/items(26814998-936a-401c-81c1-0e848a64971d)",
      "changeType": "updated",
      "lastModifiedDateTime": "2018-10-26T12:54:20.467Z",
      "systemCreatedAt": "2017-01-23T00:24:31.766Z",
      "systemCreatedBy": "f2a5738a-44e3-ea11-bb43-000d3a2feca1",
      "systemModifiedAt": "2020-08-21T00:24:31.777Z",
      "systemModifiedBy": "f2a5738a-44e3-ea11-bb43-000d3a2feca1"
    },
    {
      "subscriptionId": "webhookCustomersId",
      "clientState": "someClientState",
      "expirationDateTime": "2018-10-29T12:50:30Z",
      "resource": "api/v2.0/companies(b18aed47-c385-49d2-b954-dbdf8ad71780)/customers(130bbd17-dbb9-4790-9b12-2b0e9c9d22c3)",
      "changeType": "created",
      "lastModifiedDateTime": "2018-10-26T12:54:26.057Z",
      "systemCreatedAt": "2017-01-23T00:24:31.766Z",
      "systemCreatedBy": "f2a5738a-44e3-ea11-bb43-000d3a2feca1",
      "systemModifiedAt": "2020-08-21T00:24:31.777Z",
      "systemModifiedBy": "f2a5738a-44e3-ea11-bb43-000d3a2feca1"
    },
    {
      "subscriptionId": "webhookCustomersId",
      "clientState": "someClientState",
      "expirationDateTime": "2018-10-29T12:50:30Z",
      "resource": "api/v2.0/companies(b18aed47-c385-49d2-b954-dbdf8ad71780)/customers(4b4f31f0-dc1c-4033-b2aa-ab03ca1d6ebc)",
      "changeType": "deleted",
      "lastModifiedDateTime": "2018-10-26T12:54:30.503Z",
      "systemCreatedAt": "2017-01-23T00:24:31.766Z",
      "systemCreatedBy": "f2a5738a-44e3-ea11-bb43-000d3a2feca1",
      "systemModifiedAt": "2020-08-21T00:24:31.777Z",
      "systemModifiedBy": "f2a5738a-44e3-ea11-bb43-000d3a2feca1"
    },    {
      "subscriptionId": "salesInvoice",
      "clientState": "someClientState",
      "expirationDateTime": "2018-10-20T10:55:01Z",
      "resource": "/api/v2.0/companies(7dbba574-5f69-4167-a43e-fb975045de15)/salesInvoices?$filter=lastDateTimeModified%20gt%202018-10-15T11:00:00Z",
      "changeType": "collection",
       "lastModifiedDateTime": "2018-10-26T12:54:30.503Z",
      "systemCreatedAt": "2017-01-23T00:24:31.766Z",
      "systemCreatedBy": "f2a5738a-44e3-ea11-bb43-000d3a2feca1",
      "systemModifiedAt": "2020-08-21T00:24:31.777Z",
      "systemModifiedBy": "f2a5738a-44e3-ea11-bb43-000d3a2feca1"
    }

  ]
}

Created, updated, and deleted identifies the state change for the entity. By collection Dynamics 365 Business Central sends a notification that many records have been created or changed. A filter is applied to the resource, enabling the subscriber to request all entities satisfying the filter.

Notifications are not sent immediately when the record changes. By delaying notifications, Dynamics 365 Business Central can ensure that only one notification is sent, even though the entity might have changed several times within a few seconds.

Note

If Dynamics 365 Business Central cannot reach the subscriber, several retries will be attempted over the next 36 hours. The subscriber must respond with following error codes: 408 - Request Timeout, 429 - Too Many Requests or any error in 500-599 range (5xx). If subscriber responds with any other code than listed, no retries will be attempted and the subscription will be deleted.

Unsubscribing

To remove a subscription, execute a delete request.

Supported entities

To get a list of webhook supported entitites, the following request can be issued. The $filter parameter ensures that only v2.0 APIs are returned. Filter can be removed or changed.

GET https://{businesscentralPrefix}/api/microsoft/runtime/beta/companies({{companyId}})/webhookSupportedResources?$filter=resource eq 'v2.0*' 
Content-type: application/json
{  
  "value": [
  {
      "resource": "v2.0/accounts"
  },
  {
      "resource": "v2.0/companyInformation"
  }......
  ]
}
accounts companyInformation countriesRegions
currencies customerPaymentJournals customers
dimensions employees generalLedgerEntries
itemCategories items journals
paymentMethods paymentTerms purchaseInvoices
salesCreditMemos salesInvoices salesOrders
salesQuotes shipmentMethods unitsOfMeasure
vendors

For Document APIs, a notification will be sent for the header if a change is made a to a line. E.g. a notification to a subscription for salesInvoice will be sent, if a change is made to a related salesInvoiceLine.

Custom APIs are also webhook-enabled and will be listed in webhookSupportedResources if Dynamics 365 Business Central is able to send notifications for the entity.

Note

Webhooks are not supported for APIs in the following cases:

  • The source table for the API page is a temporary table (SourceTableTemporary = true).
  • The API page has a composite key (for example, if ODataKeyFields consists of several fields or is missing, then the primary key for the source table consists of several fields).
  • The source table for the API page is a system table ("Table No." > 2000000000).
  • The API is declared through an API type query, for example, and not through an API type page.

Notes for on-premise

By default, a subscription lives for 3 days if it is not renewed. The value is specified in the CustomSettings.config file under the ApiSubscriptionExpiration entry. There is a maximum number of subscriptions specified in the ApiSubscriptionMaxNumberOfSubscriptions in the CustomSettings.config file.

See also

Subscription Resource Type
Get subscriptions
Create subscriptions
Update subscriptions
Delete subscriptions
Microsoft REST API Guidelines - Push notifications via webhooks