How does a cXML punchout catalog work, message by message?
Short answer
In a cXML punchout, the buying system sends a PunchOutSetupRequest, the supplier answers with a start page, and the basket returns as a PunchOutOrderMessage for approval.
Key takeaways
- cXML (commerce eXtensible Markup Language) is an XML standard for business documents between buying systems and suppliers. Its current version, 1.2.071, is published at cxml.org with its document definitions and a reference guide.
- A cXML punchout session uses three documents: the PunchOutSetupRequest from the buying system, the PunchOutSetupResponse with the supplier’s start page, and the PunchOutOrderMessage that carries the basket back.
- The basket returns through the user’s browser as a hidden HTML form field, not as a server-to-server call, so it carries no password; the BuyerCookie ties it to the session that opened it.
- The basket is a quote, not an order. The supplier receives an order only when the approved requisition becomes a cXML OrderRequest, which is a separate capability to build.
- SAP’s Open Catalog Interface (OCI) does the same job with web form fields instead of XML documents, and static catalogues (CIF or cXML files) skip the live session entirely. Ask which one each buying system expects before building.
What is cXML, and where does punchout fit in it?
A cXML punchout catalog is a supplier’s web shop that a buying system opens and closes with cXML messages. cXML (commerce eXtensible Markup Language) is an XML standard for documents between buyers and suppliers; punchout is one of its transactions, next to purchase orders, order confirmations, ship notices and invoices.
The standard lives at cxml.org. The site publishes the document type definitions (DTDs), the files that set which elements a cXML document may contain and in what order, together with a Getting Started guide and a Reference Guide. The current version is 1.2.071, dated 14 August 2026; the Reference Guide for that version carries an SAP copyright line. Element names are case-sensitive: `PunchOutSetupRequest` is not `PunchoutSetupRequest`, and a strict parser rejects the second.
This page is for the people who build or test the connection: supplier developers, a buyer’s system team, an integrator. What a punchout catalogue is for the business, and how level 1 and level 2 differ, are explained in what is a punchout catalog.
The cXML guides also describe punchout chaining, through a marketplace and then a supplier, and provider punchout, which opens a remote service rather than a shop. This page covers the common case, procurement punchout: a requester shops on a supplier’s site and returns a basket.
Which messages make up a cXML punchout session?
A session has a short exchange at the start, a shopping phase with no cXML at all, and a return at the end. The cXML Reference Guide describes it as five steps. In the guide’s standard set-up, a network hub sits between buyer and supplier to check identities; a direct mode without the hub also exists.
- The requester clicks the supplier’s item or link in the buying system. The buying system posts a PunchOutSetupRequest over HTTPS, usually to the network hub, which checks the buyer and forwards the request to the supplier’s punchout address.
- The supplier’s site checks the request and replies, in the same HTTPS connection, with a PunchOutSetupResponse. It holds a status code (200 for success) and the URL of a start page.
- The buying system opens that start page in the requester’s browser. The requester searches, configures and fills a basket on the supplier’s site, with the buyer’s account and prices. No cXML moves during this phase.
- At checkout, the supplier’s page builds a PunchOutOrderMessage and the browser posts it, as a hidden form field, to the return address given in the setup request. The basket lands in the requisition.
- After the requisition is approved, the buying system sends an OrderRequest, the cXML purchase order, to the supplier, which answers with a Response and a status code.
| Document | From → to | How it travels | What it carries |
|---|---|---|---|
| PunchOutSetupRequest | Buying system → supplier (through the hub, or direct) | HTTPS POST; the reply comes in the same connection | Who is calling (Header), the session type (operation), the BuyerCookie, the return address (BrowserFormPost), user data (Extrinsic), optional ShipTo and SelectedItem |
| PunchOutSetupResponse | Supplier → buying system | Reply to the request | A Status code and StartPage, the URL the browser opens |
| PunchOutOrderMessage | Supplier → buying system, through the browser | HTML form POST, one-way, no credentials | The BuyerCookie, a header with the Total and operationAllowed, one ItemIn per basket line |
| OrderRequest | Buying system → supplier, after approval | HTTPS POST; the supplier returns a Response | OrderRequestHeader (order number, date, type) and one ItemOut per order line |
Three documents run the session; the order is a fourth that arrives only after approval, through a different endpoint on the supplier’s side.
Before any of this, a ProfileRequest asks which cXML transactions the supplier supports and at which addresses; the ProfileResponse lists them.
What does the PunchOutSetupRequest carry?
The setup request tells the supplier who is calling, what kind of session to open and where to send the basket back. A shortened example, with fictional values, in the shape of the Reference Guide’s sample:
<cXML payloadID="20261102.1234@buyer.example" timestamp="2026-11-02T09:15:00+00:00" xml:lang="en-US">
<Header>
<From><Credential domain="DUNS"><Identity>111111111</Identity></Credential></From>
<To><Credential domain="DUNS"><Identity>222222222</Identity></Credential></To>
<Sender>
<Credential domain="NetworkId">
<Identity>HUB-0001</Identity>
<SharedSecret>agreed-secret</SharedSecret>
</Credential>
<UserAgent>Buyer procurement system</UserAgent>
</Sender>
</Header>
<Request deploymentMode="test">
<PunchOutSetupRequest operation="create">
<BuyerCookie>A1B2C3D4</BuyerCookie>
<Extrinsic name="CostCenter">610</Extrinsic>
<BrowserFormPost><URL>https://buyer.example/punchout/return</URL></BrowserFormPost>
<SelectedItem><ItemID><SupplierPartID>OFFICE-STORE</SupplierPartID></ItemID></SelectedItem>
</PunchOutSetupRequest>
</Request>
</cXML>- From, To, Sender
- From is the buying organisation and To the supplier; they do not change on the way. Sender is the party that opened the connection and carries the strongest proof of identity. Each holds a Credential with a domain (such as DUNS or NetworkId), an Identity and, for Sender, a SharedSecret, the password agreed between the parties.
- operation
- create opens a new basket. edit reopens an earlier basket so it can be changed; the request then carries the existing lines as ItemOut elements. inspect reopens it read-only. source opens a session for a request for quotation in a sourcing application.
- BuyerCookie
- A value the buying system creates for the session. The supplier must return it in the order message, so the buying system can match the basket to the request that started it. It changes at every session, so it is not a customer identifier.
- BrowserFormPost
- The address where the browser will post the basket at checkout. Use the URL received in each request: it can change from one session to the next, as the guide’s own samples show.
- Extrinsic
- Extra named values the buyer chooses to send, such as the user’s email or cost centre. The supplier can use them to pick the right account, but the buyer configures which ones exist.
The hub check works with two secrets. The hub verifies the buyer’s identity and secret, then puts the supplier’s own shared secret in the Sender element before forwarding; the supplier trusts the request because it carries its own secret. In direct punchout, announced in the supplier’s ProfileResponse, the request goes straight to the supplier, authenticated by a message authentication code or a client certificate.
The edit operation matters more than it looks: a quantity changed after the basket returns is changed on the supplier’s site, because tax and freight may change with it. The Reference Guide calls this a re-punchout.
How does the basket come back in the PunchOutOrderMessage?
The supplier does not send the basket to the buyer’s server. Its checkout page holds an HTML form whose action is the BrowserFormPost address and whose hidden field, named cXML-urlencoded or cXML-base64, contains the whole PunchOutOrderMessage. The requester’s click on checkout makes the browser post it, so the buyer’s system needs no address open to the internet for returns.
Because the document passes through the browser, the user could read it, so the cXML guide says one-way messages must not carry shared secrets; the BuyerCookie does the matching instead. The cXML-urlencoded field must use plain ASCII characters, and the browser, not the supplier, URL-encodes it. Descriptions with accented letters or other scripts belong in the cXML-base64 field.
Inside the message, the PunchOutOrderMessageHeader carries the basket Total and an operationAllowed attribute, which sets what later sessions may do with these lines: create allows nothing more, inspect allows viewing, edit allows changes. Each line is an ItemIn with a quantity and these elements:
- ItemID, with the SupplierPartID (the supplier’s item number) and an optional SupplierPartAuxiliaryID. The second is a supplier cookie: a quote number or configuration key that the buying system sends back unchanged in later edit or inspect sessions and in the purchase order.
- ItemDetail, with the UnitPrice as a Money amount and a currency, a Description (with an optional ShortName), the UnitOfMeasure and a Classification.
- UnitOfMeasure must use the UN/CEFACT common codes, such as EA for each. A box of ten is a different unit from ten single items, and the price must match the unit sent.
- Classification gives a commodity code, usually in the UNSPSC domain, which the buying system uses for accounting and reports.
The Reference Guide is explicit about what the returned basket is: the supplier has provided a quote, has not received a purchase order, and cannot yet book the order. A message with status 204 means the session ended with no change to the basket. Neither case commits the buyer.
What happens after approval: the cXML OrderRequest
When the requisition is approved, the buying system turns it into a purchase order and, for a cXML supplier, sends an OrderRequest. Its OrderRequestHeader holds the orderID, which is the purchase order number, the orderDate, a type (new, update or delete) and an orderType: regular by default, release for a call-off against an agreement, or blanket for a blanket purchase order. Update and delete orders refer back to the original through a DocumentReference. Each line is an ItemOut that carries the same ItemID, including the supplier cookie returned during punchout.
The Reference Guide makes a point that saves confusion in projects: punchout and cXML order receiving are distinct capabilities. A supplier can receive cXML orders without a punchout site, and a punchout site does not receive orders by itself. The guide still recommends cXML orders for punchout suppliers, because the supplier cookie travels back in the order and does not map easily to fax, email or EDI.
The supplier answers with a Response whose status says it received and parsed the order. Confirmations, ship notices and invoices then use their own documents (ConfirmationRequest, ShipNoticeRequest, InvoiceDetailRequest), which feed three-way matching but sit outside the punchout.
cXML vs OCI vs static catalogues: which one does the buying system expect?
Disclosure: the author works as an Ivalua consultant. The products named here are described from their publishers’ public pages, not from a test.
A supplier rarely chooses the standard; the buying system does. SAP S/4HANA and SAP’s older purchasing applications use the Open Catalog Interface (OCI); SAP Ariba, Coupa and many other procurement systems use cXML; and most also accept static catalogue files loaded into the system. The three differ in what moves and when.
In OCI, the buying system opens the catalogue with a web address that carries parameters: the catalogue URL, login values agreed with the supplier and a return address, usually named HOOK_URL. SAP’s help for its older purchasing releases says the return URL must come after the catalogue’s own parameters, and SAP’s support note for SAP S/4HANA Cloud Public Edition shows the catalogue URL and the HOOK_URL set in the catalogue’s web service settings. At checkout, the basket is posted to HOOK_URL, usually as an HTTP POST, in plain name-value fields, one set per line. Integrator documentation lists the usual fields: NEW_ITEM-DESCRIPTION[1], NEW_ITEM-QUANTITY[1], NEW_ITEM-UNIT[1], NEW_ITEM-PRICE[1], NEW_ITEM-CURRENCY[1], NEW_ITEM-VENDORMAT[1] for the supplier’s item number, and so on. The basket is a list of fields, not an XML document, and the purchase order is not part of OCI: it goes to the supplier through whatever channel the buying system uses for orders.
| Question | cXML punchout | SAP OCI punchout | Static catalogue (CIF or cXML file) |
|---|---|---|---|
| What opens the session | A PunchOutSetupRequest, an XML document posted server to server | A web address with parameters, opened in the browser | No session: items are already loaded in the buying system |
| How the basket returns | A PunchOutOrderMessage in a hidden form field, posted by the browser | Name-value fields named NEW_ITEM-…[n], posted to HOOK_URL | The requester picks lines inside the buying system |
| How the supplier knows the buyer | Credentials in the Header, checked by a hub or by a code or certificate | Login values in the call, agreed with the supplier | Not needed during shopping |
| Purchase order | OrderRequest, in the same standard | Not part of OCI; sent by the buying system’s order channel | Whatever channel the buying system uses, often cXML or EDI |
| Who keeps prices current | The supplier, live on its site | The supplier, live on its site | The buyer, at each new file |
Build for the standard your customers’ systems call; a supplier that sells to both SAP and non-SAP buyers often needs cXML and OCI as two separate connections.
Static catalogues come in two main formats in SAP Ariba, according to SAP Learning: CIF (Catalog Interchange Format), a text file format, and cXML catalogue files. SAP Ariba also accepts BMEcat 1.2 files. cXML also has a light file between the two worlds: the punchout index catalogue, an Index document whose IndexItemPunchout entries point to the supplier’s punchout site, with a punchoutLevel of store, aisle, shelf or product. That index is what makes items searchable inside the buying system before the requester punches out.
What must a supplier build to offer a cXML punchout catalog?
The Reference Guide lists four transactions a punchout site must support: the Profile transaction, the PunchOutSetupRequest, the PunchOutSetupResponse and the PunchOutOrderMessage. To handle them, it describes four pages or endpoints to add to an existing web shop:
- A launch page that receives the setup request, validates it, identifies the buyer and the user, stores the session data (sender, language, operation, extrinsic values) and returns the setup response.
- A start page, the URL in the response, which logs the requester into the right customer account with its contract prices and catalogue.
- A sender page, at checkout, which builds the PunchOutOrderMessage from the basket and posts it to the BrowserFormPost address.
- An order receiver page, which accepts the OrderRequest after approval and passes it to the order management system.
The XML itself is rarely the long part. Customer accounts, contract prices and units of measure on the supplier’s side usually take more work than the four pages, so agree them with each buyer before building.
How do you test a cXML punchout before go-live?
Test with the buyer’s real configuration, not only with a sample file. A cXML document can mark itself as a test with the deploymentMode attribute set to test, and suppliers usually issue one set of credentials for testing and another for production, as Coupa’s supplier documentation notes. A useful test run covers these cases:
- A create session with three lines, one of them sold by the box, returned and checked line by line for price, unit and classification code.
- An edit session that reopens the basket, changes a quantity and keeps the same SupplierPartAuxiliaryID on every line.
- An inspect session in which the supplier’s site refuses changes.
- A session abandoned halfway, and a checkout with an empty basket.
- A description with accented characters, sent through the cXML-base64 field.
- The approved order, received as an OrderRequest with the supplier cookie intact, then a change order with type update.
| What the team sees | Likely cause | Where to look first |
|---|---|---|
| Status 401 on the setup request | The Sender credentials were not recognised: wrong secret, or test credentials used in production | The shared secret and identity domains on both sides |
| Status 406, or the document is refused | The document did not parse: a misspelt element, wrong order, or a DTD the receiver does not support | Validation against the DTD named in the document |
| Status 450 | The receiver does not implement the request or operation, for example edit | The supplier’s ProfileResponse |
| Lines arrive with prices ten times too high or too low | Unit of measure mismatch: box against each | UnitOfMeasure codes and the price basis per line |
| The basket never arrives | The checkout form posts to a stored address instead of the BrowserFormPost URL, or the field is double-encoded | The sender page’s form action and field name |
| Edit sessions open an empty basket | The supplier did not keep the session data or changed the supplier cookie | The launch page’s handling of operation="edit" |
Most go-live failures are configuration, units or encoding, not the protocol; test them on purpose rather than waiting for a requester to find them.
cXML punchout catalog solution or integration: build or buy?
A supplier has three routes. It can build the four pages into its own web shop, which suits a supplier with developers and one main standard. It can use the punchout module of its e-commerce platform, if the platform has one. Or it can use a specialist connector provider that links one shop to many buying systems and handles cXML, OCI and their variants. A “cXML punchout catalog solution” or “integration” in search results is usually one of the last two.
Whatever the route, ask: which buying systems and standards does it already connect to? Does it support edit and inspect sessions, or only create? Does it pass cXML orders into your order system? Who holds the shared secrets and test accounts, and who sees a failed checkout first? Buyers ask the same questions when choosing procure-to-pay software.
Questions
Is cXML the same thing as punchout?
No. cXML is a standard for many business documents: catalogues, purchase orders, confirmations, ship notices and invoices. Punchout is one cXML transaction, the live shopping session. Punchout also exists outside cXML, for example with SAP’s Open Catalog Interface, which uses web form fields instead of XML documents.
Does a cXML punchout need SAP Business Network or another hub?
Not always. The cXML guides describe a hub that checks the buyer and adds the supplier’s secret before forwarding the setup request. They also describe direct punchout, where the request goes straight to the supplier and is authenticated by a message authentication code or a client certificate. Which one applies depends on the buying system.
What is the BuyerCookie in cXML punchout?
It is a value the buying system creates for each punchout session and sends in the setup request. The supplier must return it unchanged in the PunchOutOrderMessage, so the buying system can attach the basket to the right session. It changes at every session, so suppliers should not use it to identify a customer.
Which cXML version should a supplier support?
Support the version the buying system sends; each document names its DTD and version in its header. Published DTDs never change, and each version has its own address, so they can be stored locally. The current version, 1.2.071, is dated 14 August 2026 on cxml.org.
Can a requester change a punchout basket after it returns?
Only if the supplier allows it. The operationAllowed attribute in the order message says whether later sessions may edit, only inspect, or not reopen the lines. Changes are made by punching out again with an edit session, because price, tax and freight are calculated on the supplier’s site.
New guides on the procure‑to‑pay line
One short email when a guide on this line is added or revised. Nothing else.
Coming soon: sign-up opens with the first email.