14 July 2019

Too many requests reached

What is the maximum number of API requests Microsoft Dynamics 365 Business Central can handle within a one minute? 

Ran into this question a couple of months ago, specifically soon after the April release. Most of our Azure Logic Apps integrations to Microsoft Dynamics 365 Business Central started to fail due to API endpoint changes

Logic Apps were kept on failing every time it tries to push the data into the MSDYN365BC. Initially, the error was related to URI.


1
2
3
4
5
6
{
    "error": {
        "code": "BadRequest_NotFound",
        "message": "The request URI is not valid. Since the segment 'customers' refers to a collection, this must be the last segment in the request URI or it must be followed by an function or action that can be bound to it otherwise all intermediate segments must refer to a single resource."
    }
}

After a while error message changed into "Too many requests reached".

1
2
3
4
5
6
7
{
  "error": {
    "code": "Application_TooManyRequests",
    "message": "Too many requests reached.  Actual (101).  Maximum (100)."

  }
}

So there is a limit! What is the limit and why there is a limit? To get an answer to all these questions we request support from Microsoft. While we wait for an answer from Microsoft we found the answer to our questions from Microsoft Docks: Business Central (Preview)

The document is related to the Business Central Connector and it specifically mentioned that Microsoft Dynamics 365 Business Central can ONLY handle 100 API calls per minute




The limit is enforced mainly to avoid DoS attacks (denial-of-service attack) and to make sure Microsoft Business Central runs smoothly. Too many API requests can bring the product to its knees causing a probable outage.

I suggest you read the "API Limits" article by Microsoft If you are working on the D365 integrations. Even though the article does not directly talk about BC, all the rules discuss it does apply to the BC as well.

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

PowerShell: Run Script Error: Exception setting "CursorPosition"

Last week I was working on a PS script to upload files to an FTP and this script supposes to runs through a windows service. It runs perfectly well when it runs manually with the PowerShell ISE.

However, when I scheduled it to run it through a service, service logs below error in the error log. 
Run Script Error: Exception setting "CursorPosition": "A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows."
While creating the script, I did add CLS to the script to clear the screen, so I can see the execution steps in the output window very clearly. This simple command was causing the error when it runs through the service. Only thing I had to do was simply remove the CLS and restart the service. 

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

13 July 2019

How to inject data to Customer Address Line 2 using Microsoft Business Central API

Creating a customer record in Microsoft Dynamics 365 Business Central is a topic I blogged about in one of my previous blog posts. If you have not read them yet I suggest you read it before going through this for better understanding. 

Part 01: Getting Started with Dynamics 365 Business Central APIs
Part 02: Understanding Microsoft Business Central Out-Of-The-Box API Endpoints
Part 03: Understanding Microsoft Business Central Custom API Endpoints

If you want to insert below address to Business Central Customer Card then how would your JSON body look like?


Field Name in BC
Data to inject
Address
 2/34
Address 2
 Coliseum Drive
City
 Albany
County
 Auckland
Country
 NZ
Postal Code
 0632 

First Attempt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
 "number": "CUST0012",
 "displayName": "Tailspin Toys",
 "type": "Company",
 "email": "jordan.moresby@contoso.com",
 "currencyCode": "NZD",
 "address": {
     "street": "2/34, Coliseum Drive ",
     "city": "Albany",
     "state": "Auckland",
     "countryLetterCode": "NZ",
     "postalCode": "0632"
 }
}

Outcome :

As you can see the first attempt did not work as expected. Address and Address 2 both end up in one field.

Second Attempt :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
 "number": "CUST0012",
 "displayName": "Tailspin Toys",
 "type": "Company",
 "email": "jordan.moresby@contoso.com",
 "currencyCode": "NZD",
 "address": {
     "street": "2/34, \r\nColiseum Drive ",
     "city": "Albany",
     "state": "Auckland",
     "countryLetterCode": "NZ",
     "postalCode": "0632"
 }
}

Outcome:
It did work and the "Address 2" field gets filled with the data we wanted. The change I did was I added \r\n into my JSON body. \r\n is used as a newline character in Windows and this is a very common way to go to a new line. 

 \r\n = CR + LF → Used as a new line character in Windows  

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

Understanding Microsoft Business Central Custom API Endpoints

This is the third blog post about the Microsoft Business Central APIs and I suggest you go through below blog posts first if you haven't read them yet.

Part 01: Getting Started with Dynamics 365 Business Central APIs
Part 02: Understanding Microsoft Business Central Out-Of-The-Box API Endpoints

If you want to access custom developed API then this blog post will give you the details of how the API endpoint will be. 

** from this point onwards "https://api.businesscentral.dynamics.com" will be referred to as "{BaseURL}

