Blog

From Hybris and Commerce Cloud Order XML to TMF622 — One Capability, Three Surfaces

Kin Lane ·May 25, 2026
Table of contents

If you work anywhere near commerce, you already know the problem. The order is the most important object in the business — it is what gets fulfilled, billed, recognized as revenue, and shipped to the customer — and yet the order travels through the enterprise in whatever shape the originating platform happened to emit fifteen years ago. SAP Commerce (Hybris) emits an XML order envelope that predates TM Forum Open APIs. Salesforce Commerce Cloud’s OCAPI order XML predates them too. The downstream systems that need to read those orders — billing, provisioning, customer notifications, the warehouse, the dashboards, and now the AI agents — each end up writing their own little translator. Fifteen translators for one shape. None of them traceable. None of them observable. None of them talking to each other.

This is exactly the kind of seam a Naftiko capability is built to close.

What Naftiko actually is

Naftiko is an open framework for wrapping any upstream API — legacy, modern, internal, third-party — as a versioned capability. A capability is a single YAML file that names what the capability consumes (the upstream API in its real wire-level shape), and what it exposes (one or more clean, governed surfaces on top of it). The engine that reads the YAML runs as a container. The exposed surfaces can be REST endpoints, MCP tools for AI agents, gRPC, GraphQL, or all of the above — from the same spec, with the same auth, the same observability, the same tests.

The point is not to write yet another integration. The point is to stop writing integrations and start declaring them. One capability YAML replaces the fifteen translators. When the upstream changes, you change the consumes block. When a new downstream — say, an agent runtime, or a TMF-aligned partner — needs the same data in a different shape, you add an exposes block. The capability is the contract. The engine handles everything else.

Why convert legacy order XML to TMF622 at all

TM Forum’s TMF622 Product Ordering Management API v5.0 is the closest thing the industry has to a universal ordering vocabulary. It is REST. It is JSON. It is versioned. It carries productOrderItem, relatedParty, requestedStartDate, state, productOffering, itemPrice, note, agreement, payment, and billingAccount as first-class fields. Every modern BSS, every API gateway, every TMF-aligned partner integration, every commerce-aware AI agent already knows how to read it.

What that means in practice is the difference between fifteen one-off translators and one published contract. If your fulfillment partner speaks TMF622, your billing platform speaks TMF622, your portal speaks TMF622, and your agent stack speaks TMF622, then the only thing left to do is normalize whatever your Hybris or Commerce Cloud instance is actually emitting into that one shape. Once. Behind a capability. With observability on the seam.

The legacy XML is not going anywhere. Rip-and-replace projects on commerce platforms are how careers end, not how value gets delivered. The right move is to wrap, not replace — let Hybris keep doing what Hybris does well, let Commerce Cloud keep being the storefront, and put a Naftiko capability in front of them that hands the rest of the enterprise a TMF622 ProductOrder on every read.

What the capability looks like

The shape is intentionally simple. Two consumes blocks — one for the SAP Commerce OCC v2 order resource, one for the Salesforce Commerce Cloud OCAPI order resource. Both speak XML. Both authenticate with a bearer token. Both expose a per-order GET that returns the legacy envelope unchanged. On top of those, one exposes block per surface: MCP for agents, REST for humans and dashboards. The output of every exposed call is a clean TMF622 v5 ProductOrder JSON.

naftiko: "1.0.0-alpha2"

info:
  title: Manage Commerce Orders — TMF622
  description: >
    Wraps SAP Commerce (Hybris) and Salesforce Commerce Cloud order XML
    endpoints and exposes every order as a TMF622 v5 ProductOrder via REST
    and MCP. One capability, two upstreams, three surfaces, one contract.

binds:
  - namespace: env
    keys:
      HYBRIS_TOKEN: HYBRIS_TOKEN
      SFCC_TOKEN: SFCC_TOKEN

