Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunityDoc feedbackLog In
GitHubNuGetDev CommunityDoc feedback


This is article five, in a series of five articles:

  1. [PunchOut/cXML process and design](🔗)

  2. [PunchOut/cXML configuration and data requirements](🔗)

  3. [PunchOut setup request and response](🔗)

  4. [PunchOut order Message (that is Cart information)](🔗)

  5. Order request (that is Purchase Order)

As end users place orders in their procurement/ERP systems, their purchase orders are transmitted to Optimizely <<product-name>> via the cXML-based Order Request message. The Customer's Procurement system will technically connect to the Integration Partner's system, so that connection will be established between those two parties.

The Integration Partner will translate the Customer's Order Request message into Insite's standard cXML format and POST that cXML to a <<product-name>> endpoint. The endpoint will be located as follows, with a separate endpoint available for each domain setup within <<product-name>>:

`https://<DOMAIN>/punchout/punchoutorderrequest.isch`

The PO message should contain all of the necessary data elements to create a single order (such as order header and any line information). Each cXML message should only contain a single order with any number of lines. Each order received can only be shipped to a single location. Each order received will be considered a new order; <<product-name>> does not process order changes/updates.

<<product-name>> uses the cXML standard for the transmission and processing of purchase order (PO) information, specifically using the Order Request format. The PO would be sent from a customer's procurement system/ERP to <<product-name>> via the Integration Partner and <<product-name>> would process the cXML message and submit the order into the client's ERP for fulfillment.

## Order request message processing

Order Request cXML data will be composed of both order header and line-level information. Insite will translate the cXML into <<product-name>> CustomerOrder & OrderLine records that are used to submit the resulting order into the client's ERP for fulfillment. The following diagram provides a high-level overview of the general steps followed by the <<product-name>>:



### Identify Bill-To

Using the From Identity value found in the cXML (or potentially the BillTo addressID) and the Customer records attached to the PunchOut/cXML Customer User, the corresponding Bill-To will be assigned to the Customer Order. Also, the related CustomerOrder.BT\* fields will be populated from the <<product-name>> Customer Bill-To record.

Note

Refer to this article for the Bill-To identification logic: [PunchOut cXML configuration and data > requirements](🔗). It is found under the heading of cXML/PunchOut Users and Address ID > Mapping.

### Identify Ship-To

Using the Ship-To Address ID found in the cXML and the Customer records attached to the PunchOut/cXML Customer User, a <<product-name>> Ship-To record will be attached to the Customer Order. Also, the related CustomerOrder.ST\* fields will be populated from the Customer Ship-To record.

Note

For more information on Ship-To identification logic, reference this article: [PunchOut cXML configuration and data requirements](🔗). The specific reference is found under the heading of **cXML/PunchOut Users and Address ID Mapping**.

### Identify product