Tenant version is below 14.1:

{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/<api publisher>/<api group>/<api version>

Tenant version is 14.1 or above:

{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/<api publisher>/<api group>/<api version>

You might be wondering from where the "api publisher", "api group" and "api version" are coming from. These values are defined during the development of the custom API.

Below is a custom developed API page and these values are defined as properties of the page.

Below are the endpoints to access above mentioned custom API.
Tenant version is below 14.1:

{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/tc/iot/beta/companies/<companyID>/outdoortempentries

Tenant version is 14.1 or above:


{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/tc/iot/beta/companies(<companyID>)/outdoortempentries

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

Understanding Microsoft Business Central Out-Of-The-Box API Endpoints

If you are working on a project which involves integrating a third party application to Microsoft Dynamics 365 Business Central, then I assume you have already come across with the Business Central APIs. 

I noticed that most of the developers are still not comfortable with the endpoints of the BC APIs. Therefore this blog post is about how to understand the BC API endpoints.

Endpoint contains a couple of sections.

Sections of the URL
Purpose
https://api.businesscentral.dynamics.com
Base URL. This will be the same for all the out-of-the-box APIs and for custom APIs
/v1.0
Version
/your tenant domain
Domain name or ID
/environment name
Environment name. Can get the name from the admin portal. Ex: production, sandbox
/api
This is a keyword
/beta 
The version of the API.

** from this point onwards "https://api.businesscentral.dynamics.com" will be referred to as "{BaseURL}

If you want to use out-of-the-box API then the endpoint would be : 
{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta  

Might get an error like below when calling the endpoint even though the correct credentials were provided with the request. 

1
2
3
4
5
6
{
    "error": {
        "code": "Authentication_InvalidCredentials",
        "message": "The server has rejected the client credentials."
    }
}

I encountered this recently and manage to find the reason behind this. Above endpoint will only work if your tenant version is below 14.1. If the tenant version is 14.1 or above then it is a must to use the API version 2.0. (yet to confirm by the Microsoft)

For the tenant which are 14.1 or above endpoint would be:


{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta   

Result body will contain all the out-of-the-box APIs for Business Central.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
    "value": [
        {
            "name": "items",
            "kind": "EntitySet",
            "url": "items"
        },
        {
            "name": "companies",
            "kind": "EntitySet",
            "url": "companies"
        },
        {
            "name": "customers",
            "kind": "EntitySet",
            "url": "customers"
        }
    ]
}

Before you call any other API it is a must to point the URL to a specific company. In order to do that you can call the below Endpoint
Tenant version is below 14.1:

{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta/companies

Tenant version is 14.1 or above:


{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta/companies

It will return all the companies available in the tenant. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "value": [
        {
            "id": "e3dbe661-9c12-47d0-81f8-1186bd32518ab",
            "systemVersion": "34093",
            "name": "CRONUS NZ",
            "displayName": "CRONUS NZ",
            "businessProfileId": ""
        },
        {
            "id": "e15523c2-b04f-438c-b1bc-756321a91fae",
            "systemVersion": "34093",
            "name": "My Company",
            "displayName": "My Company",
            "businessProfileId": ""
        }
    ]
}

Version 14.1 and above treat segments as collections. Therefore it is a must to use ( ) when specifying a single record in all the new tenant versions. 

Tenant version is below 14.1:

{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta/companies/<companyID>

Tenant version is 14.1 or above:

{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta/companies(<companyID>)

Once you select the company, you can call the other entities in the same way you call the companies. 

As an example below calls will give you the list of items available. 
Tenant version is below 14.1:
{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta/companies/<companyID>/items

Tenant version is 14.1 or above:

{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta/companies(<companyID>)/items

If you want to retrieve a single item then below can be used
Tenant version is below 14.1:
{BaseURL}/v1.0/<your tenant domain>/<environment name>/api/beta/companies/<companyID>/items/<itemID>

Tenant version is 14.1 or above:

{BaseURL}/v2.0/<your tenant domain>/<environment name>/api/beta/companies(<companyID>)/items(<itemID)

Good luck and happy integration!

Please provide your feedback with a comment. 
Thank you and Regards,
Tharanga Chandrasekara
Read more »

01 July 2019

Fourth consecutive year as a Microsoft Most Valuable Professional (MVP) - Business Applications

Honored to receive my 4th consecutive MVP award for Business Applications. 

Congratulations to my fellow MVPs and best wishes to those boarding on a new journey. A special shout-out goes to my family, @ThetaNet, @MSDYN365BC, and @freddydk for all the support!


Thank you, everyone, for helping me out on this great journey and planning to do more in this year. 

Thank you and Regards,
Tharanga Chandrasekara
Read more »