D365 Finance and Operations Custom Service: Build a Secure Integration
Introduction
A D365 Finance and Operations custom service lets an external app run selected business operations without signing in to the D365 interface. It helps when standard endpoints don’t support the data or logic your integration needs. To build one, define the request and response, add the business logic, set up Microsoft Entra ID authentication, then test the custom service URL.
🎥 Watch the video: Get a practical visual walkthrough of Dataverse performance planning and scalability.
Use a D365 Finance and Operations custom service when standard endpoints don’t fit
A custom service exposes selected D365 F&O operations to an external caller through a URL. The caller still needs a valid access token and the right permissions in D365. A custom service URL gives an app a way to reach specific logic; it doesn’t bypass security.
Understand what a custom service URL exposes
A custom service can accept data from an app, process it in D365 F&O, and return a result. For example, an external app could send customer account details for a creation request. The service can check the data, carry out the operation, and report whether it succeeded.
The external app could be Postman or a middleware service. Its users don’t need to sign in to the D365 interface, but the app must authenticate and be authorized. This keeps access tied to a registered application and its assigned permissions.
Choose between a custom service and OData
OData may be the better fit when it supports the required entity and standard operations. Use it when its available fields and behavior meet the integration need. A custom service is useful when you need tailored logic or an operation that a suitable standard endpoint doesn’t provide.
Custom services take development and testing. Before building one, check whether an existing endpoint can handle the request. A custom service should solve a clear gap, not duplicate a standard route without need.
Use customer and project data as examples
A customer creation request may need the customer account, company, and other required fields. The service should validate the supplied values before it creates a record. It can then return a result that confirms success or explains a validation problem.
The video’s project example uses company, project ID, project name, and customer account. A caller sends those values to the service operation. The service checks them and attempts the requested action.
Build a D365 F&O custom service around clear contracts
In Visual Studio, the service’s parts define what data it receives, what work it performs, and what it returns. The main pieces are request and response contracts, a service class, service metadata, and a service group. Keeping these roles clear makes the integration easier to maintain.
Define request and response contract classes
The request contract describes the fields the caller must send. For the project example, it can include company, project ID, project name, and customer account. These fields form the expected input for the operation.
A response contract describes what D365 sends back. It can report successful creation or return validation details when the request fails. Some operations may not need a detailed response, but callers often need an outcome to know what happened.
Put business rules in the service class
The service class reads values from the request contract, checks required fields, and runs the business logic. It then fills the response contract with the result. Keep validation and processing in this class rather than treating the endpoint as a direct database route.
Create, retrieve, update, and delete are common operation types, often called CRUD. Each operation should have clear behavior and its own checks. For example, an update should confirm that the target record exists before changing it.
Register the operation and add it to a service group
Create a service metadata node and link it to the service class. Add the method that callers need to run as an exposed operation. Follow D365 naming rules and the development team’s coding standards.
Add the service to a service group so the endpoint can expose it. A group can contain one or more services. If you add another operation or service later, verify that the group includes it.
Configure Microsoft Entra ID before calling the custom service URL
A custom service URL isn’t open to every app that can reach it. The calling application needs to prove its identity and have permission to use D365 F&O. Microsoft Entra ID supports this application-to-application flow.
Register the calling application
Register an application in the Azure portal under Microsoft Entra ID. The registration provides a tenant ID and client ID, and you can create a client secret for authentication. Treat that secret as a password: store it in a secure secret store and share it only with authorized teams.
Don’t place credentials in public code, shared documents, or source control. Keep access to the app registration limited to people who manage the integration. Rotate secrets according to your organization’s security policy.
Grant the application appropriate D365 access
In D365 F&O, add the registered app’s client ID in the Microsoft Entra applications setup. Assign the permissions the integration needs. Use least privilege rather than granting administrator access by default.
The right access depends on the operation and the D365 security design. A read-only integration shouldn’t receive permission to create or delete records. Review the assigned access when the service’s role changes.
Request and pass an access token
With the client-credentials flow, the app requests a token using its tenant ID, client ID, and secret. The token request also uses the D365 environment as its resource scope, commonly in the form of the resource URL followed by /.default. The app then sends the token with its service request.
Use HTTPS for token requests and API calls so credentials and tokens are protected in transit. Tokens expire, so the app must request a valid token before calling the service. A request without a valid token should fail authentication.
Deploy and test the D365 F&O custom service in Postman
Postman can help confirm that authentication, routing, and service logic work before another app uses the endpoint. Test the full request, not only whether the URL responds. In the video’s demo, the project request reached the service but failed validation.
Build and deploy the service changes
Build the X++ code and complete any required database synchronization. Then deploy the changes to the D365 environment. The exact process depends on your environment and release setup.
After deployment, check that the service group and operation are available. A successful build alone doesn’t confirm that the endpoint is ready for use. Verify the deployed route before testing its business logic.
Construct the endpoint and request payload
The custom service URL uses the D365 environment URL followed by the service API route, service group, service, and operation. The full route is specific to the environment and the names you set in metadata. Don’t assume one environment’s URL will work in another.
For the project example, send a POST request with the company, project ID, project name, and customer account expected by the request contract. Use the same field names and data types the service expects. Missing or malformed fields can trigger validation errors.
Check the response and confirm the result
Inspect the response body as well as the HTTP status. A request can reach the service and still fail because a required value is missing or a business rule rejects it. In the demo, Postman sent the project details, but the service returned a failure due to validation.
When the request succeeds, check the result in D365 or through an approved read method. This confirms that the operation changed the expected record. For failed tests, use the response details and D365 logs to find the cause.
Troubleshoot failures while protecting data and performance
Troubleshooting is easier when you check authentication, route details, input data, and server logs in order. A status code helps narrow the issue, but it doesn’t always explain the cause. Review the full response and the D365 environment logs.
Diagnose common HTTP response categories
A 400 response often points to missing or invalid input. A 401 usually means the token is missing, expired, or invalid, while 403 points to insufficient permission. Check the token and the app’s D365 access when either authentication or authorization fails.
A 404 can mean the route, service group, service, or operation is wrong or unavailable. A 500 signals an unhandled server-side failure. In each case, use the response body and D365 logs to confirm what happened rather than relying on the status code alone.
Validate inputs and return only necessary data
Check required fields and business rules before processing a request. Clear validation messages help the caller correct a request without exposing internal details. Keep response contracts focused on the outcome the caller needs.
Avoid returning sensitive customer, financial, or account information unless the integration requires it. For example, a creation response may only need to confirm that the record was created. Limit each app’s permissions to the data and operations it needs.
Improve reliability and control performance
Keep request payloads focused and avoid unnecessary database round trips. Test both successful requests and expected failures, including missing fields, invalid tokens, and insufficient permissions. Unit, component, API integration, performance, and regression tests can catch issues before release.
Conclusion
A D365 Finance and Operations custom service is useful when an integration needs business logic that a suitable standard endpoint can’t provide. Define request and response contracts, put validation and processing in the service class, then expose the required operation through service metadata and a service group. Configure Microsoft Entra ID, deploy the changes, and test both success and failure paths in Postman.
Keep permissions narrow, protect client secrets, require HTTPS, and return only the data the caller needs. Before relying on the integration, confirm that the endpoint behaves as expected in the target environment.









