Skip to main content

Scenario: Post a vendor prepayment invoice for a purchase order

Goal. A vendor asks for part of an order's price up front, a deposit or advance, and sends a prepayment invoice for it. Your procurement or invoice-capture system posts that invoice against the purchase order from outside D365, as the order's Prepayment and Invoice > Prepayment invoice actions do: the order gets its prepayment (a percentage of the order total or a fixed amount), and the prepayment is posted as a vendor invoice of type prepayment under the vendor's invoice number. The prepayment can then be paid, and later applied to the order's final invoice.

When to use. Purchase orders with prepayment terms, before the goods arrive and before the order's first invoice. To pay a vendor in advance without a prepayment invoice, record the payment as a prepayment line marked against the order (Pay vendors, Part C). The order's regular receipt and invoice follow Receive and invoice a purchase order.

Prerequisites​

  1. Security. MGCLatticeAccountsPayableServiceMaintain, which also grants the order's confirmation, receipt and invoice, grants postPurchasePrepaymentInvoice and its batch variant. It is in duty MGCLatticeIntegrationServiceOperationsDuty (integration operator and administrator roles). The read-back entity VendInvoiceJourBiEntities is a standard entity and needs D365's own privileges. See Security model.
  2. D365 configuration in the legal entity:
    • a Purchase prepayment account in the inventory posting (Inventory management > Setup > Posting > Posting, Purchase order tab). USMF has one rule for all items and vendors;
    • posting definitions turned off in the general ledger parameters: prepayments are not available with them;
    • a procurement category for the prepayment that is not the category of any line of the order (USMF Training, in hierarchy "Procurement - Office Supplies");
    • the vendor (USMF US-101) not on hold for invoicing.
  3. The purchase order. An order of type Purchase order (USMF 00001042: 10 x D0001 at 50.00 USD) that is not in review or finalized, is not intercompany, and has no posted invoice yet.
  4. Lattice. A valid license (an expired or invalid one refuses the call with LicenseNotValid). To name the order by your own key, send PurchaseOrderIdExternalKey with ExternalSystem (Use your own keys).

Steps​

The operation is postPurchasePrepaymentInvoice on MGCLatticePurchaseOrderPostingService in service group MGCLatticeAccountsPayableServiceGroup. Send a POST with an OAuth 2.0 bearer token and the request in _request (see Trial and day-one guide).

  1. Post the prepayment invoice. Name the order, the vendor's invoice number, the prepayment and its category:

    POST https://<your-environment>/api/services/MGCLatticeAccountsPayableServiceGroup/MGCLatticePurchaseOrderPostingService/postPurchasePrepaymentInvoice
    {
    "_request": {
    "RequestId": "c2f8a4d6-1e3b-4a7c-9d05-6b8e2f4a1c39",
    "LegalEntityId": "USMF",
    "UserContext": "Admin",
    "PurchaseOrderId": "00001042",
    "VendorInvoiceNumber": "PP-0001",
    "PrepaymentPercent": 10,
    "PrepaymentCategoryName": "Training",
    "PostingDate": "2026-10-08"
    }
    }
    • The prepayment. Send PrepaymentPercent (greater than 0, at most 100, of the order total) or PrepaymentAmount (a fixed amount in the order currency, at most the order total), not both. PrepaymentDescription is optional. When the category name exists in several procurement category hierarchies, add PrepaymentCategoryHierarchyName.
    • An order that already has a prepayment (set up on the order in D365, for example) is invoiced for it: leave the prepayment members out, or send the same values. A different percentage, amount or category is refused; change the prepayment on the order in D365.
    • The invoice. VendorInvoiceNumber is required and becomes the posted invoice number, with the usual duplicate checks. InvoiceDate defaults as on a vendor invoice; PostingDate defaults to today.

    The prepayment and its invoice are created and posted in one transaction: a failed posting leaves neither behind.

  2. Read the result. DocumentId is the purchase order and PostedDocumentId the voucher of the posted prepayment invoice. The message names the invoice, amount and voucher, for example Prepayment invoice PP-0001 of 50.00 USD was posted for purchase order 00001042 on voucher APINV000213. The whole prepayment still available to invoice is invoiced, so a second call for the same order is refused.

  3. Pay the prepayment like any other vendor invoice, for example with Pay vendors.

  4. Receive the goods and apply the prepayment to the final invoice. Post the product receipt as usual (Receive and invoice a purchase order). To have the prepayment reduce the order's final invoice, enter that invoice as a pending vendor invoice in D365, use Apply prepayment on it, and post it (Post a pending vendor invoice).

