REST APIs and the importance of Versioning.

REST API (also known as RESTful API) is an application programming interface that conforms to the constraints of REST architecture and it’s one of the main building block for integration between applicartions running in the cloud (but not only).

In a traditional Dynamics 365 Business Central project, it’s quite common to work with APIs for integrations and usually you can have the following:

  • APIs (standard and/or custom) exposed by Dynamics 365 Business Central extensions.
  • APIs exposed by your custom external solutions (like for example an external B2B website, an external web application or others).

During the evolution of a project you could have the need to modify an API. Changes in an API are quite often inevitable as our knowledge and experience of a system improve and managing the impact of these changes can be quite a challenge when it threatens to break existing client integration.

When modifying an API, you can potentially create breaking changes to existing applications. These breaking changes include:

  • a change in the format of the response data for one or more calls
  • a change in the request or response type
  • removing any part of the existing API.

Adding new endpoint to an existing API is not a breaking change.

API versioning is the practice of managing changes to an API and ensuring that these changes are made without disrupting clients. A good API versioning strategy clearly communicates the changes made and allows API consumers to decide when to upgrade to the latest version at their own pace.

When using APIs, versioning should not be an option but it’s a mandatory best practice in my opinion. Unfortunately, I see too often that this rule is not respected.

Versioning Dynamics 365 Business Central standard APIs

Dynamics 365 Business Central standard APIs supports versioning. To call a standard APIs in Dynamics 365 Business Central today, you need to send a request to the following endpoint:

https://api.businesscentral.dynamics.com/v2.0/production/api/v2.0

where the first v2.0 is the version of the online platform and the second v2.0 (in bold) is the API version.

When a new version of the standard APIs will be released in a future, Microsoft will increase that version number (and the previous endpoint will still be available but deprecated).

Versioning Dynamics 365 Business Central custom APIs

When defining a custom API page in Dynamics 365 Business Central, you need to specify an API version in the page definition:

and this version is reflected into the url for calling that API (url versioning):

/api/sd/finance/v1.0/companies(COMPANYID)/bankaccounts

If you need to change an API definition (creating breaking changes to existing consumers) you should handle versioning accordingly and then create a new API definition with a new version. Modifying an existing API definition is a breaking change (I see too many partners doing that)!!

Versioning your external custom APIs

Also if you design external custom APIs for your integrations, versioning is a must to handle. Here is probably is where I see the main chaos: lots of partners will not use versioning for custom-made APIs but they publish a single API to clients and then modify that APIs directly when needed.

This is not a best practice to do at all… you should always handle versioning also in your external custom-made APIs because it allows your API to evolve independently from the clients using it.

How to handle versioning in custom external APIs depends on the platform you’re using to build them. For example, as a .NET developer, to create REST APIs I often use ASP.NET Minimal APIs for example.

When creating an API project with this framework, versioning is not handled by default (so someone can forgot that). Handling versioning requires extra code, but this extra code is in my opinion a must to do

To handle versioning with ASP.NET Minimal API you need to add a reference to the Asp.Versioning.Http NuGet package:

Then in the Program.cs file of your API project, you can API versioning specification like in the following code:

In this code I’m specifying that the API has a default version as 1.0. With the AssumeDefaultVersionWhenUnspecified property set to true, the default API version will be used if the client has not specified an API version in the request.

The ApiVersionReader property is used to specify the key that will be used by the client to pass the API version to use when calling the API endpoints. Here I’m saying that the API version can be specifyed via query string (with the api-version parameter) or directly in the header of the http call by using the X-Version parameter.

Then with the VersionSet object I can define the supported versions for this API. Here I’m defining that the version 1.0 is deprecated and versiob 2.0 is the new supported version. You can create more than one supported version here.

Now in the API definition (here I’m using the standard project skelethon provided by Visual Studio that creates a /weatherforecast API) you can specify the API version supported by the endpoint:

Ass you can see from the above code, the /weatherforecast method in version 1.0 returns random temperature values from -20 to -1, while the /weatherforecast method in version 2.0 returns random values from 10 to 30.

In the VersionSet object definition I’m also using the ReportApiVersions property.

This property permits you to have the headers api-deprecated-versions and api-supported-versions parameters returned as part of responses, and these headers contain a comma separated list of supported/deprecated API versions.

Let’s do some tests…

If I execute the following Http GET call (no API version is specified):

GET {{baseaddress}}/weatherforecast/
Accept: application/json

The engine redirects the API call to the default API version (1.0 in my case) and so negative temperature numbers are returned as response:

In the response headers, you can see that the API returns the api.supported-versions and api-deprecated-versions parameters:

We can also call the API by specifying the API version in the query string:

GET {{baseaddress}}/weatherforecast?api-version=2.0
Accept: application/json

Here I’m calling the 2.0 version of the API and the response now gives positive temperature numbers:

As per the AddApiVersioning definition in the project previously explained, we can also call an API by passing the API version the header by using the specified X-Version parameter:

GET {{baseaddress}}/weatherforecast/
Accept: application/json
X-Version: 2.0

and the 2.0 endpoint will be called:

Also URL versioning (like in Dynamics 365 Business Central APIs) is supported by ASP.NET Minimal APIs. You can do that like in the following code:

And now you can call the version 2.0 of your API endpoint in the following way:

GET {{baseaddress}}/v2.0/weatherforecast
Accept: application/json

Nice and clean… 🙂

If you plan to have breaking changes in your APIs (despite their nature) please always use versioning. It requires a bit of code more, but at the end you will have a more robust solution…

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.