Scenario: Return goods to a vendor and post the credit note
Goal. Send goods back to a vendor and get the money back in Accounts payable: create a purchase return order with the vendor's return authorization (RMA) number, confirm it, post the return shipment when the goods leave your warehouse, and post the vendor's credit note. Your system makes the calls; D365 moves the stock out and credits the vendor.
When to use. Defective, wrong or surplus goods that the vendor has agreed to take back, when the return is recorded in an external system (a quality or warehouse system). For the forward flow, see Receive and invoice a purchase order.
Prerequisites
- Security. The D365 user your Entra application is mapped to needs
MGCLatticeAccountsPayableServiceMaintain(dutyMGCLatticeIntegrationServiceOperationsDuty) forcreatePurchaseReturn,shipPurchaseReturn,creditPurchaseReturnandconfirmPurchaseOrder, andMGCLatticeAccountsPayableServiceView(dutyMGCLatticeIntegrationServiceQueryDuty) forgetPurchaseOrderStatus. The integration operator and administrator roles hold both. - The vendor's RMA number. D365 does not save a return order without one; the field holds 10 characters.
- Stock to ship. The return ships out of the warehouse on its line, so that warehouse must hold the
quantity (USMF: item
D0001at site1, warehouse11). When purchase order change management is on, the return order must be approved before it can be confirmed. - D365 configuration. The vendor (USMF
US-101) with a posting profile and a purchase order number sequence. A return reason code is optional; when you send one it must exist. - Lattice. A valid license for the write operations. To send your own keys, set up an external system and
send
VendAccountExternalKey, lineItemIdExternalKeyorPurchaseOrderIdExternalKeywithExternalSystem(see Cross-reference keys).
Steps
Calls are POST https://<your-environment>/api/services/MGCLatticeAccountsPayableServiceGroup/<ServiceClass>/<operation>
with an OAuth 2.0 client-credentials token and the request in _request. Use a new RequestId per step and the
same one when you retry it. DocumentId is always the return order number.
-
Create the return order with
createPurchaseReturn(MGCLatticePurchaseReturnService). The standard purchase order entity covers ordinary orders only, so this operation is how you create a return order through the API. Every line needsItemIdand a non-zeroQty; D365 stores return quantities negative. Name the warehouse the goods leave from withSiteIdandWarehouseId(or anInventDimId).{ "_request": { "RequestId": "8e2c4a17-5b9d-4f06-a3e1-c7d0b6f29a58", "LegalEntityId": "USMF","UserContext": "Admin", "VendAccount": "US-101", "ReturnItemNum": "RMA7788","Lines": [ { "ItemId": "D0001", "Qty": 1, "SiteId": "1", "WarehouseId": "11" } ] } }DocumentIdandPostedDocumentIdare the new return order number, for example00001063. AddReturnReasonCodeIdto set a return reason on the order. -
Confirm it with
confirmPurchaseOrder(MGCLatticePurchaseOrderPostingService). A return shipment needs a confirmed order. Send the whole order, withoutLines:{ "_request": { "RequestId": "1f6d3b80-a24e-4c97-8b5a-0e3d9c71f6a2", "LegalEntityId": "USMF","UserContext": "Admin", "PurchaseOrderId": "00001063", "PostingDate": "2026-10-07" } } -
Post the return shipment with
shipPurchaseReturn(MGCLatticePurchaseReturnService) when the goods leave.PackingSlipId, the return shipment number, is required. The shipment covers the whole return order.{ "_request": { "RequestId": "c4a90e2b-6d17-4b38-95f0-2e8b1a7c3d64", "LegalEntityId": "USMF","UserContext": "Admin", "PurchaseOrderId": "00001063", "PackingSlipId": "RS-00001063","PostingDate": "2026-10-07" } }PostedDocumentIdis the return shipment number. -
Post the credit note with
creditPurchaseReturn(MGCLatticePurchaseReturnService) when the vendor's credit note arrives.InvoiceId, the vendor's credit note number, is required. Once the return has shipped, the credit note is built from the shipped quantity.{ "_request": { "RequestId": "7b05e3d9-1c42-4a6f-b8e7-94d2f0a51c36", "LegalEntityId": "USMF","UserContext": "Admin", "PurchaseOrderId": "00001063", "InvoiceId": "RC-00001063","PostingDate": "2026-10-07" } }PostedDocumentIdis the credit note number. The credit is an open vendor transaction that offsets what you owe US-101.
How to verify
- Each step:
Successtrue,Status3,DocumentId= the return order,PostedDocumentId= the created order, the shipment number or the credit note number. getPurchaseOrderStatus(MGCLatticePurchaseOrderPostingService,DocumentId= the return order) works for return orders too:StatusDetailsgainsConfirmDate, thenReceiptDateafter the shipment andInvoiceDateafter the credit note. The standardPurchaseOrderHeadersV2entity does not list return orders, so use this query, not the entity, to read a return back.- In D365: Procurement and sourcing > Purchase orders > All purchase orders lists the order with purchase type Returned order; its product receipt and invoice journals hold the shipment and the credit note.
- The Purchase return order created business event fires when the return order is created, if you have activated it.
When it goes wrong
ErrorCode arrives as an integer (1 ValidationFailed, 2 DocumentNotFound, 3 InvalidStatus, 4 BusinessRule).
- Create,
ValidationFailed:ReturnItemNummissing, no lines, a line withoutItemId, or a line whoseQtyis missing or 0 (a quantity is never defaulted).VendAccountmissing isValidationFailedtoo; an unknown vendor isDocumentNotFound. - Create,
BusinessRule: D365's own validation refused the order or a line; the reason is inErrors. Nothing is created. - Ship,
InvalidStatus, "must be confirmed before it can be shipped": run step 2 first. The message also names the order's approval status, so you can tell an order still waiting for change-management approval. - Ship or credit,
InvalidStatus, "is not a return order":PurchaseOrderIdnames an ordinary purchase order. Use Receive and invoice a purchase order for those. - Ship or credit,
ValidationFailed:PackingSlipId(ship) orInvoiceId(credit) is missing, orPurchaseOrderIdis missing. - Ship or credit,
BusinessRule, "posted nothing": there was nothing to post, for example the return was already shipped or credited. - Ship or credit,
BusinessRule, other: D365 refused the posting itself, for example not enough stock in the warehouse or a credit note number already used for the vendor. The D365 message is inErrors; fix the cause and send the step again (a failed request is not recorded, so itsRequestIdruns again). DocumentNotFound: no such order inLegalEntityId.- Preview and retries:
PreviewMode: trueis refused withPreviewUnsupported. Resending a step with the sameRequestIdreturns the recorded result and never creates or posts twice;TransientRuntimeandRequestInProgressare safe to retry that way.
Reference
- API reference: sections 6 (Return Order Services), 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 vendor, item and order keys
- Purchase return order created event
- Related: Receive and invoice a purchase order, Pay vendors