PunchOut
cXML PunchOut explained: the documents, in the order they travel
A cXML PunchOut session is three XML documents: a setup request from the procurement system to your store, a setup response with a start URL, and an order message that carries the cart back through the buyer's browser. The purchase order, the confirmation, the ship notice and the invoice follow as four more.
Updated
What cXML is
cXML, commerce XML, is an XML vocabulary for procurement documents between a buying organization and a supplier. The procurement system of the buyer sends the session request and the purchase order; the supplier sends the cart, the confirmation, the ship notice and the invoice. The format is published at cxml.org. The current reference guide is version 1.2.071 of August 14, 2026, published by SAP; the facts on this page were checked against it on October 3, 2026.
Every document has the same envelope:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.071/cXML.dtd">
<cXML payloadID="1791032580.7731.41893@procure.bakker.example"
timestamp="2026-10-03T09:03:00-04:00">
<Header>...</Header>
<Request deploymentMode="production">...</Request>
</cXML>
payloadIDis unique per document and stays the same when the document is sent again. The recommended form is date and time, process id and a random number, then@and the host name.timestampis ISO 8601 with a UTC offset. TheZdesignator is not allowed.deploymentModeistestorproduction. Production is the default.- The body is a
Request, aResponseor aMessage. A request is posted from server to server and answered with a response in the same HTTP connection. A message is one-way and gets no answer.
The documents, in the order they travel
| # | Document | From | To | Transport |
|---|---|---|---|---|
| 1 | PunchOutSetupRequest |
procurement system | your endpoint | HTTPS POST |
| 2 | PunchOutSetupResponse |
your endpoint | procurement system | the answer to 1 |
| 3 | PunchOutOrderMessage |
your store | procurement system | form POST by the browser |
| 4 | OrderRequest |
procurement system | your order endpoint | HTTPS POST |
| 5 | ConfirmationRequest |
you | procurement system | HTTPS POST |
| 6 | ShipNoticeRequest |
you | procurement system | HTTPS POST |
| 7 | InvoiceDetailRequest |
you | procurement system | HTTPS POST |
Documents 1 to 3 are the session. The reference states that the session produces a quote, not a purchase order: the order exists once document 4 arrives. With SAP Ariba, documents 1, 2 and 4 pass through SAP Business Network, which authenticates the buyer and forwards them. Coupa sends the setup request straight to your endpoint. What the store has to do at each step is on the supplier checklist.
The setup request
A buyer at Bakker Installatie B.V. clicks your tile at 9:03 AM. The procurement system posts this:
<Header>
<From><Credential domain="NetworkId">
<Identity>bakker-installatie</Identity></Credential></From>
<To><Credential domain="NetworkId"><Identity>your-store</Identity></Credential></To>
<Sender>
<Credential domain="NetworkId"><Identity>bakker-installatie</Identity>
<SharedSecret>the-agreed-secret</SharedSecret></Credential>
<UserAgent>Procurement System 4.2</UserAgent>
</Sender>
</Header>
<Request deploymentMode="production">
<PunchOutSetupRequest operation="create">
<BuyerCookie>1CX3L4843PPZO</BuyerCookie>
<Extrinsic name="UserEmail">j.devries@bakker.example</Extrinsic>
<BrowserFormPost><URL>https://procure.bakker.example/return</URL></BrowserFormPost>
</PunchOutSetupRequest>
</Request>
| Part | What it is | What to do with it |
|---|---|---|
operation |
create for a new cart, edit to change an earlier one, inspect to view it, source for a request for quote |
On edit and inspect the earlier lines arrive as ItemOut elements; rebuild the cart from them |
BuyerCookie |
The only required element. Opaque, new in every session per the cXML reference; Coupa keeps one per user (see PunchOut for Coupa) | Store it and return it unchanged in the cart |
BrowserFormPost/URL |
Where the cart has to go | Store it with the session |
Contact, Extrinsic |
User name, email, cost center. Each buying organization configures its own | Use them when present; never depend on them |
ShipTo |
An address for delivery and price estimates | The delivery address that counts is on the purchase order |
SelectedItem |
The item the buyer clicked in its own search | Open that product. See Level 2 PunchOut |
Each element is walked through in the PunchOutSetupRequest.
The setup response
The answer holds a status and one URL:
<Response>
<Status code="200" text="OK"/>
<PunchOutSetupResponse>
<StartPage>
<URL>https://store.example.com/punchout/start?sid=9f2c41d8a07b</URL>
</StartPage>
</PunchOutSetupResponse>
</Response>
The procurement system sends the buyer's browser to that URL. It has to log the buyer in without a form and show the catalog and contract prices of that organization. The reference asks for a unique, temporary URL that refers to the session state and does not contain it, because many applications limit the length of a URL. An identifier that is not used expires fast, for example after five minutes, so a copied link opens nothing.
When the request cannot be accepted, the response holds a status and no PunchOutSetupResponse:
| Status | Text | When | Sent again by the buyer |
|---|---|---|---|
| 200 | OK | accepted | |
| 400 | Bad Request | the document parses and cannot be accepted | no |
| 401 | Unauthorized | the credentials in Sender are not recognized |
no |
| 406 | Not Acceptable | the XML does not validate | no |
| 450 | Not Implemented | the requested operation is not supported, for example edit |
no |
| 500 | Internal Server Error | the request could not be completed | yes |
The 400 range is permanent. The 500 range, and any answer that is not valid cXML, is transient: the reference recommends 10 retries, one per hour.
The order message (the cart)
The cart is the one document that travels through the buyer's browser. The store renders a page with a form whose action is the BrowserFormPost URL and whose single hidden field holds the whole document:
<form method="post" action="https://procure.bakker.example/return">
<input type="hidden" name="cXML-base64"
value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4K...">
</form>
The field is named cXML-urlencoded or cXML-base64. The reference calls base64 the best choice, since the browser then has no quotes or ampersands to interpret. Inside the document:
- The
Headercarries no shared secret, because the buyer can read the page source. The procurement system matches the cart to the session by theBuyerCookie. PunchOutOrderMessageHeaderhas anoperationAllowedattribute.createmeans the cart cannot be reopened,inspectallows viewing,editallows changes. ItsTotalexcludes tax and shipping.- Each
ItemInneeds aquantity, aSupplierPartID, aUnitPrice, aDescription, aUnitOfMeasureand aClassification. The unit is a UN/CEFACT code such asEA. A store that sends "each" gets its cart refused by systems that check the code list. SupplierPartAuxiliaryIDis yours to fill, for example with a cart reference. It comes back in aneditsession and in the purchase order.- A message without any
ItemIncancels the session. A cancel button in the store sends it.
A full ItemIn and the totals of a three-line cart are on the PunchOut hub.
The order request (the purchase order)
After approval the procurement system posts an OrderRequest to your order endpoint. Its header carries:
| Attribute or element | Content |
|---|---|
orderID |
The purchase order number of the buyer |
orderDate |
Date and time, ISO 8601 |
type |
new, update or delete. An update or delete points to the original through DocumentReference |
orderVersion |
1 for the original, plus 1 per change order |
requestedDeliveryDate |
When the buyer wants to receive the goods |
Total, BillTo |
Required. ShipTo, Shipping, Tax and Payment are optional |
The answer is a Response with a status and nothing else. A 200 says the order was received and parsed. It does not say which lines can ship; that is document 5.
The retry rule sets the time you have. The procurement system posts PO 4500001234 at 2:10 AM while your endpoint is down for maintenance. A system that follows the recommendation tries again at 3:10, 4:10 and so on. With the endpoint back at 5:30, the fourth retry at 6:10 delivers the order, 4 hours late. An endpoint that stays down longer than 10 retries of 1 hour, 10 hours, no longer receives the order from such a system until someone at the buyer sends it again by hand.
The reverse case is the duplicate. Your endpoint stores the order and the answer is lost on the way. The retry carries the same payloadID and the same orderID. An endpoint that keeps both answers the repeat with 200 and creates nothing. An update that the state of the order no longer allows, because it has shipped, gets 409 Conflict.
Confirmations, ship notices and invoices
| Document | Key content | Without it |
|---|---|---|
ConfirmationRequest |
A type such as accept, reject, backordered or detail, and a reference to the order |
The buyer assumes every line ships as ordered |
ShipNoticeRequest |
shipmentID, shipmentDate, deliveryDate, carrier and the lines in the shipment |
The buyer has no shipment to receive against |
InvoiceDetailRequest |
invoiceID, invoiceDate, the order it bills and a summary that equals the sum of the lines |
The invoice arrives on paper or as a PDF and is keyed in by hand |
Confirmations and ship notices validate against Fulfill.dtd, invoices against InvoiceDetail.dtd, so the DOCTYPE line of these documents differs from the one above. cxml.org describes the confirmation and the ship notice as the cXML analogues of the EDI 855 and 856. These three are your documents: you post them to an address of the buyer, with your identity in From and Sender and the buyer's in To.
Credentials: identity, domain, shared secret
| Element | Who it names | Used for |
|---|---|---|
From |
The buying organization | Finding the customer account |
To |
You | Routing by a network hub |
Sender |
The party that opened the HTTP connection, with the SharedSecret |
Authentication |
The domain attribute says which kind of identity it is. The reference names DUNS for a D-U-N-S number, NetworkId for an ID assigned by the network and AribaNetworkUserId for an email address. On SAP Business Network the assigned IDs in the reference's examples read like AN01000000001.
Sender is where direct and routed requests differ. Sent directly, From and Sender are both the buyer. Through a network hub, the hub verifies the buyer, replaces Sender with itself and inserts your own shared secret. A store that looks up the customer by the identity in Sender works with a direct buyer and fails with a routed one. The match that holds in both cases: check the secret in Sender, find the customer by From.
cXML next to OCI
OCI is SAP's protocol for the same session. The login travels through the browser as parameters, the cart returns as form fields named NEW_ITEM-<field>[n] with fixed lengths, and the order and the documents after it are not in the specification. A buyer on SAP asks for OCI; a buyer on Coupa or SAP Ariba asks for cXML. The two are compared part by part in cXML vs OCI, and the OCI fields are on the OCI page.
What this means for your store
A cXML connection is an endpoint, a session and four document types, each with rules that fail without a message on your side when they are missed. We build them on your existing store, host the endpoints and monitor every document: a 401 on a setup request, a cart without a purchase order and an order that was retried are all in the log.
The whole flow, including prices and the order in your ERP, is on the PunchOut hub. Tell us which procurement system your customer uses.
Frequently asked questions
What is the difference between cXML and XML?
XML is the syntax: elements, attributes and a document type definition. cXML is one vocabulary written in that syntax, for procurement documents. Its DTDs define which elements exist, in which order and with which attributes, so an OrderRequest from any procurement system has the same structure.
What is the difference between cXML and EDI?
Both carry orders, confirmations, ship notices and invoices between a buyer and a supplier. EDI X12 uses numbered transaction sets in a segment format, the 850, 855, 856 and 810. cXML uses XML documents over HTTPS, and it adds the PunchOut session, which EDI does not have. See PunchOut vs EDI.
Which procurement systems use cXML?
Coupa and SAP Ariba use cXML for PunchOut. SAP Ariba also routes purchase orders, confirmations, ship notices and invoices as cXML through SAP Business Network. SAP SRM uses its own protocol, OCI, for the session; the order that follows can still be a cXML document. For another system, ask the administrator at the buyer for a sample setup request: it shows the protocol and the fields at once.
Which cXML version does my endpoint have to support?
The version the buyer sends. Every document names its DTD in the DOCTYPE line, for example cXML/1.2.071/cXML.dtd, and the DTDs of all versions are published on cxml.org. The endpoint reads the elements listed on this page and passes over the ones it does not use, so a buyer on another 1.2 version is handled the same way.
Is the shared secret safe in an XML document?
It travels in documents that go from server to server over HTTPS, so the buyer's browser never sees it. The one document that passes through the browser, the PunchOutOrderMessage, is sent without it. On your side the secret is stored as a hash, like a password.
Tell us what you need
Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.
- You know the price and the timeline before you commit to anything
- We work out the connection that takes the work off your hands
- We handle the build, hosting, monitoring and maintenance
- Your team has less information to retype and fewer discrepancies to chase