Blog

PunchOut Setup for SAP Ariba: cXML Requirements and Common Failures

What SAP Ariba actually requires for a working PunchOut connection, the cXML documents involved, and the configuration mistakes that cause most first-round failures.

SupplierForge team

SAP Ariba is one of the most common buying platforms a supplier will connect a catalog to over PunchOut, and its implementation of the cXML standard is also one of the pickier ones to get right on the first attempt. Ariba doesn’t deviate from the cXML specification in any exotic way: the four documents that make up a PunchOut round trip are the same ones defined by the standard BoreaTech covers in What is cXML?. What trips up first-round integrations is a small, repeatable set of configuration details specific to how Ariba issues credentials, validates identity, and expects its browser hand-off to behave. This guide walks through those details mechanically: what Ariba expects a supplier to have configured before the first request ever arrives, the four documents in the round trip with illustrative snippets of each, the credential fields that cause the most confusion, what a real test cycle looks like, and the five failures that account for most rejected first attempts.

What Ariba expects from a PunchOut supplier

Before any cXML document moves in either direction, three things need to exist. First, a network account: Ariba assigns every registered trading partner an Ariba Network ID (ANID), a string in the form AN followed by roughly ten digits, with test and production realms carrying entirely separate ANIDs. The buyer’s own PunchOut catalog configuration references your ANID as the addressee for every request it sends you, so a typo or a test/production mismatch here is invisible until the first request fails to authenticate.

Second, a shared secret. Ariba PunchOut authentication is symmetric-key, not certificate-based: a secret string is generated (either by you or by Ariba’s supplier enablement team, depending on how the relationship was set up) and entered on both sides: into your PunchOut handler’s credential store, and into the buyer’s Ariba Network configuration against your ANID. The shared secret for the test realm and the shared secret for production are different values even when everything else about the setup is identical, and this is the single most common source of confusion in the first section below.

Third, two HTTP endpoints. Ariba needs a URL to POST the PunchOutSetupRequest document to when a user in the buyer’s requisitioning UI clicks through to your catalog: this is generally called the PunchOutSetupOperation URL, and it must be HTTPS, publicly reachable, and stable across the life of the relationship since it gets hard-coded into the buyer’s catalog entry. Separately, most integrations also register an order intake endpoint, the URL that receives the OrderRequest document once a cart converts into a purchase order on the buyer’s side. These are frequently the same physical service behind different routes, but they are configured as two distinct URLs in Ariba’s system and each needs its own uptime guarantee, because a buyer’s procurement team has no visibility into which one is down when a session or an order silently fails to arrive. For a broader view of how these pieces sit inside a supplier-facing catalog platform rather than as one-off endpoints, see how catalog ingestion and procurement integration fit together.

The four cXML documents in an Ariba PunchOut round trip

A PunchOut session is a fixed sequence of four cXML documents moving between three actors: the buyer’s procurement system, the user’s browser, and the supplier’s catalog. Understanding which actor sends which document, and over what transport, resolves most of the confusion new integrators have about why a “request” sometimes arrives as an HTTP POST and sometimes as a browser redirect.

1. PunchOutSetupRequest: sent by the buyer’s system, as a direct server-to-server HTTPS POST, to your PunchOutSetupOperation URL. It carries the buyer’s and your own identity in the header, a BuyerCookie value you must echo back verbatim later, a BrowserFormPost element telling you where to send the user’s browser when checkout completes, and often Extrinsic elements carrying context like the requesting user’s name, email, or cost center.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.045/cXML.dtd">
<cXML payloadID="[email protected]" timestamp="2026-09-16T09:00:00-05:00">
  <Header>
    <From><Credential domain="NetworkID"><Identity>AN01000000001</Identity></Credential></From>
    <To><Credential domain="NetworkID"><Identity>AN01000000002-T</Identity></Credential></To>
    <Sender>
      <Credential domain="NetworkID">
        <Identity>AN01000000001</Identity>
        <SharedSecret>REPLACE_WITH_SHARED_SECRET</SharedSecret>
      </Credential>
      <UserAgent>Ariba Buyer 26.1</UserAgent>
    </Sender>
  </Header>
  <Request deploymentMode="test">
    <PunchOutSetupRequest operation="create">
      <BuyerCookie>a1b2c3d4e5f6</BuyerCookie>
      <Extrinsic name="UserEmail">[email protected]</Extrinsic>
      <BrowserFormPost>
        <URL>https://procure.buyer.example.com/punchout/return</URL>
      </BrowserFormPost>
    </PunchOutSetupRequest>
  </Request>
</cXML>

2. PunchOutSetupResponse: your synchronous HTTP response body, returned on the same connection as the request above. Its only real job is to hand back a StartPage URL: a one-time, session-scoped link to your hosted catalog that the buyer’s system redirects the user’s browser to.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.045/cXML.dtd">
<cXML payloadID="[email protected]" timestamp="2026-09-16T09:00:01-05:00">
  <Response>
    <Status code="200" text="OK"/>
    <PunchOutSetupResponse>
      <StartPage>
        <URL>https://catalog.supplier.example.com/session/7f3a9c?cookie=a1b2c3d4e5f6</URL>
      </StartPage>
    </PunchOutSetupResponse>
  </Response>
