All field notes
B2B Commerce

PunchOut Catalogues: Selling Into Enterprise Procurement

How cXML and OCI actually work, and why supporting them is often the requirement that unlocks your largest accounts.

360 Expert Solutions4 min read

Large buyers do not shop on your website. They shop inside Ariba, Coupa or SAP, and they expect your catalogue to appear there. PunchOut is the protocol that makes your storefront a guest inside their procurement system — and it is usually a contractual precondition, not a nice-to-have.

At a certain size, a customer stops buying from your website. Their procurement policy requires spend to flow through a purchasing system — Ariba, Coupa, Jaggaer, SAP — where it can be budgeted, approved and audited. Your beautifully built storefront is, from their point of view, an unapproved channel.

PunchOut is the bridge. It lets a buyer sit inside their procurement system, click your catalogue, be dropped into a live authenticated session on your actual storefront, build a basket, and hand it back to their system as a requisition. You keep your merchandising, search and real-time pricing. They keep their approval chain and audit trail.

The cXML round trip

cXML is the dominant standard, originally from Ariba and now broadly supported. The exchange has three messages and one browser redirect. Once you have seen the shape, it stops being mysterious.

PunchOut cXML sequence in four stages. Stage one: the buyer clicks the supplier catalogue in their procurement system, which sends a PunchOutSetupRequest containing shared secret credentials and the buyer identity to the supplier endpoint. Stage two: the supplier validates the credentials, creates a session bound to that buyer and their contract pricing, and responds with a PunchOutSetupResponse containing a one-time start URL. Stage three: the buyer’s browser is redirected to that URL and shops the live storefront with contract pricing applied. Stage four: on checkout the storefront posts a PunchOutOrderMessage back to the procurement system containing the cart, which becomes a requisition; after approval a purchase order arrives by cXML OrderRequest or EDI.

Note the direction of travel: the cart goes back to the buyer’s system. You do not take the order at checkout.

What the setup request looks like

xml
<cXML payloadID="20260903T094512.882Z@ariba.example.com" timestamp="2026-09-03T09:45:12Z">
  <Header>
    <From>
      <Credential domain="DUNS"><Identity>987654321</Identity></Credential>
    </From>
    <To>
      <Credential domain="DUNS"><Identity>123456789</Identity></Credential>
    </To>
    <Sender>
      <Credential domain="NetworkID">
        <Identity>AN01000000123</Identity>
        <SharedSecret>••••••••</SharedSecret>
      </Credential>
      <UserAgent>Ariba Buyer 9.x</UserAgent>
    </Sender>
  </Header>
  <Request deploymentMode="production">
    <PunchOutSetupRequest operation="create">
      <BuyerCookie>4a9f1c77-2b10-4f6e-9a1e-8c3d5f0b2e77</BuyerCookie>
      <Extrinsic name="UserEmail">j.okafor@buyer.example.com</Extrinsic>
      <Extrinsic name="UniqueName">jokafor</Extrinsic>
      <BrowserFormPost>
        <URL>https://buyer.example.com/punchout/return</URL>
      </BrowserFormPost>
      <SupplierSetup>
        <URL>https://store.example.com/punchout/setup</URL>
      </SupplierSetup>
    </PunchOutSetupRequest>
  </Request>
</cXML>
A PunchOutSetupRequest, trimmed. The shared secret and the buyer identity are the parts that matter.

Two fields carry most of the weight. The BuyerCookie is an opaque token you must echo back unchanged in the order message — it is how the procurement system reconnects the returned cart to the requisition it started. The BrowserFormPost URL is where you post that cart. Store both against the session and treat them as immutable.

Session handling is the hard part

A PunchOut session is not a normal storefront session. It is created by a server-to-server call and then adopted by a browser that arrives with no cookies and no login. That mismatch is where most implementations leak.

  • The start URL must be single-use and short-lived. A start URL that can be replayed is an authentication bypass into a customer’s contract pricing.
  • Bind the session to the buyer identity from the setup request, and resolve pricing from that binding — never from anything in the URL or a client-side parameter.
  • Expect the session to be abandoned. Buyers get interrupted; carts sit for days. Decide your expiry and say so in the UI rather than silently emptying a basket.
  • Handle "edit" operations as well as "create". A buyer who returns to amend an existing requisition sends operation="edit" with the previous cart, and is entitled to get it back.
  • Never render your normal header navigation. The buyer is inside an iframe or a managed window in their procurement system; links to your homepage, login or retail checkout break the model and confuse them.

OCI, and where it differs

SAP’s Open Catalog Interface solves the same problem with simpler machinery. Instead of XML documents, OCI uses HTTP form parameters: the buyer arrives with credentials as query or POST fields, and the cart returns as a form post of indexed fields — NEW_ITEM-DESCRIPTION[1], NEW_ITEM-PRICE[1], and so on.

It is easier to implement and less expressive. If you are building for the first time and your prospect list is SAP-heavy, OCI is a reasonable place to start. If it includes Ariba or Coupa, build cXML — and design the session layer so the protocol is a thin adapter over shared logic, because you will eventually support both.

Practical advice before you quote this work

  1. Get test credentials early

    Procurement platform test environments are slow to provision. Start that request at the beginning of the project, not the sprint you need it.

  2. Ask which UNSPSC level they need

    Many buyers require UNSPSC classification on returned lines. Retrofitting classification across a catalogue is a data project in its own right.

  3. Confirm the unit of measure vocabulary

    UN/CEFACT codes are typical. A mismatch here surfaces as rejected requisitions after go-live, which is an embarrassing way to find out.

  4. Plan for the PO to arrive separately

    The approved purchase order comes back hours or days later by cXML OrderRequest or EDI 850, and must reconcile to the original cart.

Key takeaways

  • PunchOut is usually a shortlist gate in enterprise tenders, not a differentiator.
  • The cart returns to the buyer’s procurement system; your checkout transfers, it does not sell.
  • Echo the BuyerCookie unchanged and make start URLs single-use and short-lived.
  • Strip your normal navigation — the buyer is inside a managed window in someone else’s application.
  • Build cXML for Ariba and Coupa, OCI for SAP, and keep the protocol a thin adapter over shared session logic.
PunchOutcXMLOCIProcurementSAP AribaCoupaB2B

360 Expert Solutions

E-commerce & ERP Integration Team

We build and scale B2B and DTC commerce on Shopify Plus, BigCommerce and WooCommerce, wired into NetSuite and Oracle. These articles are written by the engineers and architects who deliver those projects.

Building something like this?

We architect B2B commerce and ERP integrations end to end.

B2B Commerce

B2B Checkout: Net Terms, PO Numbers and Approval Chains

A B2B checkout is not a retail checkout with an invoice option bolted on. It has to carry a purchase order number, respect a credit limit the ERP owns, and route orders above a threshold to an approver — without becoming the slowest part of the buying process.

Read
B2B Commerce

Customer-Specific Pricing That Survives 40,000 SKUs

The instinct is to precompute every customer-product price. With 800 accounts and 40,000 SKUs that is 32 million rows that go stale the moment a contract changes. The alternative is to store rules and resolve them — with caching designed around how buyers actually browse.

Read
ERP Integration

Real-Time Inventory Between NetSuite and Shopify Plus B2B

Most NetSuite-to-Shopify integrations poll on a timer. For B2B that is too slow: a single wholesale order can move a thousand units, and the next buyer sees stock that no longer exists. The fix is event-driven sync with a reconciliation pass behind it.

Read
Book