We have installed on our server MS Dynamics 365 Business Central (I don’t know how to view currently installed version). We are using oData v4 protocol for our requests.
Task
We need to make API calls to this system from PHP
Issue
It’s impossible to make POST, PATCH, DELETE requests when GET request works well.
GET
Request:
GET https://d365bc.vendor.com:7058/attain/ODataV4/Company(‘{{company}}’)/Customer
Response
{
"@odata.context": "https://d365bc.vendor.com:7058/attain/ODataV4/$metadata#Company('...')/Customer",
"value": [
{
"@odata.etag": "W/"JzQ0O29EcmJmcGs4V3NRMHlEQ0Fxa0JxL1N0bi9xZjY5UDFQakZ0U2tBUGU1Kzg9MTswMDsn"",
"No": "01121212",
"Name": "Spotsmeyer's Furnishings",
"Responsibility_Center": "",
"Location_Code": "YELLOW",
"Post_Code": "US-FL 37125",
"Country_Region_Code": "US",
"Phone_No": "",
"IC_Partner_Code": "",
"Contact": "Mr. Mike Nash",
"Salesperson_Code": "JR",
"Customer_Posting_Group": "FOREIGN",
"Gen_Bus_Posting_Group": "EXPORT",
"VAT_Bus_Posting_Group": "EXPORT",
"Customer_Price_Group": "",
"Customer_Disc_Group": "",
"Payment_Terms_Code": "1M(8D)",
"Reminder_Terms_Code": "FOREIGN",
"Fin_Charge_Terms_Code": "2.0 FOR.",
"Currency_Code": "USD",
"Language_Code": "ENU",
"Search_Name": "SPOTSMEYER'S FURNISHINGS",
"Credit_Limit_LCY": 0,
"Blocked": " ",
"Privacy_Blocked": false,
"Last_Date_Modified": "2020-06-18",
"Application_Method": "Manual",
"Combine_Shipments": true,
"Reserve": "Optional",
"Shipping_Advice": "Partial",
"Shipping_Agent_Code": "",
"Base_Calendar_Code": "",
"Balance_LCY": 0,
"Balance_Due_LCY": 0,
"Sales_LCY": 0,
"Global_Dimension_1_Filter": "",
"Global_Dimension_2_Filter": "",
"Currency_Filter": "",
"Date_Filter": "..11/13/20"
},
{
"@odata.etag": "W/"JzQ0O08vNlVHSWVaZ1FGeG42d2JOa3k4Qm5uVHlkSGYzNk1ES2V5Y2E2S3hiekU9MTswMDsn"",
"No": "01445544",
"Name": "Progressive Home Furnishings",
"Responsibility_Center": "",
"Location_Code": "YELLOW",
"Post_Code": "US-IL 61236",
"Country_Region_Code": "US",
"Phone_No": "",
"IC_Partner_Code": "",
"Contact": "Mr. Scott Mitchell",
"Salesperson_Code": "JR",
"Customer_Posting_Group": "FOREIGN",
"Gen_Bus_Posting_Group": "EXPORT",
"VAT_Bus_Posting_Group": "EXPORT",
"Customer_Price_Group": "",
"Customer_Disc_Group": "RETAIL",
"Payment_Terms_Code": "14 DAYS",
"Reminder_Terms_Code": "FOREIGN",
"Fin_Charge_Terms_Code": "2.0 FOR.",
"Currency_Code": "USD",
"Language_Code": "ENU",
"Search_Name": "PROGRESSIVE HOME FURNISHINGS",
"Credit_Limit_LCY": 0,
"Blocked": " ",
"Privacy_Blocked": false,
"Last_Date_Modified": "2018-09-19",
"Application_Method": "Manual",
"Combine_Shipments": true,
"Reserve": "Optional",
"Shipping_Advice": "Partial",
"Shipping_Agent_Code": "",
"Base_Calendar_Code": "",
"Balance_LCY": 1499.03,
"Balance_Due_LCY": 1499.03,
"Sales_LCY": 1499.03,
"Global_Dimension_1_Filter": "",
"Global_Dimension_2_Filter": "",
"Currency_Filter": "",
"Date_Filter": "..11/13/20"
},
DELETE
DELETE https://d365bc.vendor.com:7058/attain/ODataV4/Company(‘{{company}}’)/Customer(No=’01121212′)
{
"error": {
"code": "BadRequest",
"message": "Entity does not support delete."
}
}
I’m not sure what is the correct syntax for the Create (POST) or Update (Patch)
For the POST request I tried to copy existing value (taken from GET) and put it into the body. I’m getting following response:
{
"error": {
"code": "BadRequest_MethodNotAllowed",
"message": "Entity does not support insert."
}
}
Sometimes if I make absolutely wrong request I’m getting following response:
{
"error": {
"code": "BadRequest_MethodNotAllowed",
"message": "'POST' requests for 'Customer' of EdmType 'Entity' are not allowed within Microsoft Dynamics 365 Business Central OData web services."
}
}
I’m unable to apply CUD operations for Customers, ProductItems. However for orders it works.
Existing Privileges
If I follow
Setup & Extensions / Manual Setup / Users / [Select User]
In the permissions section, there are too many assigned privileges. Among them, there is a SUPER privileges item. As I know all names are custom there. Here is the screenshot of the assigned privileges.
UPD 1.
I tried to follow this guide: https://learn.microsoft.com/en-us/dynamics-nav/api-reference/v1.0/
I have on-prem installation and for me it’s not clear what is the correct endpoint for any operation.
For example I can make following request:
https://d365bc.vendor.com:7057/attain/WS/CRONUS%20International%20Ltd/Page/Customer
And as result, I’m getting some scheme, but not customers, or the possibility to make any actions with them.
As I understood this guide has examples for cloud installation only.
Extension APIs:
https://<base URL>:<port>/<serverinstance>/api/<API publisher>/<API group>/<API version>
Am I doing everything correct? What do these params mean? No explanation provided in the guide.
Upd.2
Regarding requirements:
API must be enabled on the Business Central server instance:
So port is 7057, API URL is https://d365bc.vendor.com:7057/Attain/WS/
What is WS, is it really required? By the URL above I’m getting this:
The user used for authentication must have a Web Service Access Key (created for the user in Business Central)
There was nothing in this section, I’ve added new key. And now it looks like this. But it didn’t change anything in my case. Still same errors: 405 for the port 7057 and 404 for the port 7058.
p.s. Is it enough to simply generate it? Or we need to use it somewhere?
The user must have the required permissions within Business Central for the relevant API’s.
Is it managing at the following page?
Here are responses examples:
Url was changed after execution with the correct Vendor name in the domain name.
3
Answers
The OData endpoint is different to the API endpoint.
I’d recommend using the API as it’s the more up to date and efficient way to interact with data within Business Central.
The documentation for the API endpoint can be found here
https://learn.microsoft.com/en-us/dynamics-nav/api-reference/v1.0/, along with some examples such as updating customers, items, etc.
You can use OData to modify data, but only if the underlying object that drives the endpoint is a page (as opposed to a query), and must be marked with InsertAllowed. This is less optimised than the API endpoint.
https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/webservices/use-odata-to-modify-data
The paramaters are as follows:
The combination of base URL, port and server instance can be located under OData Services and the field OData Base URL on the Business Central service tier settings.
The base endpoint you need to use is (based on the information you supplied):
To work with the API’s you first need to get an id for the company – so you get the company list:
With your company id you can then get a list of customers:
You would use the same endpoint for POST or PATCH by providing the required data as json in the request body.
Requirements:
Comments:
Response to UPD.2:
Port 7057 and
https://d365bc.vendor.com:7057/Attain/WS/
is for SOAP Web Services and is not to be confused with API. You need the port 7058 as stated under the OData Services tab.To assign a Web Service Access Key you must navigate to Users in Business Central, find the user in question and click the button
Change Web Service Key
.Some notes:
You need retrieve entities first (by make ‘Get’), then when you need to do update/PUT or delete (beside the need to use correct method (PUT, DELETE)) You have to send in the Headers of your API call, the parameter: If-Match and make it equal to the value of odata.etag (that you got from the GET response), it is like this:
If-Match : W/"JzQ0O0YxVTZnTlFpQ0NxbExDdmN0N2JGSDM2azN4dUhncEk1Nnl0MVhETGRIemc9MTswMDsn"
Regarding: https://d365bc.vendor.com:7058/attain/ODataV4/Company(‘{{company}}’)/Customer(No=’01121212′)
This is not OData: /Customer(No=
you should use eq instead of the sign =
However, it is better to use the ID (GUID) of the record and you must provide If-Match in header with value of odata.etag