For each \<ItemOut> node in the cXML, a separate <<product-name>> OrderLine record will be created. Comparing various data elements in the cXML node and data within the <<product-name>> database, a Product record will attempt to be attached to the OrderLine record (that is OrderLine.ProductId). The following sequential logic is applied to determine the <<product-name>> Product, with the next step executing if the previous steps failed in finding a match. A failed match means that zero or 2+ <<product-name>> Product records are matched against a given data element.

  1. Product Lookup by \<SupplierPartID> cXML Field

    1. Match to Product.ErpNumber (that is ERP Product #)

    2. Match to CustomerProduct.Name (that is Customer Part #)

      Note

      The Bill-To Customer determined in the previous step will also be used to locate the Customer Part #.

    3. Match to Product.ManufacturerItem (that is Manufacturer part #)

  2. Item Lookup by Alternate cXML Fields

    1. Match \<Extrinsic name="BuyerId"> to CustomerProduct.Name (that is Customer Part #)

      Note

      The Bill-To Customer determined in the previous step will also be used to locate the Customer Part #.

    2. Match \<Extrinsic name="UPC"> to Product.UPCCode

    3. Match \<ManufacturerPartID> to Product.ManufacturerItem AND

    4. \<ManufacturerName> to Vendor.Name

      Note

      Product.VendorId joins Product to Vendor table

    5. Match \<ManufacturerPartID> to Product.ManufacturerItem

If a single <<product-name>> Product record is not located during the steps above, then the Item Not Found Product record (that is Application Setting: Punchout_NotOnFileProductName; see Section 1.2.4) is attached to the OrderLine record. When this occurs, the following OrderLine fields are still populated with data from the cXML document:

  • OrderLine.Line as any other line

  • OrderLine.QtyOrdered as any other line

  • OrderLine.UnitOfMeasure as any other line

  • OrderLine.Description from the \<Description> element; usually populated from the Product.ShortDescription

  • OrderLine.ActualPrice from the \<UnitPrice>\<Money> element, regardless of the price calculation setting

  • OrderLine.Notes populated with a list of cXML fields used for matching to an <<product-name>> Product - the list of cXML fields include supplierId, ManufacturerName, MfgPartNumber, BuyerId, and UPC

### Identify unit of measure

Once a given ItemOut Node has been mapped to a <<product-name>> Product record, the \<UnitOfMeasure> element is compared against the <<product-name>> Product.UnitOfMeasure and ProductUnitOfMeasure.UnitOfMeasure. If the cXML value does not match a value within <<product-name>>, then the OrderLine will be assigned with the Item Not Found Product.

### Identify quantity

The quantity attribute of the \<ItemOut> element will be used to determine the OrderLine.QtyOrdered value.

Identify Price

Depending on the User Custom Property attached to the PunchOut/cXML Customer User (that is Punchout_AcceptPriceProvided) Application Setting (that is Punchout_DefaultAcceptPriceProvided), the OrderLine price will be set directly from the cXML or will be recalculated within <<product-name>> using the given pricing rules used by the site. See Section 1.2.4 for further details around these settings.

If a PunchOut/cXML Customer User is configured to accept the price submitting in the cXML, then the \<UnitPrice>\<Money> value will be passed into the OrderLine.ActualPrice field.

If a PunchOut/cXML Customer User is configured to recalculate price, and the calculated price differs from the price sent in the cXML, then the cXML price will be written to an OrderLine Custom Property named "Unit Price Submitted".

If a Price cannot be determined, then the OrderLine will be assigned with the Item Not Found Product.

### Populate miscellaneous order header fields

In addition to the Bill-To & Ship-To data on the <<product-name>> CustomerOrder record, the following fields are explicitly mapped from the Order Request cXML message to the <<product-name>> CustomerOrder table:

  • Order Date

    • \<OrderRequestHeader orderDate> element & attribute populates <<product-name>> CustomerOrder.OrderDate

  • Customer PO

    • \<OrderRequestHeader>\<Extrinsic name="CustomerPO"> element populates <<product-name>> CustomerOrder.CustomerPO.

  • Requested Ship Date

    • \<OrderRequestHeader>\<Extrinsic name="RequestedShipDate"> element populates <<product-name>>

  • Ship Via

    • \<OrderRequestHeader>\<Extrinsic name="ShipVia"> element ultimately populates <<product-name>> CustomerOrder.ShipViaId, after executing a lookup against the <<product-name>> ShipVia.ERPShipCode field.

  • Order Header Notes

    • \<OrderRequestHeader>\<Comments> element populates <<product-name>> CustomerOrder.Notes

  • PDF Attachment

    • \<OrderRequestHeader>\<Extrinsic name="AttachmentFileType">PDF\</Extrinsic>

    • \<OrderRequestHeader>\<Extrinsic name="Attachment">\[BLOB\]\</Extrinsic>

    • The \[BLOB\] value sent in the cXML should be a base-64 version of the original PDF document. This data will be stored in the PunchOutOrderRequestExtrinsic table with a Name = 'PDFattachment' and the Value = \[BLOB\], but can be viewed as a PDF through the Admin Console. See Section 5.4 for detailed screenshots.

To accommodate for any other Order Header fields to be sent into the cXML and passed into the <<product-name>> system, the Application Setting "Punchout_OrderCustomPropertyFields" can be used. This setting will be populated with a comma-separated list of \<OrderRequestHeader> level extrinsic field names that will be mapped from the cXML into <<product-name>> Custom Properties of the CustomerOrder.

For example, the following extrinsic fields come over in the cXML:



<?xml version="1.0"?>



### Order request field mapping

The table below includes some of the most important cXML data elements required to process an order into a client's ERP. However, the sample cXML in the previous section contains additional format and field information.

<table class="TableStyle-Borders" style="margin-left: 0; margin-right: auto; width: 100%;" data-cellspacing="0"> <colgroup> <col style="width: 25%" /> <col style="width: 25%" /> <col style="width: 25%" /> <col style="width: 25%" /> </colgroup> <thead> <tr class="header TableStyle-Borders-Head-Header1"> <th colspan="4" class="TableStyle-Borders-HeadD-Regular-Header1"><p>Field Mapping: Purchase Order/Order Request</p></th> </tr> <tr class="odd TableStyle-Borders-Head-Header1"> <th class="TableStyle-Borders-HeadE-Regular-Header1"><p>Field Name</p></th> <th class="TableStyle-Borders-HeadE-Regular-Header1"><p>cXML Element/Attribute</p></th> <th class="TableStyle-Borders-HeadE-Regular-Header1"><p>Destination Commerce Table.Field</p></th> <th class="TableStyle-Borders-HeadD-Regular-Header1"><p>Notes</p></th> </tr> </thead> <tbody> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Payload ID</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;cXML payloadID&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Dynamic Unique Value</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>Unique value for each cXML document used for locating a particular cXML dataset.</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>From Identity</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;Header&gt;&lt;From&gt;&lt;Credential&gt;&lt;Identity&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Static Value</p> <p>Used to Set: CustomerOrder.CustomerID</p> <p>&amp; CustomerOrder.BT*</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>Represents the Customer from which the Order originated. From a business perspective, it will correlate with a client's Bill-To customer.</p> <p>This value will need to tie back to the Username field on a User record in the <<product-name>> platform, which will determine the Bill-To of the order.</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>To Identity</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;Header&gt;&lt;To&gt;&lt;Credential&gt;&lt;Identity&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Static Value</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>Represents the Client to which the Setup Request is sent. This will always be the client name, and does NOT tie back to a <<product-name>> Username.</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Sender Identity</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;Header&gt;&lt;Sender&gt;&lt;Credential&gt;&lt;Identity&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Static Value</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>Represents the system sending the message to <<product-name>>. From a process perspective, it will represent the client system sending the message to <<product-name>> (such as Integration Partner).</p> <p>This value will need to tie back to the Username field on a User record in the <<product-name>> platform.</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Sender Shared Secret</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;Header&gt;&lt;Sender&gt;&lt;Credential&gt; &lt;SharedSecret&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Static Password</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>The <<product-name>> password associated with the Username sent in the &lt;Header&gt;&lt;Sender&gt;&lt;Credential&gt;&lt;Identity&gt; field. Technically used to validate that the Setup Request sent to <<product-name>> is from a valid source.</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Order Date</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;OrderRequestHeader orderDate&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>CustomerOrder.OrderDate</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>?</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1">Bill-To Address?ID</td> <td class="TableStyle-Borders-BodyE-Regular-Row1">&lt;BillTo&gt;&lt;Address addressID&gt;</td> <td class="TableStyle-Borders-BodyE-Regular-Row1">CustomerOrder.CustomerId &amp;?CustomerOrder.BT*</td> <td class="TableStyle-Borders-BodyD-Regular-Row1">The BillTo addressID?may be optionally used to determine the Customer from which the order originated. This will only be used if a given Username is attached to multiple Bill-To records.</td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Ship-To Address ID</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;ShipTo&gt;&lt;Address addressID&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>CustomerOrder.ShipToID &amp; CustomerOrder.ST*</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>Using the Address ID to Customer Mapping table, locate the client's ERP ship-to and corresponding bill-to.</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Ship-To Address Info</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;ShipTo&gt;&lt;Address&gt;&lt;...&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>N/A</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>The actual ship-to address information submitted in the cXML is only used if an AddressID match is not made. If that is the case, then the cXML address data is submitted into the order notes.</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Customer Purchase Order #</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;OrderRequestHeader&gt; &lt;Extrinsic name="CustomerPO"&gt;</p> <p>?</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>CustomerOrder.CustomerPO</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1">?</td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Requested Ship Date</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;OrderRequestHeader&gt; &lt;Extrinsic name="RequestedShipDate"&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>CustomerOrder. RequestedShipDate</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>?</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Ship Via</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;OrderRequestHeader&gt; &lt;Extrinsic name="ShipVia"&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>CustomerOrder.ShipViaId</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>Using the cXML value, a match to ShipVia.ErpShipCode is made.</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Order Header Notes</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;OrderRequestHeader&gt; &lt;Comments&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>CustomerOrder.Notes</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>?</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Document Type</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;OrderRequestHeader&gt; &lt;Extrinsic name="AttachmentFileType"&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>N/A</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>?</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Document BLOB</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;OrderRequestHeader&gt; &lt;Extrinsic name="PDFattachment"&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>PunchOutOrderRequestExtrinsic. Name = ‘PDFattachment'</p> <p>PunchOutOrderRequestExtrinsic. Value = [BLOB]</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>Value is a base-64 version of the original PDF.</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Order Line #</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;ItemOut lineNumber&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>OrderLine.Line</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>?</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Order Quantity</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;ItemOut quantity&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>OrderLine.QtyOrdered</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>?</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Client's ERP Part #</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;ItemOut&gt;&lt;ItemID&gt;&lt;SupplierPartID&gt;</p> <p>OR</p> <p>&lt;ItemOut&gt;&lt;ItemDetail&gt;&lt;Extrinsic name="BuyerId"&gt;</p> <p>OR</p> <p>&lt;ItemOut&gt;&lt;ItemDetail&gt;&lt; Extrinsic name="UPC"&gt;</p> <p>OR</p> <p>&lt;ItemOut&gt;&lt;ItemDetail&gt;&lt;ManufactuerPartID&gt;</p> <p>&lt;ItemOut&gt;&lt;ItemDetail&gt;&lt;ManufacturerName&gt;</p> <p>OR</p> <p>&lt;ItemOut&gt;&lt;ItemDetail&gt;&lt;ManufactuerPartID&gt;</p> <p>OR Application Setting "Punchout_NotOnFileProductName"</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>OrderLine.ProductId</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>See Section 5.1 for further details on the sequencing &amp; logic around Identifying an <<product-name>> Product from the cXML data.</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Unit of Measure</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;ItemDetail&gt;&lt;UnitOfMeasure&gt;</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>OrderLine.UnitOfMeasure</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>?</p></td> </tr> <tr class="even TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>Unit Price</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>&lt;ItemDetail&gt;&lt;UnitPrice&gt;&lt;Money&gt;</p> <p>OR</p> <p><<product-name>>- Calculated</p></td> <td class="TableStyle-Borders-BodyE-Regular-Row1"><p>OrderLine.ActualPrice</p></td> <td class="TableStyle-Borders-BodyD-Regular-Row1"><p>See Section 5.1 for further details on how <<product-name>> will determine the price.</p></td> </tr> <tr class="odd TableStyle-Borders-Body-Row1"> <td class="TableStyle-Borders-BodyB-Regular-Row1"><p>Order Line Notes</p></td> <td class="TableStyle-Borders-BodyB-Regular-Row1"><p>&lt;ItemOut&gt;&lt;Comments&gt;</p></td> <td class="TableStyle-Borders-BodyB-Regular-Row1"><p>OrderLine.Notes</p></td> <td class="TableStyle-Borders-BodyA-Regular-Row1"><p>?</p></td> </tr> </tbody> </table>