PunchOut
PunchOut for suppliers: what your store has to do, item by item
A store is PunchOut-ready when a buyer can open it from the procurement system, shop at contract prices and take the cart back, and when the purchase order that follows lands without retyping. That is 38 items in six groups. A buyer that only needs the cart takes 14 of them.
Updated
Which items apply to your buyer
PunchOut connects two sides. The procurement system of your customer logs a buyer into your store, the store sends the cart back as a requisition, and after approval the purchase order comes to you. The order of the steps is on the PunchOut hub. This page lists what the store and the software around it have to do, per step.
The 38 items fall into six groups. Group A is the base for every cXML buyer; the others depend on what the buyer asks for.
| Group | Items | Applies when |
|---|---|---|
| A. cXML PunchOut, the minimum | 1 to 10 | the buyer uses Coupa, SAP Ariba or another cXML system |
| B. Purchase orders | 11 to 16 | the buyer sends its orders as cXML documents |
| C. Documents back | 17 to 20 | the buyer wants confirmations, ship notices or invoices in cXML |
| D. OCI | 21 to 30 | the buyer runs SAP with the Open Catalog Interface |
| E. Level 2 | 31 to 34 | the buyer wants your items in its own search |
| F. Testing and going live | 35 to 38 | always |
Three common cases, counted. A cXML buyer that only needs the cart: 10 + 4 = 14 items. The same buyer with purchase orders and documents back: 10 + 6 + 4 + 4 = 24. An SAP buyer over OCI that sends its orders in cXML: 10 + 6 + 4 = 20. All six groups: 10 + 6 + 4 + 10 + 4 + 4 = 38.
Element and field names below come from the cXML reference guide, version 1.2.071, and SAP's OCI 5.0 specification, both checked on October 3, 2026.
A. The minimum for cXML PunchOut (items 1 to 10)
| # | Item | What it has to do |
|---|---|---|
| 1 | HTTPS endpoint | Accept a POST with the cXML document as the body, sent as text/xml in UTF-8, and answer in the same connection. |
| 2 | Connection per buying organization | One record per buyer: identity and domain, the shared secret stored as a hash, the customer account in the store, and the addresses for test and production. |
| 3 | Credential check | Compare the SharedSecret in Sender and find the buying organization by the Identity in From. Through a network hub, Sender is the hub and only From names the buyer. |
| 4 | Reading the setup request | BuyerCookie is the only required element. BrowserFormPost, Contact, Extrinsic, ShipTo and SelectedItem are optional, so the session may not depend on any user field. |
| 5 | Session and start URL | Store the buyer, the BuyerCookie, the return URL and the operation under a random identifier, and return one StartPage/URL that refers to it. An unused identifier expires fast, for example after five minutes. |
| 6 | Login without a form | The start URL opens the store as the customer account of that buyer, with its catalog and contract prices. No password prompt. |
| 7 | Transfer in place of the checkout | Build a PunchOutOrderMessage, put it in a hidden form field named cXML-urlencoded or cXML-base64, and let the browser post the form to the BrowserFormPost URL. Return the BuyerCookie unchanged and leave the shared secret out. |
| 8 | Line items | Per ItemIn: quantity, SupplierPartID, UnitPrice with a currency, Description, UnitOfMeasure as a UN/CEFACT code and at least one Classification. |
| 9 | Cart header | PunchOutOrderMessageHeader with operationAllowed (create, inspect or edit) and a Total without tax and shipping. Tax and Shipping are separate elements. |
| 10 | Four error statuses | 400 for a request that parses and cannot be accepted, 401 for credentials that are not recognized, 406 for XML that does not validate, 500 for an internal error. |
An error is a cXML document with a status, in the same shape as a success:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.071/cXML.dtd">
<cXML payloadID="1791032615.4821.90417@store.example.com"
timestamp="2026-10-03T09:03:35-04:00">
<Response>
<Status code="401" text="Unauthorized">Shared secret does not match</Status>
</Response>
</cXML>
The class of the status matters. The buyer's system does not retry a status in the 400 range. It treats a status in the 500 range, or an answer that is not valid cXML, as transient and sends the request again. A wrong password answered with 500 comes back.
Two details behind items 5 and 7. The BuyerCookie is new in every session, so it cannot serve as the key for your own cart. The field for that is SupplierPartAuxiliaryID, which the procurement system returns in a later edit session and in the purchase order. And a buyer who leaves without a cart needs a cancel button: it posts a PunchOutOrderMessage without items, and the procurement system closes the session. The documents themselves are explained on cXML PunchOut.
B. If the buyer sends purchase orders electronically (items 11 to 16)
| # | Item | What it has to do |
|---|---|---|
| 11 | Order endpoint | A second URL that accepts OrderRequest documents. PunchOut and order receiving are separate capabilities in cXML; a buyer can use one without the other. |
| 12 | Answer first, process later | Store the document, answer with status 200 and process the order from a queue. A buyer's system that gets no valid answer sends the order again. |
| 13 | Duplicate detection | A retried order keeps its payloadID. Keep every accepted payloadID and orderID, answer a repeat with 200 and create nothing. |
| 14 | Change and cancel orders | type="update" and type="delete" point to the original order through DocumentReference. orderVersion starts at 1 and goes up by 1 per change. An update the state of the order no longer allows gets 409. |
| 15 | Purchasing cards | Payment/PCard carries a number, an expiration date and an optional name. The DTD has no attribute for a security code, so the charge runs without one. |
| 16 | Seven error statuses | 400, 401, 402 when a Payment element is required and missing, 406, 409, 450 when change orders are not implemented, and 500. |
A status of 200 on an order says the document was received and parsed. It does not say which lines can ship. That is the job of item 17. The order then goes to the store or the ERP through the orders flow; its EDI counterpart is the 850 purchase order.
C. If the buyer wants documents back (items 17 to 20)
| # | Item | What it has to do |
|---|---|---|
| 17 | Order confirmation | A ConfirmationRequest with a type: accept, reject, except or backordered for the whole order, detail or allDetail per line. It points to the order through OrderReference. |
| 18 | Ship notice | A ShipNoticeRequest with shipmentID, noticeDate, shipmentDate and deliveryDate, the carrier in ShipControl and the order lines in ShipNoticePortion. One notice is one shipment and may hold lines of several orders. |
| 19 | Invoice | An InvoiceDetailRequest with invoiceID, invoiceDate and the order it bills. The line amounts add up to the total in InvoiceDetailSummary. |
| 20 | Outbound credentials | Per buyer and per environment: the address to post to, your identity in From and Sender, the buyer in To, the shared secret in Sender. Confirmations and ship notices validate against Fulfill.dtd, invoices against InvoiceDetail.dtd. |
Only one accept, reject or except confirmation is allowed per order; a later one replaces the earlier. Line-level confirmations can be several, as long as no line appears in two of them. The data comes from the ERP: the confirmed quantity, the tracking number, the invoice number. The EDI counterparts are the 855, the 856 and the 810.
D. If the buyer runs SAP: OCI (items 21 to 30)
| # | Item | What it has to do |
|---|---|---|
| 21 | Login address for the browser | SAP calls the store from the buyer's browser, by POST as the standard setting or by GET. Accept both. |
| 22 | Credential names per buyer | The specification leaves the names of the login parameters to the catalog and the SAP administrator. Keep per buyer which parameter holds the user name and which the password. |
| 23 | Return URL with its parameters | The return URL arrives as a parameter, by default named HOOK_URL, and usually carries parameters of its own. The address goes in the action of the transfer form, its parameters in hidden fields. |
| 24 | Target and character set | returntarget goes in the target attribute of the form, so the cart lands in the right window. http_content_charset names the character set for the transfer page. |
| 25 | Cart as form fields | One input per value, named NEW_ITEM-<field>[n], posted by the browser. POST, because GET runs into length limits in browsers. |
| 26 | Field mapping within the lengths | Description 40 characters, part number 40, unit 3, material group 10, quantity and price 15 with at most 3 decimals and no thousands separator. Which of the 34 fields a buyer reads is recorded per buyer. |
| 27 | Long text | NEW_ITEM-LONGTEXT_n:132[] has its own name format and no length limit. |
| 28 | Loading inside a frame | A procurement system that shows the catalog in a frame needs a store that permits it. A Shopify storefront sends X-Frame-Options: DENY; Magento defaults to SAMEORIGIN. |
| 29 | One login, many buyers | The login parameters are usually fixed values, so every buyer of one customer arrives as the same user. Keep the cart per session, not per account. |
| 30 | A route for the order | OCI ends at the cart. The order comes as a cXML document (items 11 to 16), as EDI or as a PDF by email. |
The transfer form for one line:
<form method="post" target="_parent" action="https://srm.bakker.example/return">
<input type="hidden" name="NEW_ITEM-DESCRIPTION[1]" value="Duplex receptacle 20 A, white">
<input type="hidden" name="NEW_ITEM-QUANTITY[1]" value="120">
<input type="hidden" name="NEW_ITEM-UNIT[1]" value="EA">
<input type="hidden" name="NEW_ITEM-PRICE[1]" value="9.60">
<input type="hidden" name="NEW_ITEM-CURRENCY[1]" value="USD">
<input type="hidden" name="NEW_ITEM-VENDORMAT[1]" value="10482">
</form>
The specification requires a description (or the buyer's own product number in NEW_ITEM-MATNR) and a quantity, plus a unit when no product number is given and a currency when a price is given. The unit has to be an ISO code that exists in the buyer's SAP system. The field list with every length is on the OCI page.
E. If the buyer wants your products in their search: Level 2 (items 31 to 34)
| # | Item | What it has to do |
|---|---|---|
| 31 | Index catalog | A file that lists the items the buyer may search, each with a part number, a description and a classification. The procurement system sets the format. A catalog upload over cXML takes files with a .cif, .xml or .zip extension of at most 4 MB. |
| 32 | Landing on the product page | The setup request carries a SelectedItem with the SupplierPartID from the index, and the start URL opens that product. Without SelectedItem the whole store opens. |
| 33 | Commodity codes | A classification on every item. For a cXML index catalog that is a UNSPSC code; an invalid code on a catalog upload comes back as status 461. |
| 34 | Regenerating the index | A part number in the index that no longer exists in the store sends the buyer to a page that is not there. The index is rebuilt from the store on a schedule and loaded again at the buyer. |
The cXML index has a punchoutLevel per item with the values store, aisle, shelf and product. A store-level item opens the home page, a product-level item one product. More on Level 2 PunchOut.
F. Testing and going live (items 35 to 38)
| # | Item | What it has to do |
|---|---|---|
| 35 | Test environment | A test address for the endpoint and a test connection per buyer. deploymentMode="test" marks a request as a test; production is the default. |
| 36 | Round trip with the buyer | From the test instance of the buyer: a create session with a cart, an edit and an inspect session on that cart, a canceled session, and a purchase order followed by a change and a cancellation. |
| 37 | Network account and profile | With a buyer on SAP Business Network, your PunchOut URL, order URL and shared secret are set in your account on the network, which routes each request by them. The endpoint also answers a ProfileRequest, the one transaction every cXML server has to support. |
| 38 | Ownership after going live | Someone watches failed logins, rejected carts and carts without a purchase order, and changes the mapping when the buyer's system changes. |
Item 38 has no end date. A buyer rotates its shared secret and every setup request gets a 401. A theme update removes the transfer button. A new item carries a unit the buyer's system does not know. None of these shows up in the store.
We build these items on your existing store, host the endpoints and monitor every session. A failed login is in the log when it happens, and a change at the buyer is ours to fix. Tell us which procurement system your customer uses and which groups it asked for.
Frequently asked questions
Do I need all 38 items?
No. A buyer on cXML that only wants the cart needs the 10 items of the minimum and the 4 for testing: 14. Purchase orders in cXML add 6, documents back add 4. The 10 OCI items apply only with a buyer on SAP, and the 4 for Level 2 only when the buyer wants your items in its own search.
Can PunchOut run on my existing store, or do I need a separate site?
On the existing store. The session opens the store as the customer account of the buyer, with the catalog and contract prices that account already has. What is added is an endpoint for the setup request, a transfer in place of the checkout for these sessions, and the handling of the documents. Regular customers keep the normal checkout.
Does every buyer need its own endpoint?
No. One endpoint takes the setup requests of every buyer and tells them apart by the identity in From and the shared secret in Sender. What is separate per buyer is the connection record: credentials, customer account, field mapping and the test and production addresses for outbound documents.
What does the administrator at my buyer need from me?
The PunchOut URL of your endpoint, the identity and domain you are known by (usually a DUNS number or a network ID) and a shared secret. Coupa also asks for a logo of 150 by 50 pixels for the tile. For purchase orders the buyer needs the URL of the order endpoint.
How is the endpoint tested before the buyer is involved?
By posting a sample PunchOutSetupRequest to the test address and checking the response and the start URL; the cXML reference guide contains sample documents for every step. The round trip that ends in a requisition can only be run from the test instance of the buyer, which is item 36.
My buyer uses OCI and wants to send orders electronically. Which items apply?
The 10 OCI items for the session and the cart, the 6 items for purchase orders in cXML and the 4 for testing: 20 items. OCI itself ends at the cart, so the order needs its own route. A buyer that sends the order as a PDF by email takes 14 items, and someone retypes each order.
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