Scenario: Receive and invoice a purchase order
Goal. Take a purchase order through the vendor side of procure-to-pay: confirm it to the vendor, post the product receipt when goods arrive (all of them or only part), post the vendor's invoice for what was received, and read the order's progress back at each step. Your warehouse or AP system makes the calls; D365 posts the documents.
When to use. Any purchase order whose receipt and invoice are recorded outside D365, for example a warehouse system that scans deliveries or an invoice-capture tool that reads vendor invoices. The order can come from an approved requisition (Turn a purchase requisition into a purchase order) or be created directly. To pay the posted invoice, continue with Pay vendors; for goods going back to the vendor, see Return goods to a vendor. To take back a product receipt posted in error, see Cancel a posted product receipt; for a prepayment the vendor invoices up front, see Post a vendor prepayment invoice for a purchase order; for invoices entered as pending vendor invoices, see Post a pending vendor invoice.
Prerequisites
- Security. The D365 user your Entra application is mapped to needs
MGCLatticeAccountsPayableServiceMaintainforconfirmPurchaseOrder,postPurchasePackingSlipandinvoicePurchaseOrder(dutyMGCLatticeIntegrationServiceOperationsDuty), andMGCLatticeAccountsPayableServiceViewforgetPurchaseOrderStatus(dutyMGCLatticeIntegrationServiceQueryDuty). The integration operator and administrator roles hold both. Creating and reading the order through the standard entities (PurchaseOrderHeadersV2,PurchaseOrderLinesV2and the read-back entities below) needs D365's own privileges for those entities. - D365 configuration. The vendor (USMF
US-101) with a posting profile; a purchase order number sequence; a receiving site and warehouse on each line (a product receipt without a warehouse posts nothing); and, when purchase order change management is on, an approved order before it is confirmed. The vendor's invoice number must be new for that vendor and, unless extended invoice numbers are enabled, at most 20 characters. - Lattice. A valid license for the posting operations. To send your own order keys instead of D365 order
numbers, set up an external system and send
PurchaseOrderIdExternalKeywithExternalSystem(see Cross-reference keys).
Steps
All four operations belong to MGCLatticePurchaseOrderPostingService in MGCLatticeAccountsPayableServiceGroup:
POST https://<your-environment>/api/services/MGCLatticeAccountsPayableServiceGroup/MGCLatticePurchaseOrderPostingService/<operation>,
OAuth 2.0 client-credentials token, request in _request. Use a new RequestId for each step and the same one
when you retry that step. In each posting response DocumentId is the purchase order and PostedDocumentId
the document the step posted.
-
Have an open purchase order and know its line numbers. To create one,
POSTa header tohttps://<your-environment>/data/PurchaseOrderHeadersV2:{ "dataAreaId": "USMF", "OrderVendorAccountNumber": "US-101", "CurrencyCode": "USD" }and a line to
https://<your-environment>/data/PurchaseOrderLinesV2with the returnedPurchaseOrderNumber:{ "dataAreaId": "USMF", "PurchaseOrderNumber": "00001042", "LineNumber": 1, "ItemNumber": "D0001","OrderedPurchaseQuantity": 10, "PurchasePrice": 50, "ReceivingSiteId": "1", "ReceivingWarehouseId": "11" }The posting requests name order lines by
LineNum, the line'sLineNumberinPurchaseOrderLinesV2. -
Confirm the order with
confirmPurchaseOrder. A confirmation always covers the whole order, so send noLines:{ "_request": { "RequestId": "6b1e0d47-2c8a-4f53-9e61-0d4c7a2b8f15", "LegalEntityId": "USMF","UserContext": "Admin", "PurchaseOrderId": "00001042", "PostingDate": "2026-10-07" } }PostedDocumentIdis the confirmation number. -
Post the product receipt with
postPurchasePackingSlip.PackingSlipIdis the receipt number from the delivery note and is required. WithLines, only the named lines and quantities are received; withoutLines, everything not yet received is. Half of the line arrived:{ "_request": { "RequestId": "f03a9c12-7d4b-4e8f-b2a6-5c1e9d07a3b4", "LegalEntityId": "USMF","UserContext": "Admin", "PurchaseOrderId": "00001042", "PackingSlipId": "GRN-104201","PostingDate": "2026-10-07", "Lines": [ { "LineNum": 1, "ItemId": "D0001", "Qty": 5 } ] } }PostedDocumentIdisGRN-104201. The other 5 stay open on the order. -
Post the vendor invoice with
invoicePurchaseOrder.InvoiceIdis the vendor's invoice number and is required. An order with product receipts is invoiced from them: either send noLines(everything received and not yet invoiced is invoiced), or send every line that has a received, uninvoiced quantity with exactly that quantity:{ "_request": { "RequestId": "2c7d5e90-41af-4b6c-8d03-e9a1f6b42c7d", "LegalEntityId": "USMF","UserContext": "Admin", "PurchaseOrderId": "00001042", "InvoiceId": "VINV-88412","PostingDate": "2026-10-07", "Lines": [ { "LineNum": 1, "ItemId": "D0001", "Qty": 5 } ] } }PostedDocumentIdisVINV-88412. An order without product receipts is invoiced for its ordered quantity, or for the lines and quantities you send. -
Check progress with
getPurchaseOrderStatus(same service and group; read-only, no idempotency):{ "_request": { "RequestId": "9a4f2b18-6e3c-4d71-a05b-3f8c2e6d1b90", "LegalEntityId": "USMF", "DocumentId": "00001042" } }DocumentStatusis the order's status (Backorder,Received,Invoiced,Canceled).StatusDetailslistsPurchStatusandOrderAccount, thenConfirmDate,ReceiptDateandInvoiceDate(asyyyy-MM-dd) once a confirmation, receipt or invoice exists. After this partial receipt and invoice the order is stillBackorder, because 5 are open. -
Repeat steps 3 and 4 for the rest of the delivery, each with a new receipt number, invoice number and
RequestId.
How to verify
- Each posting step:
Successtrue,Status3,DocumentId= the order,PostedDocumentId= the confirmation, the receipt number you sent, or the invoice number you sent. getPurchaseOrderStatusshows theConfirmDate,ReceiptDateandInvoiceDatedetails.- The posted quantities, through the standard entities (add
dataAreaId eq 'USMF'andcross-company=true):PurchaseOrderConfirmationLines(OrderedPurchaseQuantitybyPurchaseOrderNumberandLineNumber),ProductReceiptLines(ReceivedPurchaseQuantitybyPurchaseOrderNumber,PurchaseOrderLineNumberandProductReceiptNumber) andVendInvoiceTransBiEntities(QtybyPurchID,PurchaseLineLineNumberandInvoiceId). - In D365: Procurement and sourcing > Purchase orders > All purchase orders, open the order; its confirmation, product receipt and invoice journals are listed from the action pane.
- Resending a step with the same
RequestIdreturns the samePostedDocumentIdand posts nothing again.
When it goes wrong
ErrorCode arrives as an integer (1 ValidationFailed, 2 DocumentNotFound, 4 BusinessRule, 10
PreviewUnsupported); Errors carries the D365 messages. Request checks fail before anything is posted.
ValidationFailedon confirm, "send the request without Lines": a purchase order confirmation cannot confirm part of an order. Send the request withoutLines.ValidationFailed,PackingSlipIdorInvoiceIdrequired: send the receipt or invoice number.ValidationFailed, "only ... is left to post": the quantity is more than the line has left to receive (or to invoice). Read the order's lines and send at most the open quantity.ValidationFailedon invoice, "must name every line with a received, uninvoiced quantity": the order has product receipts, so the invoice must cover exactly what was received and not invoiced. Send noLines, or correct the quantities.ValidationFailed, line not found or does not match:LineNumnames no line of the order, or theItemIdyou sent with it is not that line's item.DocumentNotFound: no such purchase order inLegalEntityId.BusinessRule, "posted nothing": D365 found nothing to post, for example the order is not confirmed yet, has no open quantity, or waits for change-management approval.BusinessRule, receipt or invoice number "already used": that number was posted before for the vendor. Use the vendor's real, new number.- Preview:
PreviewMode: trueis refused withPreviewUnsupported; these operations have no preview. - Retries:
TransientRuntimeandRequestInProgressare safe to retry with the sameRequestId. A request stopped mid-flight for more than an hour answersRequestNeedsReview: check in D365 whether the document posted, then have an operator close the claim (see Idempotency reconcile runbook).
Reference
- API reference: sections 2 (Purchase Order Posting Service) and 20 (Status Query Operations)
- Endpoint payload specification: request payloads per operation
- Security model: privileges, duties and roles
- Cross-reference keys: sending your own order keys
- Posting preview: which operations have a preview
- Integration operations: service call log and test console
- Related: Turn a purchase requisition into a purchase order, Pay vendors, Return goods to a vendor