Scenario: Send your own system's keys instead of D365 ids
Goal. Let an external system identify Finance and Operations records by the keys it already knows (a
webshop's order number, a CRM's account id, a legacy item code) instead of keeping a copy of every D365 id.
You register the system once, store its keys against the D365 records, and from then on the system sends
ExternalSystem plus ...ExternalKey members in its Lattice requests. Lattice resolves each key to the D365 id
before the operation runs and refuses a key it cannot resolve, so a wrong key never posts against the wrong
record.
When to use. Any integration whose source system has its own identifiers for customers, vendors, items, orders, journals, projects, fixed assets or production orders. Business events about those records report the keys back to subscribers (React to business events), and file ingestion templates can resolve them too (Inbound file to posted document).
Prerequisites
-
Security.
- Using keys in a request needs only the operation's own privilege.
- Registering an external system and writing keys needs
MGCLatticeCrossReferenceMaintainDuty(administrator role), orMGCLatticeExternalSystemMaintainplus the module's Maintain privilege, for exampleMGCLatticeCrossReferenceAccountsReceivableMaintainfor customers, sales orders and free text invoices. - Reading keys needs
MGCLatticeCrossReferenceViewDuty(operator and read-only roles).
See Security model.
-
The record kind is covered. 33 record kinds in seven modules: customer; sales order and line; return order and line; sales quotation and line; free text invoice and line; sales agreement and line; vendor; purchase order and line; purchase requisition and line; purchase agreement and line; released product; product variant; batch; transfer order and line; fixed asset; project; project contract; journal and journal line; production order; BOM and BOM version; route and route version. Addresses and main accounts are not covered.
-
The client is connected (Connect an integration client).
Steps
-
Register the external system. In the client: System administration > Setup > Lattice > External systems, add the id, a description and Active. Or from the integration, through the shared entity
LatticeExternalSystems(nodataAreaId; one list for all legal entities). Check first, then create or activate:GET https://<your-environment>/data/LatticeExternalSystems?$filter=ExternalSystemId eq 'SHOP'If it is missing,
POST https://<your-environment>/data/LatticeExternalSystems:{ "ExternalSystemId": "SHOP", "Description": "Webshop", "Active": "Yes" }If it exists with
ActiveNo,PATCH https://<your-environment>/data/LatticeExternalSystems(ExternalSystemId='SHOP')with"Active": "Yes". Keys can be added or changed only for an active system; an inactive system's keys are kept and still resolve. -
Decide how the keys behave (optional). On the module's parameters page (for sales orders, Accounts receivable parameters), open the Cross references tab and add a row per record kind and external system: Key kind (Alternate key resolves in requests; Historical is kept for reference and never resolves), Visible on forms, Editable on forms and Enforce unique. Turn on Enforce unique for keys that requests will send, so one key can never name two records. Without a row, keys written through the entities are alternate keys, not unique and not shown on forms.
-
Store the keys. Each record kind has its own entity, keyed by the record's business key plus
ExternalSystem, with the key inExternalKey. For a webshop order number on USMF sales order000698,POST https://<your-environment>/data/LatticeSalesOrderCrossReferences:{ "dataAreaId": "usmf", "SalesOrderNumber": "000698", "ExternalSystem": "SHOP", "ExternalKey": "SHOP-100045" }Other examples:
LatticeCustomerCrossReferences(CustomerAccountUS-001),LatticeVendorCrossReferences(VendorAccountNumber),LatticeReleasedProductCrossReferences(ItemNumberD0001),LatticeLedgerJournalCrossReferences(JournalBatchNumber). A record holds at most one key per external system. To change a key,PATCHthe row; an emptyExternalKeyclears it andDELETEremoves it. Add?cross-company=trueto aPATCHorDELETEwhose key names adataAreaIdother than the caller's default company. You can also load the same entities through Data management, or type keys on the record's Cross references page. No service operation stores keys. -
Send the key in a request. Put
ExternalSystemon the request header and the key in the...ExternalKeymember next to the id it replaces. Preview first where the operation has a preview.confirmSalesOrderonMGCLatticeSalesOrderPostingService(MGCLatticeAccountsReceivableServiceGroup):{"_request": {"RequestId": "5d6e7f80-91a2-4b3c-8d4e-5f6a7b8c9d0e","LegalEntityId": "USMF","ExternalSystem": "SHOP","SalesOrderIdExternalKey": "SHOP-100045","PostingDate": "2026-10-07","PreviewMode": true}}The key alone is enough;
SalesOrderIdmay be left out. If you send both, they must name the same order. Send the same request withPreviewModefalse(or left out) to confirm for real; a preview does not use up itsRequestId. Line keys (for example a line'sItemIdExternalKey) use the header'sExternalSystem. Keys resolve in the request's legal entity.The key members by service (full list in Cross-reference keys):
Service Key members Sales order posting (confirm, packing slip, invoice) SalesOrderIdExternalKeySales order capture ( createSalesOrder)CustAccountExternalKey; lineItemIdExternalKeyPrice inquiry ( resolveSalesPrice)CustAccountExternalKey,ItemIdExternalKeyPurchase order posting PurchaseOrderIdExternalKeyReturn orders SalesOrderIdExternalKey,PurchaseOrderIdExternalKey,CustAccountExternalKey,VendAccountExternalKey; lineItemIdExternalKeyTransfer order posting TransferOrderIdExternalKey; lineItemIdExternalKey,LineNumExternalKeyProduction order posting ProdIdExternalKey; pick list lineItemIdExternalKeyPurchase requisitions PurchReqIdExternalKeyFree text invoice InvoiceAccountExternalKey(post),InvoiceRecIdExternalKey(cancel)Payment journals and settlements AccountNumExternalKeyInventory journals, vendor invoice journal, fixed assets, projects, trade agreements see Cross-reference keys Status queries DocumentIdExternalKeyNot covered: the
Linesof sales and purchase order posting requests (they take D365 line numbers), return order line numbers, route card lines, depreciation proposals, workflow submission and work-item actions, async submissions, database access and Data management configuration. -
Query by key. The status queries take
ExternalSystemandDocumentIdExternalKeyin place ofDocumentId;getSalesOrderStatuswith"ExternalSystem": "SHOP"and"DocumentIdExternalKey": "SHOP-100045"returns the status of order000698(Track documents and read data). -
Receive keys back. Business events about a covered record carry a
crossReferencesarray ofexternalSystem/externalKeypairs (empty when the record has none), so a subscriber can match the event to its own record without a lookup.
How to verify
- The key is stored:
GET https://<your-environment>/data/LatticeSalesOrderCrossReferences?cross-company=true&$filter=dataAreaId eq 'usmf' and SalesOrderNumber eq '000698'returns the row withExternalSystemSHOPandExternalKeySHOP-100045. In the client, the sales order's Cross references button and FactBox show it when the system is set up as visible on forms. - The request found the record: the preview returns
SuccesstrueandPreviewAppliedtrue; the real call returns the D365 order number inDocumentIdand the confirmation inPostedDocumentId. - The service call log (
LatticeServiceCallLogs) records the call with the D365DocumentId.
When it goes wrong
Every key failure is refused before the operation reads or writes anything, with ErrorCode ValidationFailed
(1) and IsRetryable false. A failed call releases its RequestId, so after you fix the key or the
request you can resend it with the same RequestId.
| Message | Cause | What to do |
|---|---|---|
| "External key SHOP-100045 needs an external system." | ...ExternalKey sent without ExternalSystem | Add ExternalSystem to the request header. |
| "No ... has key SHOP-100045 in external system SHOP." | No alternate key matches in the request's legal entity: the key was never stored, is stored in another legal entity or for another record kind, is a Historical key, the external system id is wrong, or the record was deleted | Store the key (step 3), or correct the system id or legal entity. |
| "Key SHOP-100045 of external system SHOP matches more than one ..." | Two records hold the same key and the record kind does not enforce unique keys | Remove the duplicate, then turn on Enforce unique (step 2). |
| "Key SHOP-100045 of external system SHOP refers to 000698, but the request names 000702." | The request sends both a D365 id and a key, and they name different records | Send only the key, or make them agree. |
| "Key ... refers to a line of ..., not of ..." | A line key names a line of another document | Correct the line key or the document. |
- Price inquiry.
resolveSalesPriceanswers an unresolved key withSuccessfalseandErrorCodeValidationFailedin its own response contract. - Batches. Each item resolves its own keys; an item with a bad key fails alone and the others run.
- Entity writes refused. A business key that names no record (or a record of another kind, such as a sales
order number sent to the return order entity) is refused, and so is a key for an inactive external system.
Keys of purchase requisitions and agreements live in one owning legal entity, and a row written with another
dataAreaIdis refused. - An external system cannot be deleted while any legal entity holds keys or settings for it; set it inactive instead.
Reference
- Cross-reference keys: concepts, settings, all 33 entities and their keys, every service member, file ingestion placeholders, events.
- API reference: the key members in each operation's field table.
- Data entity reference: the cross-reference and external system entities.
- Security model: the cross-reference duties and privileges.
- Integration operations: letting callers send their own keys.