capability:
  consumes:
    - namespace: hybris
      type: http
      baseUri: "https://commerce.example.com"
      description: "SAP Commerce (Hybris) OCC v2 order resource  XML."
      authentication:
        type: bearer
        token: "{{HYBRIS_TOKEN}}"
      resources:
        - name: order
          path: "/occ/v2/{{site_id}}/orders/{{order_code}}"
          operations:
            - name: get-hybris-order
              method: GET
              headers:
                - name: Accept
                  value: "application/xml"
              inputParameters:
                - name: site_id
                  in: path
                  required: true
                - name: order_code
                  in: path
                  required: true

    - namespace: sfcc
      type: http
      baseUri: "https://commerce.demandware.net"
      description: "Salesforce Commerce Cloud OCAPI shop order resource  XML."
      authentication:
        type: bearer
        token: "{{SFCC_TOKEN}}"
      resources:
        - name: order
          path: "/s/{{site_id}}/dw/shop/v21_3/orders/{{order_no}}"
          operations:
            - name: get-sfcc-order
              method: GET
              headers:
                - name: Accept
                  value: "application/xml"
              inputParameters:
                - name: site_id
                  in: path
                  required: true
                - name: order_no
                  in: path
                  required: true

  exposes:
    - type: mcp
      address: "0.0.0.0"
      port: 3061
      namespace: manage-commerce-orders
      description: >
        TMF622 v5 ProductOrder fetcher for SAP Commerce (Hybris) and
        Salesforce Commerce Cloud. One tool per platform, identical
        output shape.
      tools:
        - name: get-hybris-order-tmf622
          description: "Fetch a Hybris order by site and order code, return as a TMF622 v5 ProductOrder."
          hints:
            readOnly: true
          inputParameters:
            - name: site_id
              type: string
              required: true
            - name: order_code
              type: string
              required: true
          call: hybris.get-hybris-order
          transform:
            engine: xslt
            template: "transforms/hybris-to-tmf622.xsl"

        - name: get-sfcc-order-tmf622
          description: "Fetch a Salesforce Commerce Cloud order by site and order number, return as a TMF622 v5 ProductOrder."
          hints:
            readOnly: true
          inputParameters:
            - name: site_id
              type: string
              required: true
            - name: order_no
              type: string
              required: true
          call: sfcc.get-sfcc-order
          transform:
            engine: xslt
            template: "transforms/sfcc-to-tmf622.xsl"

    - type: rest
      address: "0.0.0.0"
      port: 8091
      namespace: manage-commerce-orders-rest
      resources:
        - name: hybris-order
          path: "/productOrder/hybris/{site_id}/{order_code}"
          operations:
            - name: get-hybris-order-tmf622
              method: GET
              inputParameters:
                - name: site_id
                  in: path
                  required: true
                - name: order_code
                  in: path
                  required: true
              call: hybris.get-hybris-order
              transform:
                engine: xslt
                template: "transforms/hybris-to-tmf622.xsl"
        - name: sfcc-order
          path: "/productOrder/sfcc/{site_id}/{order_no}"
          operations:
            - name: get-sfcc-order-tmf622
              method: GET
              inputParameters:
                - name: site_id
                  in: path
                  required: true
                - name: order_no
                  in: path
                  required: true
              call: sfcc.get-sfcc-order
              transform:
                engine: xslt
                template: "transforms/sfcc-to-tmf622.xsl"

The two consumes blocks each name the legacy XML resource exactly as it lives today. The exposes block declares one MCP tool and one REST route per upstream. The transform blocks pin the conversion to a versioned XSLT — the order XML goes in, a TMF622 v5 ProductOrder JSON comes out. That XSLT is the single point of truth for how a Hybris order item becomes a productOrderItem, how the buyer block becomes a relatedParty with role customer, how the order total becomes an itemPrice, and how the order status becomes the TMF622 state. One file. One review surface. One diff when the mapping changes.

Traceable, observable, integrated into AI

This is where the capability stops being a translator and starts being a control surface. Three things change the moment the legacy XML moves behind a Naftiko capability.

Traceable. Every read of a Hybris or Commerce Cloud order now flows through one engine. That engine emits a trace per call: which upstream was hit, which credentials were used, which XSLT version produced the output, how long the upstream took, how long the transform took, what the caller asked for, what was returned. Today, when a billing dispute lands on someone’s desk, the answer to “what shape did the order actually arrive in?” is a guess. Behind a capability, it is a query.

Observable. The capability is one named workload — one set of metrics, one dashboard, one alerting target. If Hybris starts returning a malformed envelope at 2 a.m., you do not find out from a billing reconciliation report three days later. You find out from the capability’s error rate. If Commerce Cloud’s OCAPI starts shedding requests under load, you see it in one place, not in fifteen translator logs scattered across teams.

Integrated into AI. This is the part that did not exist when the legacy XML was written. The same capability that hands a TMF622 ProductOrder to your billing system over REST also hands the exact same shape to an AI agent over MCP — same auth, same trace, same observability, same XSLT version. When a support agent’s LLM asks “what is order 4815162342 in?” the answer comes through the same pipe the rest of the business already trusts. You do not stand up a separate AI integration. You add an exposes block.

The bigger move

Hybris and Commerce Cloud are not the problem. They are doing what they were built to do. The problem is that the rest of the enterprise has been quietly paying the cost of every team writing its own order translator. A capability turns that cost into one file, one container, one contract, one trace.

If you have a commerce platform emitting order XML today and a roadmap that says “TMF-align everything,” start with one capability. Hybris on Monday. Commerce Cloud on Tuesday. By Friday every downstream — billing, fulfillment, the dashboards, the agent stack — is reading TMF622 v5 from one URL, and the mapping is one XSLT review away from changing. That is what wrap-not-replace actually looks like in code.