Hi, Readers.
Yesterday we discussed how to use OAuth 2.0 to connect Dataverse tables (APIs) in Postman (Using Grant type: Client Credentials, not Implicit) – Get, Patch, Post and Delete. Let’s look at some simple examples,

For Authentication and environment setup, please refer to yesterday’s post. It is strongly recommended to test all processes in Postman before customizing BC.
In this post, I would like to talk about how to integrate with Microsoft Dataverse via APIs (Not using the standard Dataverse connector).
PS: Business apps often use data from more than one source. Dataverse combines data into a single set of logic that makes it easier to connect Business Central to other Dynamics 365 applications. For example, Dynamics 365 Sales or your own application built on Dataverse. To learn more about Dataverse, go to What is Dataverse? We have discussed the following topics:
- Dynamics 365 Sales and Business Central integration setup (Set up a connection to Dataverse and Set up a connection to Dynamics 365 Sales)
- Dynamics 365 Business Central: Customizing an Integration with Microsoft Dataverse (Integrate custom tables)
- Business Central 2024 wave 1 (BC24): Changes to AL Table Proxy Generator tool (altpgen) – Two additional arguments: ClientId and RedirectUri
- Dynamics 365 Business Central: Can we timely synchronize Dataverse entity changes without Power Automate? Yes, but……
As a test, let me briefly share the requirements.
Use Dataverse standard API to synchronize the “account” table to BC. This time the fields only use the following four, Account Name, Main Phone, City, Website.

In addition, the Guid type field Account is used as the primary key in BC to associate values. (Hidden by default)

And the main table are maintained on the BC side, so it mainly meet the following two requirements
- Get all the data of the “account” table in Dataverse from BC
- Add, modify, and delete data in BC and synchronize it to the “account” table in Dataverse
Simple diagram:

Let’s get started.
1. Create a new table to store the data from the “account” table in Dataverse. As mentioned above, the primary key is “Account”, and the secondary key “Account Name” is used for sorting, which you can ignore.

2. Create a new list page to display the table data.


3. Create a codeunit to manage the code, including Authentication, Get, Insert, Update, and Delete logic.

Authentication: Using the information I mentioned in how to use OAuth 2.0 to connect Dataverse tables (APIs) in Postman (Using Grant type: Client Credentials, not Implicit) – Get, Patch, Post and Delete.
Access Token URL: https://login.microsoftonline.com/d8f36038-1f93-4543-affc-5dc92b6ee871/oauth2/v2.0/token (Change it to your tenant ID)
Client ID: a80c03cf-6ffa-4b6e-b2c8-6005310d3d87
Client Secret: fME7Q~cAaSBhXMGZoHY3ei64nn1fxGpqF42mh
Scope: https://org2ffa63f6.api.crm.dynamics.com/.default (Note that Scope is different from BC)
Web API endpoint: https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2
I hardcoded it in this example, but you can add some settings to allow users to enter this information flexibly.

More details: Dynamics 365 Business Central: How to use OAuth 2.0 in AL with SecretText (Using codeunit 501 OAuth2)
Get:
Endpoint:
https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2/accounts?$select=name,telephone1,address1_city,websiteurl

PS: In order to be compatible with previous versions, I still use the old way to read the value in JsonObject. If you are BC26 or later, you can use the following new method
Business Central 2025 wave 1 (BC26): Overloaded JsonObject data type GetValue method (New methods access properties and array elements for JSON)

Then add an action on the list page to get the data.


Done.


Test video:
Insert (Post):
Endpoint:
https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2/accounts?$select=name,telephone1,address1_city,websiteurl

PS: To retrieve data from an entity you’re updating, you can compose your PATCH
/Post request so that data from the created record is returned with a status of 200 (OK). To get this result, you must use the Prefer: return=representation
request header.

If the Prefer header is not added, the following error will occur.

The data does not represent a valid JSON token.

And when inserting data, first insert it into the “Account” table of Dataverse, then get the returned Account id (Guid), and then insert it into the BC table as the primary key. In this way, the data of the “Account” table in Dataverse can be associated with this primary key.

PS: This requires setting the DelayedInsert property of the page to true

Test video:
Modify (Patch):
Endpoint:
'https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2/accounts(' + GraphMgtGeneralTools.GetIdWithoutBrackets(DataverseAccount.Account) + ')'
Please note, we need to get the id from Guid without brackets, more details: Dynamics 365 Business Central: How to quickly get the id from Guid without brackets.


If you forget to do this, the following error will be displayed.

400 {“error”:{“code”:”0x80060888″,”message”:”Bad Request – Error in query syntax.”}}

Test video:
Delete:
Endpoint: As in Modify (Patch), you need to pay attention to the brackets.
'https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2/accounts(' + GraphMgtGeneralTools.GetIdWithoutBrackets(DataverseAccount.Account) + ')'

PS:
1. Because there is no way to return a value after deleting data, do not try to read the response text after deleting it.

The data does not represent a valid JSON token.

2. If you encounter the following error when deleting, please confirm whether the roles you have granted include the table’s delete permission.
403 {“error”:{“code”:”0x80048306″,”message”:”user with id 9e531e38-0d3d-f011-b4cc-000d3a3800ca does not have DeleteAccess right(s) for record with id 9196309f-2f40-f011-b4cb-000d3a3800ca of entity Account. Consider assigning a role with the required access level to the user or team. For further troubleshooting, please work with a system administrator to use the Access Checker tool on this record: https://org2ffa63f6.crm.dynamics.com/main.aspx?forceUCI=1&pagetype=entityrecord&etn=account&id=9196309f-2f40-f011-b4cb-000d3a3800ca


Test video:
Very simple, using this way, users do not need a Dataverse license and can achieve real-time synchronization. The disadvantage is that each synchronized table needs to be customized. Although the standard connector is not that easy to expand, I recommend using standard features as much as possible. However, if you only synchronize one table, this method is also very efficient. Please choose the most suitable solution based on your needs.
Source Code: GitHub (Please note that the source code is for reference only, you can improve it according to your own needs)
END
Hope this will help.
Thanks for reading.
ZHU
コメント