PunchOut
OCI PunchOut: how SAP's Open Catalog Interface carries the cart
OCI is SAP's protocol for PunchOut. The buyer's browser opens your store with login parameters and a return address, and after shopping the browser posts the cart back as form fields named NEW_ITEM-
Updated
What OCI is
OCI, the Open Catalog Interface, is SAP's protocol for buying from a supplier's online catalog inside SAP SRM. The procurement system sends the buyer's browser to your store, the buyer shops at the prices of their company, and the browser posts the cart back to SAP as a shopping cart for approval. Login and cart both travel through the browser; there is no server-to-server document as in cXML.
SAP's current specification is OCI 5.0, dated October 4, 2012. It keeps the call-up and the cart fields of OCI 4.0 and adds four things: replication of catalog data to SRM in JSON, fields for an item hierarchy, an inbound and outbound handler on the SAP side, and Secure OCI. A catalog that is OCI 5.0 compliant has to be OCI 4.0 compliant first. Checked against that document on October 3, 2026.
OCI covers the shopping part only. The purchase order, confirmation, ship notice and invoice run over cXML, EDI or email; the whole flow is on the PunchOut hub.
How an OCI session runs
A buyer at Bakker Installatie B.V., customer 10432 in your ERP, orders three items from SAP SRM.
- The administrator at the buyer has entered your catalog URL and its parameters in SRM Customizing. The buyer picks your catalog.
- The buyer's browser calls your URL with the parameters. POST is the standard setting; the administrator can switch it to GET.
- Your store reads the login fields, finds customer 10432 and opens a session that stores
HOOK_URLandreturntarget. - The buyer shops at the contract prices of customer 10432 and fills a cart: 3 lines, 1,468.75 USD.
- In place of the checkout, the store returns a page with a form whose
actionis the return URL and whose hidden fields hold the cart. - The browser posts the form to SAP. SRM creates a shopping cart, and the buyer sends it for approval.
- After approval the purchase order comes to you through another channel.
The call-up in step 2 is a form POST to your login address. Its body, decoded, one parameter per line:
USERNAME=bakker-10432
PASSWORD=k7Qp2w
HOOK_URL=https://srm.bakker.example/oci/return?sessid=8F2A61&client=100
OCI_VERSION=4.0
http_content_charset=utf-8
returntarget=_parent
USERNAME and PASSWORD are this buyer's names, not SAP's. The specification leaves the names and values of login parameters to the catalog provider, and the administrator enters them in Customizing as fixed values or as SAP fields filled at runtime. Another buyer may send user and pass, or a customer number as a third parameter.
The call-up parameters
| Parameter | Content | What the store does with it |
|---|---|---|
| Login fields | names and values set per catalog | authenticate and pick the customer account |
HOOK_URL |
return URL with its own query string; the name is configurable, HOOK_URL is the default |
store it in the session; split it when building the cart form |
OCI_VERSION |
for example 4.0 |
informative only |
http_content_charset |
for example iso-8859-1 |
use it in the charset of the cart page |
returntarget |
for example _parent |
put it in the target attribute of the cart form |
FUNCTION |
DETAIL, VALIDATE, BACKGROUND_SEARCH |
answer with a product page, a validated item or search results |
The return URL arrives with parameters of its own, here sessid=8F2A61 and client=100. The specification requires the store to strip them off: the bare URL goes in the form's action, and each parameter becomes a hidden input with its own name and value.
The cart fields
Every field is named NEW_ITEM-<field>[n], where n numbers the line, and every field is of type CHAR. These are the fields a supplier store fills most:
| Field | Max length | Content | Rule |
|---|---|---|---|
NEW_ITEM-DESCRIPTION[n] |
40 | short description | required, unless MATNR is filled |
NEW_ITEM-QUANTITY[n] |
15 | quantity | required; 11 digits before the point, 3 after, no thousands separator |
NEW_ITEM-UNIT[n] |
3 | unit of measure | ISO code maintained in the buyer's system; required without MATNR |
NEW_ITEM-PRICE[n] |
15 | price per price unit | same number format as quantity |
NEW_ITEM-CURRENCY[n] |
5 | ISO currency code | required when a price is sent |
NEW_ITEM-PRICEUNIT[n] |
5 | price unit | whole number; empty means 1 |
NEW_ITEM-LEADTIME[n] |
5 | delivery time in days | whole number |
NEW_ITEM-VENDORMAT[n] |
40 | your part number | |
NEW_ITEM-MANUFACTMAT[n] |
40 | manufacturer part number | |
NEW_ITEM-MATGROUP[n] |
10 | material group in SRM | often a commodity code |
NEW_ITEM-EXT_PRODUCT_ID[n] |
40 | your database key | needed for DETAIL and VALIDATE |
NEW_ITEM-LONGTEXT_n:132[] |
none | long text | own name format, the index sits before the colon |
NEW_ITEM-CUST_FIELD1[n] to 5 |
10, 10, 10, 20, 50 | free fields | meaning agreed per buyer |
NEW_ITEM-MATNR[n] is the buyer's own product number. The specification allows it only when the catalog knows that number, which means a cross-reference per buyer. The full table in section 3.2 holds 34 fields.
The cart of Bakker Installatie B.V. as a form, first line in full:
<form method="post" target="_parent" action="https://srm.bakker.example/oci/return">
<input type="hidden" name="sessid" value="8F2A61">
<input type="hidden" name="client" value="100">
<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">
<input type="hidden" name="NEW_ITEM-MATGROUP[1]" value="39121406">
<!-- lines 2 and 3: the same 7 fields with [2] and [3] -->
</form>
Three lines of 7 fields are 21 cart fields, plus the 2 fields split off the return URL. Line by line: 120 x 9.60 = 1,152.00, then 2 panelboards x 149.00 = 298.00, then the cable ties. Those are sold in packs of 100 at 3.75 a pack, and OCI gives two ways to send them. As 5 packs: QUANTITY 5, UNIT PK, PRICE 3.75, line value 5 x 3.75 = 18.75. As pieces: QUANTITY 500, UNIT EA, PRICE 3.75, PRICEUNIT 100, line value 500 x 3.75 / 100 = 18.75. The amount is the same; the quantity that lands in the buyer's SAP system is not. Which one a buyer wants is recorded per buyer. The cart total is 1,152.00 + 298.00 + 18.75 = 1,468.75 USD.
More than the cart: detail, validation, search and Secure OCI
| Function or parameter | What SAP sends | What the store returns |
|---|---|---|
FUNCTION=DETAIL |
PRODUCTID |
the product page for an item already in a SAP document; no data goes back |
FUNCTION=VALIDATE |
PRODUCTID, QUANTITY |
a page with one item in OCI fields that posts itself by JavaScript, so a template gets the current price |
FUNCTION=BACKGROUND_SEARCH |
SEARCHSTRING |
search results in OCI fields on one page without scrolling; the form is not posted |
| Secure OCI | a server call with FUNCTION=INITIALIZE |
an XML answer with a SessionId and a SessionTransmissionId |
| OCI 5.0 replication | FUNCTION=DOWNLOADJSON, PAGESIZE (default 20), LASTUPDATED |
catalog items in JSON, page by page |
DETAIL and VALIDATE work only if the store filled NEW_ITEM-EXT_PRODUCT_ID on the first transfer. With Secure OCI the login and the prices stay off the browser: SAP fetches the items afterward with FUNCTION=RETRIEVEOCI and the SessionTransmissionId, and both IDs are deleted once the items have been transferred. With replication, a catalog of 4,000 items at the default page size of 20 is 4,000 / 20 = 200 calls from SRM to the store. An item sent with CATALOG_MANAGED=X shows in SAP's search without a price and with a "Go to Catalog" button, which opens the store on that item through FUNCTION=DETAILADD. That is OCI's counterpart to Level 2 PunchOut in cXML.
Where OCI sessions go wrong
| What goes wrong | What the buyer sees | Cause |
|---|---|---|
| No items arrive | an empty shopping cart in SRM | the return URL was put in action with sessid and client still in it, not split into hidden fields |
| Text garbled | "90° elbow" | the cart page was sent in UTF-8 while http_content_charset said iso-8859-1 |
| Two identical lines | "Duplex receptacle 20 A, tamper resistant" twice | descriptions of 54 characters cut at 40; the white and the ivory variant read the same |
| Price rejected | an invalid number | 1,152.00 sent with a thousands separator |
| Unit rejected | a unit error on the line | "each" or a code that is not maintained as an ISO unit in the buyer's system |
| Carts mixed | a colleague's items | all buyers of a customer arrive with one fixed login, and the store keeps the cart per account |
| Catalog window does not close | SAP shows no items | the catalog renamed the window SAP opened, or left extra windows open |
| Blank frame | nothing | SAP shows the catalog in a frame and the store sends X-Frame-Options: DENY |
The rows on the window, the character set, the number format and the return URL come straight from rules in the specification. The mixed carts follow from login parameters being fixed values in Customizing. The integration keeps one cart per call-up, not per account, and checks every outgoing field against its length before the page is rendered.
Testing an OCI connection
An OCI login can be tested without the buyer. A test page posts the call-up parameters to the store, with a HOOK_URL that points to an address you control. That address records every field it receives, so the cart can be checked for length, number format and unit before a buyer sees it. Here the panelboard's store title, "Panelboard 100 A, 24 circuits, main breaker, surface mount", is 58 characters:
NEW_ITEM-DESCRIPTION[1] 29 of 40 ok
NEW_ITEM-QUANTITY[1] 120 ok
NEW_ITEM-UNIT[1] EA ok
NEW_ITEM-PRICE[1] 9.60 ok
NEW_ITEM-DESCRIPTION[2] 58 of 40 cut
The round trip that ends in a shopping cart can only be run from the buyer's SAP test system, with the test URL entered in its Customizing.
OCI next to cXML
| OCI | cXML | |
|---|---|---|
| Session start | the browser calls the store with parameters | a PunchOutSetupRequest server to server |
| Credentials | login fields through the browser; Secure OCI moves them to a server call | a shared secret in the document |
| Cart | NEW_ITEM form fields with fixed lengths |
one XML document in a form field |
| Order and documents after it | not in the specification | OrderRequest, confirmation, ship notice, invoice |
| Asked for by | SAP SRM and systems that implement OCI | Coupa, SAP Ariba |
The full comparison is in cXML vs OCI, and the documents are on cXML PunchOut.
Which systems ask for OCI
The specification is written for SAP SRM, and a buyer on SAP SRM asks for OCI. Other procurement systems implement the same call-up and the same form fields. AFAS Profit in the Netherlands is one: it takes the cart over OCI and sends the order as a cXML document, so a supplier with an AFAS customer needs both. What an SAP buyer needs on top of the session, such as unit codes that exist in their system, is on PunchOut for SAP.
What this means for your store
An OCI connection is a login address, a session per call-up and a cart page that gets every field length and format right. We build it on your existing store, keep the field mapping per buyer and run the order route that OCI leaves open, in cXML, EDI or from an email.
Every item a store needs for OCI is listed under group D of the supplier checklist. Tell us which system your customer runs.
Frequently asked questions
Is OCI the same as PunchOut?
OCI is one way to run a PunchOut session. SAP calls it the Open Catalog Interface; the other common protocol is cXML, used by Coupa and SAP Ariba. Both open your store from the procurement system and return a cart. OCI does it with browser parameters and form fields, cXML with XML documents. See cXML PunchOut.
Where is the OCI specification?
SAP publishes it as a PDF on help.sap.com: Open Catalog Interface 5.0, dated October 2012. Sections 2 and 3 describe the call-up and the cart fields as in OCI 4.0; sections 5 and 6 add Secure OCI and the JSON catalog replication of 5.0.
Does OCI send the purchase order?
No. The specification ends when the cart reaches the procurement system. The purchase order, the confirmation, the ship notice and the invoice need their own route: a cXML OrderRequest, EDI, or a PDF by email that someone retypes. AFAS Profit, for example, takes the cart over OCI and sends the order as cXML.
Can OCI carry VAT per line?
Not in a field of its own. The field list in section 3.2 of the specification has no VAT field. A buyer that needs a VAT rate per line reads it from one of the five customer fields, NEW_ITEM-CUST_FIELD1 to CUST_FIELD5, and which one is agreed per buyer.
What is Secure OCI?
A variant in which the user name, password and prices do not pass through the browser. SAP first calls the store server to server and gets a SessionId and a SessionTransmissionId back. The browser opens the catalog with the SessionId, and after shopping SAP fetches the cart items server to server with the SessionTransmissionId. Both IDs are valid for one session.
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