</cXML>

3. PunchOutOrderMessage: not sent as a plain HTTP POST between servers, but posted directly from the user’s browser to the BrowserFormPost URL the buyer supplied in step one, as an auto-submitting HTML form generated by your catalog once the user finishes shopping and clicks checkout. Its body is the cXML document as a hidden form field, and it carries line items back to the buyer’s cart. (The classification codes in this and the next example are illustrative placeholders, not verified real-world UNSPSC lookups.)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.045/cXML.dtd">
<cXML payloadID="[email protected]" timestamp="2026-09-16T09:14:22-05:00">
  <Message>
    <PunchOutOrderMessage>
      <BuyerCookie>a1b2c3d4e5f6</BuyerCookie>
      <PunchOutOrderMessageHeader operationAllowed="create">
        <Total><Money currency="USD">452.00</Money></Total>
      </PunchOutOrderMessageHeader>
      <ItemIn quantity="4">
        <ItemID>
          <SupplierPartID>BRK-4521</SupplierPartID>
        </ItemID>
        <ItemDetail>
          <UnitPrice><Money currency="USD">113.00</Money></UnitPrice>
          <Description xml:lang="en">Bracket assembly, 4in, zinc-plated</Description>
          <UnitOfMeasure>EA</UnitOfMeasure>
          <Classification domain="UNSPSC">31161701</Classification>
        </ItemDetail>
      </ItemIn>
    </PunchOutOrderMessage>
  </Message>
</cXML>

4. OrderRequest: the actual purchase order, sent later and separately by the buyer’s system once the cart from step three has cleared their own internal approval workflow. This can be minutes or days after the PunchOut session ended, and it arrives at your order intake endpoint as its own server-to-server POST, unconnected to the browser session that produced it except by the line-item and cookie data the buyer’s system retained.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.045/cXML.dtd">
<cXML payloadID="[email protected]" timestamp="2026-09-17T11:02:00-05:00">
  <Request deploymentMode="test">
    <OrderRequest>
      <OrderRequestHeader orderID="PO-000482" orderDate="2026-09-17T11:02:00-05:00" type="new">
        <Total><Money currency="USD">452.00</Money></Total>
      </OrderRequestHeader>
      <ItemOut quantity="4" lineNumber="1">
        <ItemID><SupplierPartID>BRK-4521</SupplierPartID></ItemID>
        <ItemDetail>
          <UnitPrice><Money currency="USD">113.00</Money></UnitPrice>
          <Description xml:lang="en">Bracket assembly, 4in, zinc-plated</Description>
          <UnitOfMeasure>EA</UnitOfMeasure>
          <Classification domain="UNSPSC">31161701</Classification>
        </ItemDetail>
      </ItemOut>
    </OrderRequest>
  </Request>
</cXML>

Credential configuration and the DUNS / NetworkID question

Every cXML Header carries three identity blocks (From, To, and Sender), and Ariba is stricter than most trading partners about what belongs in each. From identifies the party the message is conceptually sent by (the buyer, in a PunchOutSetupRequest). To identifies the intended recipient (you, the supplier) using the identity Ariba has on file for your account. Sender identifies who actually transmitted the bytes and carries the authentication credential, which on an Ariba PunchOut round trip is the party whose SharedSecret you’re expected to validate against.

The recurring point of confusion is the domain attribute on each Credential element. Older cXML integrations, and some non-Ariba trading partners, identify parties by domain="DUNS" using a D-U-N-S number as the identity value. Ariba Network has moved its own identity scheme to domain="NetworkID", using the ANID as the identity value instead, and a shared secret registered against a NetworkID-domain identity will not authenticate a request that presents the same numeric-looking value under a DUNS domain: Ariba treats them as different identities even if a human would recognize them as the same trading partner. If your integration was originally built against a non-Ariba buyer using DUNS identifiers, the most common first-round failure is simply carrying that domain forward into the Ariba configuration unchanged. Confirm with whichever team manages your Ariba Network account which domain and identity value are actually registered against your shared secret before assuming the credential itself is wrong.

Testing against the Ariba test network

Ariba maintains a separate test realm with its own ANIDs (typically your production ANID with a -T suffix) and its own shared secret, entirely independent of production. A realistic first test cycle looks like this: the buyer’s admin (or a test buyer account, if you’re certifying independently) configures a PunchOut catalog entry pointing at your test endpoint with the test ANID and test secret, and every cXML document in the exchange carries deploymentMode="test" on the Request or Response element. The first several attempts usually fail on document structure (a missing required element, an attribute in the wrong casing, a DOCTYPE referencing a DTD version the test realm doesn’t recognize) before authentication and the browser hand-off succeed cleanly. Once PunchOutSetupRequest and PunchOutSetupResponse are working, the harder half of the cycle starts: populating the hosted catalog session with real item data, confirming the PunchOutOrderMessage the browser posts back parses on the buyer’s side without error, and watching a test OrderRequest arrive at your order intake endpoint hours or days later once someone on the buyer’s side pushes a test cart through their approval flow.