The bulk variant postPurchasePrepaymentInvoiceBatch takes { "_requests": [ ... ] } and answers one result per item. The operation is synchronous only and has no preview.

How to verify​

  • The response: Success true, Status 3, DocumentId the order, PostedDocumentId the voucher.
  • The invoice: VendInvoiceJourBiEntities lists it as a prepayment invoice, for example GET https://<your-environment>/data/VendInvoiceJourBiEntities?cross-company=true&$filter=dataAreaId eq 'usmf' and PurchId eq '00001042' and InvoiceId eq 'PP-0001'&$select=InvoiceType,LedgerVoucher,InvoiceAmount returns InvoiceType VendorAdvance and the returned voucher in LedgerVoucher.
  • The vendor: LatticeVendorTransactions (filter on VendorAccountNumber and InvoiceId eq 'PP-0001') shows the open prepayment invoice.
  • In D365: open the order (Procurement and sourcing > Purchase orders > All purchase orders); Purchase > Prepayment shows the prepayment with nothing left available to invoice. The invoice journal (Accounts payable > Inquiries and reports > Invoices > Invoice journal) shows the invoice as a prepayment invoice on the returned voucher.
  • The call: System administration > Inquiries > Lattice > Services > Service call log, or LatticeServiceCallLogs filtered on your RequestId.

When it goes wrong​

A failed call answers Success false, Status 4, an ErrorCode and the message "Prepayment invoice posting failed due to validation or business rule constraints."; the reasons are in Errors. Nothing is created.

ErrorCodeTypical cause (text in Errors)What to do
ValidationFailed (1)No VendorInvoiceNumber; "Send either PrepaymentPercent or PrepaymentAmount, not both."; "Purchase order ... has no prepayment yet: send PrepaymentPercent or PrepaymentAmount." (or PrepaymentCategoryName); a value not greater than zero or a percentage above 100; a fixed amount above the order total; an unknown category, or one that exists in several hierarchies ("... send PrepaymentCategoryHierarchyName."); a category used on the order's lines; "Purchase order ... already has a prepayment (...). Send the same prepayment or none to invoice it; change it on the purchase order in D365."Correct the request and resend.
DocumentNotFound (2)Unknown purchase orderCheck the order number and LegalEntityId.
InvalidStatus (3)The order is not of type Purchase order, is in review or finalized, is intercompany, "already has a posted invoice", "has a pending prepayment invoice ...", "has no prepayment left to invoice", or its vendor is on hold for invoicingA prepayment invoice is possible only before the order's first invoice. Post or delete a pending prepayment invoice in D365 first.
ConfigurationMissing (11)"Purchase order prepayments are not available in legal entity ... because posting definitions are enabled in the general ledger parameters."Prepayments need posting definitions turned off.
BusinessRule (4)D365 refused the posting, for example a vendor invoice number already used or no Purchase prepayment account (its messages in Errors)Fix the cause, then resend.
PreviewUnsupported (10)PreviewMode trueSend without PreviewMode. Nothing was run.
TransientRuntime (6)A runtime fault; IsRetryable trueResend with the same RequestId.
LicenseNotValid (12)The Lattice license is expired or invalidRenew the license, then resend.

Retries are safe. Resending a successful request with the same RequestId posts nothing again: the answer repeats the original voucher with the message Duplicate request detected. Original request processed at ....

Reference​