cXML PunchOutOrderMessage
Message that closes a punchout session and transfers the cart the user built at the supplier back to the buyer's ERP. Posted by the browser, not the supplier server — a critical detail of the flow.
Purpose
When the user clicks "Checkout" inside the supplier catalog, the supplier does not
post the cart server-to-server. It generates an HTML page with a hidden
<form> containing the PunchOutOrderMessage cXML and
submits that form from the user's browser, which relays it to the
BrowserFormPost URL announced by the ERP at setup.
The ERP correlates the returned cart with the original request via the
BuyerCookie — that is the only link between the
PunchOutSetupRequest and this message. The PunchOutOrderMessage
is not an order in the cXML sense: it is a cart that will be converted into
an OrderRequest after internal ERP approval.
XML structure
The DTD declares: PunchOutOrderMessage (BuyerCookie,
PunchOutOrderMessageHeader, ItemIn*). The useful content is therefore three
blocks: the cookie that correlates the session, a header that summarises totals,
and the list of items the user put in the cart.
The PunchOutOrderMessageHeader is declared as (SourcingStatus?,
Total, ShipTo?, Shipping?, Tax?, SupplierOrderInfo?). Only Total
is required by content. The operationAllowed attribute is
#REQUIRED and signals what the buyer can do with the cart later:
create (use as-is), inspect (read-only revisit) or
edit (reopen for modification — implies the supplier stores state to
be able to restore it).
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.069/cXML.dtd">
<cXML payloadID="260513.150500.poom@supplier.example"
timestamp="2026-05-13T15:05:00+00:00"
version="1.2.069">
<Header>
<From>
<Credential domain="DUNS"><Identity>987654321</Identity></Credential>
</From>
<To>
<Credential domain="DUNS"><Identity>123456789</Identity></Credential>
</To>
<Sender>
<Credential domain="DUNS">
<Identity>987654321</Identity>
<SharedSecret>shared-secret-here</SharedSecret>
</Credential>
<UserAgent>supplier-catalog/3.2</UserAgent>
</Sender>
</Header>
<Message>
<PunchOutOrderMessage>
<BuyerCookie>session-abc-12345</BuyerCookie>
<PunchOutOrderMessageHeader operationAllowed="edit">
<Total>
<Money currency="USD">129.97</Money>
</Total>
<ShipTo>
<Address>
<Name xml:lang="en">Acme Corp — London site</Name>
<PostalAddress>
<Street>10 Cheapside</Street>
<City>London</City>
<PostalCode>EC2V 6AA</PostalCode>
<Country isoCountryCode="GB">United Kingdom</Country>
</PostalAddress>
</Address>
</ShipTo>
</PunchOutOrderMessageHeader>
<ItemIn quantity="3" lineNumber="1">
<ItemID>
<SupplierPartID>SKU-A100</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice><Money currency="USD">29.99</Money></UnitPrice>
<Description xml:lang="en">Ergonomic office chair, black</Description>
<UnitOfMeasure>EA</UnitOfMeasure>
<Classification domain="UNSPSC">56101504</Classification>
<ManufacturerName>Acme Furniture</ManufacturerName>
</ItemDetail>
</ItemIn>
<ItemIn quantity="2" lineNumber="2">
<ItemID>
<SupplierPartID>SKU-B200</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice><Money currency="USD">20.00</Money></UnitPrice>
<Description xml:lang="en">Adjustable footrest</Description>
<UnitOfMeasure>EA</UnitOfMeasure>
<Classification domain="UNSPSC">56121601</Classification>
<ManufacturerName>Acme Furniture</ManufacturerName>
</ItemDetail>
</ItemIn>
</PunchOutOrderMessage>
</Message>
</cXML> Required vs optional
In the message body: BuyerCookie and
PunchOutOrderMessageHeader are required (cardinality 1).
ItemIn* is optional but in practice always present — that is the point
of the message. An empty cart is theoretically allowed (user leaves without buying)
but unusual.
On PunchOutOrderMessageHeader: operationAllowed is
#REQUIRED, quoteStatus defaults to "final"
(alternative: "pending"). The content requires a Total;
ShipTo, Shipping, Tax,
SourcingStatus and SupplierOrderInfo are optional.
On each ItemIn: quantity is #REQUIRED,
lineNumber is #IMPLIED (but almost always supplied). The
content requires ItemID and ItemDetail.
ItemDetail requires UnitPrice, at least one
Description, UnitOfMeasure and at least one
Classification.
Common patterns
The browser-as-courier design is not a detail: the supplier server
never sees the final form of the BrowserFormPost URL (it may sit behind
an internal buyer load balancer). The supplier also does not sign the request at
the HTTP layer — the cXML payload itself carries the credentials, and the ERP
authenticates via the shared SharedSecret and the
BuyerCookie.
A punchout cart is self-contained: no reference to any prior
OrderRequest. Each ItemIn must carry the price, description, unit and
classification. The ERP uses that data to build its own OrderRequest
after approval.
Implementation tip: also emit a supplier-side identifier in
SupplierOrderInfo so you can correlate the later
OrderRequest with this punchout cart.
Punchout flow (final leg)
The PunchOutOrderMessage is stage 2 of the full flow:
Buyer (ERP) User's browser Supplier (catalog)
│ │ │
│ │ (active web session) │
│ │◄─────────────────────────────────┤
│ │ │
│ │ user clicks "Checkout" │
│ │ │
│ │ 1. generate PunchOutOrderMessage
│ │ with BuyerCookie + ItemIn* │
│ │◄─────────────────────────────────┤
│ │ │
│ 2. HTTP POST from browser ► BrowserFormPost URL (cXML body)│
│◄═════════════════════════╪ │
│ │ │
│ 3. ERP correlates via BuyerCookie, loads the cart │
│ 4. internal approval workflow, then... │
│ │ │
│ 5. OrderRequest (server-to-server) │
├──────────────────────────────────────────────────────────► │ Documentation
- Fulfill.dtd — current version
— search for
ELEMENT PunchOutOrderMessageandELEMENT PunchOutOrderMessageHeader. - cXML Reference Guide (PDF) — Punchout chapter, browser-relay return mechanics.
- PunchOutSetupRequest
— the opener that defines the
BuyerCookieandBrowserFormPostURL.