# SAP still speaks IDoc, and IDoc is our home game

> transactions.dev · by visibility.cloud — 2026-07-31
> Written for the supply-chain ISV / traceability-vendor engineering org — the integration engineer who meets S/4HANA through a customer's system.

One thesis: **S/4HANA's modern OData APIs and its decades-old IDoc traffic
are two syntaxes for the same four documents, and because IDocs carry EDI
semantics in SAP framing, the transaction layer treats them as a first-class
dialect — compiled to the same CBV references as an 856 or a DESADV, not
shoved through a second pipeline.**

## Two faces, one cycle

Every S/4HANA estate you will meet as an ISV engineer has both faces
running at once. The catalog face is OData, and the operations that matter
for the record have exact names:

- `API_PURCHASEORDER_2` — the purchase order, OData v4. (The v2 service,
  `API_PURCHASEORDER_PROCESS_SRV`, was deprecated in August 2024; new
  wiring targets the v4 API.)
- `API_INBOUND_DELIVERY_SRV_0002` — the inbound delivery: the supplier's
  despatch advice as SAP models it, and the object a goods receipt posts
  against.
- `API_SUPPLIERINVOICE_PROCESS_SRV` — the supplier invoice.

The traffic face is IDoc, and it has not gone anywhere: **ORDERS05** for
purchase orders, **DELVRY03** and **DELVRY07** carrying
[DESADV despatch advices](/blog/eancom-desadv-walkthrough/), **INVOIC02**
for invoices. These remain the workhorse message
types moving between S/4HANA and its trading partners in 2026.

For a transaction layer this is not a complication, it is a homecoming. An
IDoc is a segment-structured business document with a control record — the
same anatomy as the [X12 and EDIFACT dialects](/blog/the-856-is-already-an-aggregation-tree/)
the parser already reads. The compile map is one table:

- `API_PURCHASEORDER_2` order / ORDERS05 → `po`
- inbound delivery / DELVRY03/07 (DESADV) → `desadv`
- goods receipt posted against the inbound delivery → `recadv`
- supplier invoice / INVOIC02 → `inv`

Note what the middle two rows buy you: **the inbound-delivery-plus-goods-
receipt pair yields both `desadv` and `recadv` from one flow** — the
document that promised the shipment and the document that closed it, joined
to the same delivery object, which is precisely the pairing the
[reconcile verdict](/blog/reconcile-is-a-verdict/) consumes.

## The proof artifact: one inbound delivery, compiled

A worked figure from the connector's committed output shape. An inbound
delivery notification for one pallet of one lot-tracked material compiles
to a receiving-side ObjectEvent skeleton carrying the two references and
the party context:

```json
{
  "type": "ObjectEvent",
  "action": "OBSERVE",
  "bizStep": "receiving",
  "disposition": "in_progress",
  "quantityList": [
    {
      "epcClass": "urn:epc:class:lgtin:4012345.011111.LOT2026A",
      "quantity": 48,
      "uom": "EA"
    }
  ],
  "bizTransactionList": [
    { "type": "desadv", "bizTransaction": "urn:epc:id:gdti:4012345.00001.0080012345" },
    { "type": "po", "bizTransaction": "urn:epc:id:gdti:4012345.00001.4500001234" }
  ],
  "sourceList": [
    { "type": "owning_party", "source": "urn:epc:id:pgln:4012345.00001" }
  ],
  "destinationList": [
    { "type": "owning_party", "destination": "urn:epc:id:pgln:0614141.00001" }
  ]
}
```

Every field there is core CBV machinery —
[`bizTransactionList` is a core field, not an extension](/blog/biztransaction-is-a-core-field/) —
and the output validates against the pinned official EPCIS 2.0 JSON schema
before it leaves the tool: superset where SAP's document carries more than
the standard models, and conformant always, because the two claims only
mean anything together.

## Why the identifiers are the best in the matrix

The reason that figure can be GS1-real rather than SKU-approximate is an
SAP fact worth stating precisely: **the material master carries per-unit
GTINs** — `MARA-EAN11` for the base unit plus the `MEAN` table for
additional GTINs per unit of measure — and **the Business Partner model
carries a GLN field with uniqueness enforcement**. No other system in our
verified connector matrix outside the standards rails ships both a
validated GTIN home and an enforced GLN home. (The matrix's full census is
[the GTIN-gap post](/blog/the-gtin-gap/); SAP and Business Central are the
two exceptions it names.)

So when the compile writes `epcClass` and `pgln` URIs above, it is reading
identity the customer's own master data already governs — not inferring it
from a free-text barcode column the way an
[ecommerce-sourced record](/blog/ecommerce-has-no-invoice-object/) must.

## Access honesty: sandbox for shape, customer for reality

The gates, stated the way you will actually hit them. SAP's Business
Accelerator Hub sandbox is genuinely public: a free SAP ID gets you an API
key and live try-out calls against `sandbox.api.sap.com`, which is enough
to verify shapes, field names, and the compile map before any commercial
conversation exists. Production is another matter — a real S/4HANA system,
communication arrangements configured by its administrators, and events
arriving via Enterprise Event Enablement into Event Mesh (topics like
`sap.s4.beh.purchaseorder.released.v1`). There is no self-serve door into
a customer's ERP, and this page does not pretend otherwise: the SAP
connector is activated **through the customer's own platform team**, who
hold the keys and the change windows.

That is not a weakness of the connector; it is the shape of the segment.
The estates running S/4HANA are exactly the counterparties whose IDoc
traffic your smaller customers already receive — which means the dialect
pays for itself even before any OData wiring happens, because DELVRY03
files arriving over the existing EDI plumbing compile on the same pipeline
as everything else.

## What lands where

The result of the compile is an event record that answers the questions
the paperwork alone cannot: which lot crossed which dock under which PO,
with the despatch advice and the receiving close on the same spine that
[epcis.dev](https://epcis.dev/business-transactions-in-epcis/) captures
and [visibility.cloud](https://visibility.cloud/asn-po-context-in-traces)
answers from. The identifiers ride through because SAP already governs
them; where a counterparty's data is weaker, the
[enrichment layer](https://barcoding.dev) does the bridging.

If an SAP estate is in your integration path — yours or a customer's —
[tell us which one](/get-access/). The access flow asks which systems you
run precisely so the SAP branch is wired in the order the answers demand.

---
Access: https://transactions.dev/get-access/ · All posts: https://transactions.dev/blog/ · Machine face: https://transactions.dev/llms.txt
