Skip to main content

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​

  1. Security.

    • Using keys in a request needs only the operation's own privilege.
    • Registering an external system and writing keys needs MGCLatticeCrossReferenceMaintainDuty (administrator role), or MGCLatticeExternalSystemMaintain plus the module's Maintain privilege, for example MGCLatticeCrossReferenceAccountsReceivableMaintain for customers, sales orders and free text invoices.
    • Reading keys needs MGCLatticeCrossReferenceViewDuty (operator and read-only roles).

    See Security model.

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

  3. The client is connected (Connect an integration client).

Steps​

  1. 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 (no dataAreaId; 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 Active No, 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.

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

  3. Store the keys. Each record kind has its own entity, keyed by the record's business key plus ExternalSystem, with the key in ExternalKey. For a webshop order number on USMF sales order 000698, POST https://<your-environment>/data/LatticeSalesOrderCrossReferences:

    { "dataAreaId": "usmf", "SalesOrderNumber": "000698", "ExternalSystem": "SHOP", "ExternalKey": "SHOP-100045" }

    Other examples: LatticeCustomerCrossReferences (CustomerAccount US-001), LatticeVendorCrossReferences (VendorAccountNumber), LatticeReleasedProductCrossReferences (ItemNumber D0001), LatticeLedgerJournalCrossReferences (JournalBatchNumber). A record holds at most one key per external system. To change a key, PATCH the row; an empty ExternalKey clears it and DELETE removes it. Add ?cross-company=true to a PATCH or DELETE whose key names a dataAreaId other 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.

  4. Send the key in a request. Put ExternalSystem on the request header and the key in the ...ExternalKey member next to the id it replaces. Preview first where the operation has a preview. confirmSalesOrder on MGCLatticeSalesOrderPostingService (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; SalesOrderId may be left out. If you send both, they must name the same order. Send the same request with PreviewMode false (or left out) to confirm for real; a preview does not use up its RequestId. Line keys (for example a line's ItemIdExternalKey) use the header's ExternalSystem. Keys resolve in the request's legal entity.

    The key members by service (full list in Cross-reference keys):

    ServiceKey members
    Sales order posting (confirm, packing slip, invoice)SalesOrderIdExternalKey
    Sales order capture (createSalesOrder)CustAccountExternalKey; line ItemIdExternalKey
    Price inquiry (resolveSalesPrice)CustAccountExternalKey, ItemIdExternalKey
    Purchase order postingPurchaseOrderIdExternalKey
    Return ordersSalesOrderIdExternalKey, PurchaseOrderIdExternalKey, CustAccountExternalKey, VendAccountExternalKey; line ItemIdExternalKey
    Transfer order postingTransferOrderIdExternalKey; line ItemIdExternalKey, LineNumExternalKey
    Production order postingProdIdExternalKey; pick list line ItemIdExternalKey
    Purchase requisitionsPurchReqIdExternalKey
    Free text invoiceInvoiceAccountExternalKey (post), InvoiceRecIdExternalKey (cancel)
    Payment journals and settlementsAccountNumExternalKey
    Inventory journals, vendor invoice journal, fixed assets, projects, trade agreementssee Cross-reference keys
    Status queriesDocumentIdExternalKey

    Not covered: the Lines of 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.

  5. Query by key. The status queries take ExternalSystem and DocumentIdExternalKey in place of DocumentId; getSalesOrderStatus with "ExternalSystem": "SHOP" and "DocumentIdExternalKey": "SHOP-100045" returns the status of order 000698 (Track documents and read data).

  6. Receive keys back. Business events about a covered record carry a crossReferences array of externalSystem / externalKey pairs (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 with ExternalSystem SHOP and ExternalKey SHOP-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 Success true and PreviewApplied true; the real call returns the D365 order number in DocumentId and the confirmation in PostedDocumentId.
  • The service call log (LatticeServiceCallLogs) records the call with the D365 DocumentId.

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.

MessageCauseWhat to do
"External key SHOP-100045 needs an external system."...ExternalKey sent without ExternalSystemAdd 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 deletedStore 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 keysRemove 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 recordsSend only the key, or make them agree.
"Key ... refers to a line of ..., not of ..."A line key names a line of another documentCorrect the line key or the document.
  • Price inquiry. resolveSalesPrice answers an unresolved key with Success false and ErrorCode ValidationFailed in 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 dataAreaId is refused.
  • An external system cannot be deleted while any legal entity holds keys or settings for it; set it inactive instead.

Reference​