top of page

Integrate with third-party manufacturing execution systems (MES)

Functional perspective

We are back with a functionality that we have had available for some time in our D365FO environments. This is the integration of our environment with a third-party manufacturing system through the exchange of messages via API.

In the following image we can see the objective of this functionality. Just as D365FO will perform stock control and ERP functionality, the external system will provide Dynamics with manufacturing status data.

This third-party system can be both a complex plant control application and a simple presence sensor that reads the passage of elements through a production line. All we need is for these impulses/events to be translated into messages so that we can send them to the D365FO API.

The different events and messages that are exchanged between both platforms can be the following:

Process name


Production order status changes

D365FO indicates to MES the status changes of the productions

Start of production order

MES tells D365FO which production orders to start

Reported as finished

MES tells D365FO what quantities have been produced


MES tells D365FO which products have been consumed

Time consumed

MES indicates to D365FO the operating times

Finalize production order

MES indicates to D365FO the completion of a production order

The details of each one of them as well as the fields that we can provide to the API can be found in the official documentation of the feature:

This exchange of information occurs in real time and the D365FO processes the received messages through a configured batch process.

We can consult the messages received in the following route:

Production Control / Set Up / Manufacturing Execution / Integration of Manufacturing Execution Systems

In the following image we can see the structure of the control:

As we can see, the messages (grid above) are ordered in order of arrival and are referenced to the production order that we have introduced in the message.

In the "Type of message" column, it tells us what type of process described in the previous table is going to take place.

In the "Message status" column we see the status of that message:

  • In queue: the message is pending to be processed up to a maximum of 3 attempts

  • With error: after 3 attempts the message is marked as an error and all the messages of that production are "Queued" until this case is resolved

  • Cancelled: the message has been canceled by the user using the Cancel button. Only messages that are in the "Error" state can be canceled. Once canceled they are not taken into account for processing.

  • Processed: The message has been executed successfully.

Using the buttons on the top panel we can perform the following actions:

  • Process: allows us to manually execute messages that are in "Queue" or "With error" status

  • Edit before registration: allows us to manually modify message parameters to be able to process it satisfactorily. If we click, it opens the standard window of the particular process.

  • Cancel: allows us to cancel messages that are in "Error" status

  • Queue: allows us to requeue messages with "Error" status

In the lower grid we can see the content of the message as well as a history of its processing and consult the error log.

The following images are relative to a production order completion process:

As a final touch to the theoretical part of the process, it is important to highlight that the processing is independent for each production order; that is, each production order takes its own processing thread and is not affected by errors in other messages. However, if a production order has a bad message, message processing for that order is held until the problem is fixed.

That is why it is interesting to configure alerts or notifications so that the plant manager knows if at any time an error has occurred that hinders the processing of messages.

Technical perspective

Now we are going to see more in depth the technical part of this functionality.

First of all we will define which is the URL of the API that must be attacked with the messages:


The general structure of the messages in common in all and is defined in the body of the message:

    "_companyId": "dataAreaId",
    "_messageQueue": "JmgMES3P",
    "_messageType": "ProdProductionOrderStart",
    "_messageContent": ""


  • _companyId = dataAreaId of the destination company of the message within D365FO

  • _messageQueue = corresponds to an enumeration that distinguishes the different D365FO message queues. In this particular functionality this property is fixed with the value "JmgMES3P".

  • _messageType = corresponds to the one enumerated about the type of message within this queue. It can take the following values ​​depending on the process to be carried out:

    • ProdProductionOrderStart

    • ProdProductionOrderEnd

    • ProdProductionOrderReportFinished

    • ProdProductionOrderRouteCard

    • ProdProductionOrderPickingList

  • _messageContent = corresponds to the content of the message itself and depends on the operation to be performed.

Here is an example for each type of operation:


Cuerpo de ejemplo


{ "_companyId": "USMF", "_messageQueue": "JmgMES3P", "_messageType": "ProdProductionOrderStart", "_messageContent": "{\"ProductionOrderNumber\": \"P000211\"}" }


{ "_companyId": "USMF", "_messageQueue": "JmgMES3P", "_messageType": "ProdProductionOrderEnd", "_messageContent": "{\"ProductionOrderNumber\": \"P000214\"}" }


{ "_companyId": "USMF", "_messageQueue": "JmgMES3P", "_messageType": "ProdProductionOrderReportFinished", "_messageContent": "{\"ProductionOrderNumber\": \"P000214\", \"ReportFinishedLines\": [{\"ItemNumber\": \"L0100\", \"ReportedGoodQuantity\": 1, \"ReportAsFinishedDate\": \"2021-01-01\"}]}" }


{ "_companyId": "USMF", "_messageQueue": "JmgMES3P", "_messageType": "ProdProductionOrderRouteCard", "_messageContent": "{\"ProductionOrderNumber\": \"P000214\", \"RouteCardLines\": [{\"OperationNumber\": \"10\"}]}" }


{ "_companyId": "USMF", "_messageQueue": "JmgMES3P", "_messageType": "ProdProductionOrderPickingList", "_messageContent": "{\"ProductionOrderNumber\": \"P000214\"}" }

With all this information in mind, we only have to add the authentication in the header of the call and we will have our integrated MES.

Let's see an example of the call to start a production order:

1. Get the access token to the environment

2. Send the message

Below is a link to the Github repository where you will find a Postman collection to make all the calls we are talking about just by configuring the different variables.

Of course, with this functionality we can integrate in real time the plant control of a company and, based on it, create new types of messages to be exchanged for other third-party applications. Do you dare to try?


bottom of page