Moving to production means more than flipping deploymentMode to production: it means swapping in the production ANID, the production shared secret, and, in the buyer’s own catalog configuration, the production endpoint URLs if they differ from the test ones. A configuration that still references test credentials in one place after the rest has been cut over produces exactly the same 401 discussed above, and it’s worth an explicit checklist item rather than an assumption that “changing one setting” covers the whole cutover.

Five failures that account for most first-round rejections

Auth / identity-domain mismatch. Covered above, and still the single most common cause of a rejected PunchOutSetupRequest: either the shared secret is wrong for the realm being targeted, or the credential domain (DUNS versus NetworkID) doesn’t match what the secret was issued against.

Wrong deploymentMode. Sending deploymentMode="production" against Ariba’s test endpoint, or deploymentMode="test" against production, is a separate failure from the identity mismatch above and produces a similar-looking rejection. Because the attribute lives on the Request/Response element rather than in the URL or the credentials, it’s easy to update one and forget the other during a test-to-production cutover.

Unescaped XML in item descriptions. Item names and descriptions sourced from a supplier’s own catalog data routinely contain ampersands, angle brackets, or unescaped quotation marks (“Brackets & Fasteners,” 6” pipe, 3/4” fitting), and if those characters aren’t XML-entity-escaped before being written into a Description element, the resulting PunchOutOrderMessage fails to parse on the buyer’s side. This is a silent failure from the supplier’s perspective: your own logs show a successfully generated document, and the rejection only surfaces once the buyer’s system tries to import the cart.

Missing UNSPSC classification. Ariba’s requisitioning workflow frequently uses UNSPSC commodity codes for approval routing and tax treatment, not just categorization. An ItemIn or ItemOut element without a Classification domain="UNSPSC" value can pass PunchOut validation cleanly and still get stuck or misrouted once it reaches the buyer’s approval workflow, which looks from the supplier side like the integration “worked” even though the order stalls downstream.

Browser form post lost on redirect. The hand-off from PunchOutOrderMessage back to the buyer depends on an auto-submitting HTML form executing in the user’s browser, not a server-to-server call. Corporate proxies that strip inline scripts, browser extensions that block third-party form auto-submission, or a session cookie dropped during the redirect back to the buyer’s domain can all break this step even when both cXML documents involved are perfectly well-formed. And because nothing server-side ever sees an error, this failure mode is usually diagnosed by watching the actual browser session rather than by reading logs.

Where SupplierForge fits

None of the mechanics above are specific to any one platform: they’re properties of how Ariba implements PunchOut. Where a catalog platform matters is in reducing how often these failures happen in the first place, largely through item mapping and categorization (so UNSPSC classification is consistent going in) and ongoing catalog health and data-quality monitoring (so malformed item data surfaces before it reaches a buyer). SupplierForge’s feature set covers catalog ingestion and item mapping generally, and PunchOut specifically is handled by the PunchOut Gateway, a separately licensed component built to handle cXML, OCI, and EDI translation, Ariba’s PunchOut profile being one of several it’s designed to cover.

Frequently asked questions

What cXML version does SAP Ariba require for PunchOut?
Ariba's PunchOut implementation is built on the cXML 1.2.x schema family, referenced by a DOCTYPE declaration such as http://xml.cxml.org/schemas/cXML/1.2.045/cXML.dtd at the top of every document. The exact subversion tolerated depends on which release your buyer's Ariba Network realm is running, so the buyer's own PunchOut setup documentation is the source of truth for the DOCTYPE string, not a single number that applies everywhere. In practice Ariba validates document structure and required elements more strictly than it validates the DTD version string itself, so a slightly older 1.2.x reference rarely causes a rejection on its own.
Why does my PunchOutSetupRequest return a 401?
A 401 on PunchOutSetupRequest is almost always an authentication problem, not a routing or network problem. Either the SharedSecret configured on your endpoint doesn't match what's registered against your identity in Ariba's system, or the identity domain in the Sender credential (DUNS versus NetworkID) doesn't match what that secret was issued for. Mixing a test ANID with a production shared secret, or vice versa, produces the identical 401 because Ariba treats test and production as fully separate identities with separate credentials.
How long does an Ariba PunchOut certification take?
There's no fixed timeline, but a realistic first-time cycle runs one to three weeks. Connectivity and authentication failures typically get resolved in the first few days, item-data problems like missing UNSPSC codes or unescaped descriptions surface once real catalog data starts flowing through, and the production cutover (swapping test credentials for production ones) adds its own short validation pass. Suppliers who have done this before with clean catalog data can often compress the whole cycle to a few days.
Can one supplier serve PunchOut to multiple Ariba buyers?
Yes. Each buyer relationship is configured independently, with its own ANID pairing and its own shared secret, even though every buyer sends the same cXML document types against your same endpoints. In practice this means your PunchOutSetupRequest handler needs to route by the identity in the incoming header rather than assume a single fixed credential, since one hard-coded secret only ever matches one buyer relationship at a time.