Scenario: Connect an integration client
Goal. Give an external system (middleware, an e-commerce platform, a CRM, a script) its own identity in Dynamics 365 Finance and Operations, with exactly the Lattice rights it needs, and prove that the identity can authenticate, reach the Lattice services and read back what it did. When you finish, the client has made a read-only status query and a non-committing preview, and you can see the preview in the service call log (status queries are not written to it).
When to use. Once per integration client and per environment, before the first business call. Every other scenario assumes it is done: Post a journal exactly-once, Workflow approvals, Use external keys, Batch and async operations, Track documents and read data and React to business events.
Prerequisites
- Lattice is installed in the environment and the database is synchronized. The Lattice package carries the Siren licensing module, so there is nothing separate to install for it.
- License. There is no license key to enter and no activation page. A newly installed environment reports
Unlicensed, and that status is allowed through, so every operation works. Lattice refuses a call withErrorCodeLicenseNotValidonly after the licensing service has returned an adverse verdict (Expired,InvalidorOfflineExceeded). Previews, status queries, data entities and business events are never refused for licensing. See Deployment. - An administrator who can create an app registration in Microsoft Entra ID, register it in Finance and Operations and assign security roles.
- A dedicated, non-interactive Finance and Operations user for the client, one per integration. All role, duty and privilege checks run against this user.
- Know which calls the client makes, so you can pick the role (step 3 below). The roles and duties are in Security model.
Steps
-
Create the app registration in Microsoft Entra ID. Register a single-tenant application, create a client secret (or upload a certificate), and record the Application (client) ID, the Directory (tenant) ID and the secret. Store the secret in a vault.
-
Register the app in Finance and Operations. Go to System administration > Setup > Microsoft Entra ID applications, click New, enter the application (client) ID in Client Id, a Name (for example
Webshop integration - UAT) and, in User ID, the dedicated user from the prerequisites. Save. Every call the client makes now runs as that user. -
Assign the Lattice role the calls need. Go to System administration > Security > Assign users to roles, select the role, click Manually assign / exclude users, select the user and click Assign to role. Choose the narrowest role that covers the client:
The client will... Role Main duties Post and act on documents, query status, read monitoring and Lattice entities MGCLatticeIntegrationOperatorRoleMGCLatticeIntegrationServiceOperationsDuty,MGCLatticeIntegrationServiceQueryDuty,MGCLatticeIntegrationServiceMonitoringDuty,MGCLatticeDataEntitiesView,MGCLatticeDataEntitiesMaintain,MGCLatticeCrossReferenceViewDutyOnly read: status queries, price inquiry, monitoring, Lattice entities MGCLatticeIntegrationReadOnlyRoleMGCLatticeIntegrationServiceQueryDuty,MGCLatticeIntegrationServiceMonitoringDuty,MGCLatticeDataEntitiesView,MGCLatticeCrossReferenceViewDutyAlso cancel free text invoices, post intercompany journals or fixed asset disposals, activate new standard costs, or write external systems and cross-reference keys MGCLatticeIntegrationAdministratorRoleadds MGCLatticeIntegrationServiceHighRiskDutyandMGCLatticeCrossReferenceMaintainDutyFor least privilege, build a custom role from the module privileges instead (for example
MGCLatticeAccountsReceivableServiceMaintainplusMGCLatticeIntegrationServiceMonitoringDuty). Never assignMGCLatticeDatabaseAccessAdministratorto an integration identity. -
Set the user's default company to the legal entity the client works in (System administration > Users > Users, the Company field of the user). Service calls name their legal entity in
LegalEntityId, but an OData read withoutcross-company=trueruns in the default company. -
Confirm the service groups are deployed. The service groups deploy with the package and need no setup. To check them, open
https://<your-environment>/api/servicesin a browser signed in to the environment and confirm that the 13 Lattice groups are listed:MGCLatticeAccountsPayableServiceGroup,MGCLatticeAccountsReceivableServiceGroup,MGCLatticeAsyncOperationServiceGroup,MGCLatticeDataManagementServiceGroup,MGCLatticeDbAccessServiceGroup,MGCLatticeExpenseServiceGroup,MGCLatticeFixedAssetsServiceGroup,MGCLatticeGeneralLedgerServiceGroup,MGCLatticeInventoryServiceGroup,MGCLatticeJournalPostingServiceGroup,MGCLatticeProductionServiceGroup,MGCLatticeProjectServiceGroupandMGCLatticeWorkflowServiceGroup. If one is missing, the package did not finish deploying (Deployment, section 16). -
Get a token with the OAuth 2.0 client-credentials flow. The scope is your environment URL followed by
/.default:POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/tokenContent-Type: application/x-www-form-urlencodedgrant_type=client_credentials&client_id=<client-id>&client_secret=<client-secret>&scope=https://<your-environment>/.defaultThe response carries
access_token. Send it asAuthorization: Bearer <access_token>on every call and request a new one shortly before it expires. -
Make a first, read-only call: a status query.
getSalesOrderStatusonMGCLatticeSalesOrderPostingService(service groupMGCLatticeAccountsReceivableServiceGroup) reads a sales order and changes nothing. Every Lattice call isPOST https://<your-environment>/api/services/<ServiceGroup>/<ServiceClass>/<operation>with the request in_request:POST /api/services/MGCLatticeAccountsReceivableServiceGroup/MGCLatticeSalesOrderPostingService/getSalesOrderStatus{"_request": {"RequestId": "3b7c0d52-8e41-4f0a-9c55-1d2e6f7a8b90","LegalEntityId": "USMF","UserContext": "webshop","DocumentId": "000698"}}RequestIdis required on every call, queries included. It returnsSuccesstrue,DocumentTypeSalesOrder, the order's status inDocumentStatus(for exampleBackorderorInvoiced) and namedStatusDetailssuch asCustAccount. -
Make a first write-path call: a preview. A preview validates a posting and commits nothing. Send
postGeneralJournal(MGCLatticeGeneralLedgerServiceGroup/MGCLatticeGeneralLedgerJournalService) withPreviewModetrue, today's date and an open period:{"_request": {"RequestId": "9b2d5f60-1c34-4e8a-b7d2-0a4c6e8f1b23","LegalEntityId": "USMF","UserContext": "webshop","JournalNameId": "GenJrn","Description": "Connection check","PostingDate": "2026-10-07","PreviewMode": true,"Lines": [{ "MainAccountId": "110110", "OffsetMainAccountId": "110180", "AmountCurDebit": 10.00,"AmountCurCredit": 0, "CurrencyCode": "USD", "TransDate": "2026-10-07" }]}}It returns
Successtrue,PreviewAppliedtrueandPreviewFidelity1(validation only). No journal is created, no number is used and theRequestIdstays free for a real post. Only five operations have a real preview (sales confirm, packing slip and invoice, general journal, intercompany journal); see Posting preview. -
If the client will send its own keys, register its external system once. Either go to System administration > Setup > Lattice > External systems and add a row, or let the client create it through the shared
LatticeExternalSystemsentity (this needs the administrator role orMGCLatticeExternalSystemMaintain):{ "ExternalSystemId": "SHOP", "Description": "Webshop", "Active": "Yes" }Send it as
POST https://<your-environment>/data/LatticeExternalSystems. The rest of the setup is in Use external keys.
How to verify
- The token request returns
access_token, and both calls return HTTP 200 withSuccesstrue. - The preview is in the service call log: open System administration > Inquiries > Lattice > Services >
Service call log, or read the monitoring entity
GET https://<your-environment>/data/LatticeServiceCallLogs?$filter=RequestId eq 9b2d5f60-1c34-4e8a-b7d2-0a4c6e8f1b23.CalledByis the dedicated user from step 2,UserContextis what the client sent, andIsPreviewisYes. Use a posting operation withPreviewModetruefor this check: status queries are never written to the service call log, so the step 7 query is not there. GET https://<your-environment>/data/LatticeExternalSystemslists the external system withActiveYes, when you created one.
When it goes wrong
| What you see | Cause and fix |
|---|---|
| The token request fails, or HTTP 401 on the call | No valid token: wrong scope (it must be https://<your-environment>/.default), an expired secret, or an expired token. Request a new token. |
| HTTP 403 | The token is valid, but the app is not registered on Microsoft Entra ID applications or its user is disabled (step 2), or the user has no Lattice role that grants the operation (step 3). |
| HTTP 404 on a service URL | The service group is not deployed, or the group, service or operation name in the URL is misspelled. |
ErrorCode ValidationFailed (1) with "RequestId is required." or "LegalEntityId is required." | Send a GUID RequestId and a LegalEntityId on every call. |
ValidationFailed with "Legal entity ... was not found or is not accessible." | The LegalEntityId does not exist. |
DocumentNotFound (2) on the status query | No sales order with that number in that legal entity. |
PreviewUnsupported (10) | PreviewMode true on an operation without a preview. Nothing ran; send it without the flag when you mean to post. |
LicenseNotValid (12), IsRetryable true | The license was found expired, invalid or offline too long. Reads, previews and entities keep working; renew or reconnect and resend the same request unchanged (Deployment, section 16). |
| An OData read returns no rows for a record that exists | The read ran in the user's default company. Add cross-company=true and filter on dataAreaId; see Track documents and read data. |
Error codes travel as integers in service responses; the full table is in API reference.
Reference
- Trial and day-one guide: install, first calls and the first business event in one sitting.
- Deployment: app registration, security configuration, licensing, troubleshooting.
- Security model: every role, duty and privilege.
- API reference and Endpoint payload specification: endpoint pattern, common request and response members, payloads.
- Cross-reference keys: external systems and keys.
- Integration operations: the service call log, the operations console and the jobs that must be running.