skip to Main Content

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.

enter image description here

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:

enter image description here

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:

enter image description here

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.

enter image description here

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?

enter image description here

Here are responses examples:

enter image description here
enter image description here

Url was changed after execution with the correct Vendor name in the domain name.

I’m unable to test everything right now, as I’m far away from my laptop on vac. Thanks everyone for your time

3

Answers


  1. 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

    Login or Signup to reply.
  2. The paramaters are as follows:

    1. base URL: the name of the server e.g. d365bc.vendor.com
    2. port: the port used for OData e.g. 7058
    3. serverinstance: the name of the Business Central server instance e.g. attain
    4. API publisher: used for grouping of custom API’s (not required when using the standard API’s)
    5. API group: used for grouping of custom API’s (not required when using the standard API’s)
    6. API version: used for grouping of custom API’s (not required when using the standard API’s)

    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):

    // Version 13
    https://d365bc.vendor.com:7058/Attain/api/beta
    
    // Version 14+
    https://d365bc.vendor.com:7058/Attain/api/v1.0
    

    To work with the API’s you first need to get an id for the company – so you get the company list:

    // Version 13
    https://d365bc.vendor.com:7058/Attain/api/beta/companies
    
    // Version 14+
    https://d365bc.vendor.com:7058/Attain/api/v1.0/companies
    

    With your company id you can then get a list of customers:

    // Version 13
    https://d365bc.vendor.com:7058/Attain/api/beta/companies([company id here!])/customers
    
    // Version 14+
    https://d365bc.vendor.com:7058/Attain/api/v1.0/companies([company id here!])/customers
    

    You would use the same endpoint for POST or PATCH by providing the required data as json in the request body.

    Requirements:

    1. API must be enabled on the Business Central server instance
    2. The user used for authentication must have a Web Service Access Key (created for the user in Business Central)
    3. The user must have the required permissions within Business Central for the relevant API’s.

    Comments:

    • Some of the API’s only support GET. This means you would get the 405 Not allowed error for POST or PATCH.
    • You might need to add If-Match * to the request headers for PATCH operations.

    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.

    Login or Signup to reply.
  3. Some notes:

    1. 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"

    2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search