Skip to main content
Version: 5.1

Connect to SAP S/4HANA and Check Stock Availability

Time: About 45 minutes | What you'll build: An HTTP service with one GET resource that returns the live unrestricted-use stock of a material in a plant, read from SAP S/4HANA Cloud, with the total quantity and the quantity in each storage location.

Web shops, point-of-sale systems and warehouse apps all need the same answer before they promise anything to a customer: how much of this material is actually in stock? SAP S/4HANA knows, but its OData API speaks in SAP field names and returns quantities as text. In this guide you build a small REST API in front of it: a client calls GET /inventory/stock/{material}?plant={plant}, and the API asks SAP S/4HANA for that material's unrestricted-use stock in that plant and returns a clean JSON answer.

How it works​

Architecture diagram: a web shop, POS or warehouse app calls the WSO2 Integrator HTTP service GET /inventory/stock/{material} to check stock; the service uses the SAP S/4HANA Material Stock connector to read stock levels from SAP S/4HANA Cloud through the Material Stock Integration (SAP_COM_0164) scenario, and returns the stock as JSONArchitecture diagram: a web shop, POS or warehouse app calls the WSO2 Integrator HTTP service GET /inventory/stock/{material} to check stock; the service uses the SAP S/4HANA Material Stock connector to read stock levels from SAP S/4HANA Cloud through the Material Stock Integration (SAP_COM_0164) scenario, and returns the stock as JSON

Each request follows the same short flow:

  1. Read the stock records for the material and plant from the Material Stock API, filtered to unrestricted-use stock (stock type 01).
  2. Turn each SAP record into a simple {storageLocation, quantity, unit} entry, converting the quantity from text to a number.
  3. Add the quantities up into a total.
  4. Return the material, plant, total and per-storage-location breakdown as JSON.

Before you begin​

Prerequisites
  • A working WSO2 Integrator environment. See Setup.
  • Access to an SAP S/4HANA Cloud system, with a user that has the SAP_BR_ADMINISTRATOR role (or equivalent) to create communication users, systems and arrangements. You set up API access in Set up access in SAP S/4HANA.
  • A material that has stock in your system, and the plant it is stored in. The examples in this guide use material RM019 in plant 1710.

Set up access in SAP S/4HANA​

SAP S/4HANA Cloud exposes each API through a communication scenario. Before the integration can read stock, you create a communication user for it, register WSO2 Integrator as a communication system, and activate the Material Stock Integration (SAP_COM_0164) scenario for that system with a communication arrangement. All the apps used below are in the Communication Management group of the SAP Fiori launchpad.

Communication Management group in the SAP Fiori launchpad with the Communication Arrangements, Communication Systems and Maintain Communication Users appsCommunication Management group in the SAP Fiori launchpad with the Communication Arrangements, Communication Systems and Maintain Communication Users apps

Create a communication user​

  1. Open Maintain Communication Users and select New.
  2. Enter a User Name and a Description, set a Password, and select Create.

Note the user name and password. The integration uses them to call the API.

Create a communication system​

A communication system represents the external system that calls SAP S/4HANA, here your WSO2 Integrator integration.

  1. Open Communication Systems and select New.

  2. Enter a System ID and a System Name, then select Create.

    New communication system with the system ID and system nameNew communication system with the system ID and system name
  3. Under General > Technical Data, enter a Host Name and a Logical System (an uppercase ID of up to 10 characters, for example, INTEGRATOR).

  4. Under Users for Inbound Communication, add the communication user you created, with the User Name and Password authentication method.

    Communication user added under Users for Inbound CommunicationCommunication user added under Users for Inbound Communication
  5. Select Save.

Create the communication arrangement​

A communication arrangement activates a communication scenario for a communication system, which decides the APIs that system may call.

  1. Open Communication Arrangements and select New.

  2. In the Scenario value help, search for Material Stock Integration and select SAP_COM_0164. This scenario exposes API_MATERIAL_STOCK_SRV, the service the Material Stock connector calls.

    Select Communication Scenario dialog searching for Material Stock Integration, showing SAP_COM_0164Select Communication Scenario dialog searching for Material Stock Integration, showing SAP_COM_0164
  3. Enter an Arrangement Name and select Create.

    New Communication Arrangement dialog with scenario SAP_COM_0164 and an arrangement nameNew Communication Arrangement dialog with scenario SAP_COM_0164 and an arrangement name
  4. Select the communication system you created. The communication user is filled in as the inbound user.

  5. Select Save.

Note the hostname​

In the saved arrangement, the API-URL next to Own SAP Cloud System shows your API hostname (<unique id>-api.s4hana.cloud.sap).

API-URL of the SAP S/4HANA Cloud system shown in the communication arrangementAPI-URL of the SAP S/4HANA Cloud system shown in the communication arrangement

You now have the three values the integration needs: the hostname (for example, my123456-api.s4hana.cloud.sap), and the communication user's username and password. For more detail, see the SAP Material Stock connector setup guide.

Build the integration​

Build the flow in the Visual Designer, or switch to the Ballerina Code tab to see the equivalent source the designer generates for you.

Step 1: Create the integration and the HTTP service​

An HTTP service exposes your integration as a REST API, which is what the calling applications need.

  1. Create a new integration named StockAvailability in a project named StockAvailability.

    Create Integration dialog with the integration name and project name both set to StockAvailabilityCreate Integration dialog with the integration name and project name both set to StockAvailability
  2. On the Artifacts page, select HTTP Service under Integration as API.

    Artifacts page with the HTTP Service card selected under Integration as APIArtifacts page with the HTTP Service card selected under Integration as API
  3. Keep Design From Scratch, set Service Base Path to /inventory, and select Create.

    Create HTTP Service form with Design From Scratch selected and the service base path set to /inventoryCreate HTTP Service form with Design From Scratch selected and the service base path set to /inventory

Step 2: Add the stock resource​

  1. Select Add Resource, then GET.

  2. Set Resource Path to stock/[string material]. The part in square brackets is a path parameter, so the material number arrives as the material variable.

  3. Select Query Parameter, enter plant as the name, and select Save. A query parameter of type string is required by default, so a request without ?plant= is rejected with 400 Bad Request.

  4. Keep the default responses (200 with json, 500 with error) and select Save.

    New Resource Configuration panel with the GET method, the resource path stock/[string material], a string query parameter named plant, and 200 json and 500 error responsesNew Resource Configuration panel with the GET method, the resource path stock/[string material], a string query parameter named plant, and 200 json and 500 error responses

The resource opens in the flow designer, with Start, an empty step and the Error Handler.

Step 3: Connect to SAP S/4HANA​

  1. Select the + below Start, then Add Connection. Search for api_material_stock (1) and select the Api_material_stock_srv connector (2).

    Add Connection dialog searching for api_material_stock, with the Api_material_stock_srv connector card shown under Pre-built ConnectorsAdd Connection dialog searching for api_material_stock, with the Api_material_stock_srv connector card shown under Pre-built Connectors
    Why is the connector called Api_material_stock_srv?

    Each SAP S/4HANA connector is generated from one API on the SAP Business Accelerator Hub, and takes its name from that API's technical name. The technical name is the last part of the API's URL on api.sap.com, and also the name of the OData service the connector calls on your system (/sap/opu/odata/sap/API_MATERIAL_STOCK_SRV).

    Example
    API on api.sap.comMaterial Stock (A2X)
    api.sap.com URLhttps://api.sap.com/api/API_MATERIAL_STOCK_SRV/overview
    Ballerina packageballerinax/sap.s4hana.api_material_stock_srv (sap.s4hana. plus the technical name in lower case)
    Connector card in WSO2 IntegratorApi_material_stock_srv

    So, to find the connector for any other SAP S/4HANA API, open the API on api.sap.com, copy the technical name from its URL, and search for it in lower case. For example, Outbound Delivery (A2X) at https://api.sap.com/api/API_OUTBOUND_DELIVERY_SRV_0002/overview is the sap.s4hana.api_outbound_delivery_srv_0002 connector.

  2. Create three string configurables for the hostname, username and password you noted in Set up access in SAP S/4HANA, so the credentials are supplied at runtime instead of stored in the flow: in a field's Expression editor helper pane, select Configurables, then New Configurable. Name them sapS4HanaHostname, sapS4HanaUsername and sapS4HanaPassword.

  3. Bind Hostname to sapS4HanaHostname.

  4. Switch Config to Expression and enter:

    {auth: {username: sapS4HanaUsername, password: sapS4HanaPassword}}

    The connector uses Basic Authentication with the communication user from the setup guide.

  5. Keep the connection name apiMaterialStockSrvClient and select Save Connection.

    Configure Api_material_stock_srv dialog with Config set to an auth expression using sapS4HanaUsername and sapS4HanaPassword, and Hostname bound to sapS4HanaHostnameConfigure Api_material_stock_srv dialog with Config set to an auth expression using sapS4HanaUsername and sapS4HanaPassword, and Hostname bound to sapS4HanaHostname

Step 4: Read the stock records​

The Material Stock API exposes stock "in the account model": one record per combination of material, plant, storage location, batch, stock type and special stock. You read the records for one material and plant and keep only unrestricted-use stock.

  1. In the node panel, expand apiMaterialStockSrvClient under Connections and select List A Matl Stk In Acct Mods (listA_MatlStkInAcctMods).

    Node panel with the apiMaterialStockSrvClient connection expanded, listing its operations including List A Matl Stk In Acct ModsNode panel with the apiMaterialStockSrvClient connection expanded, listing its operations including List A Matl Stk In Acct Mods
  2. Expand Advanced Configurations, switch $Filter to Expression, and enter this string template. It inserts the material path parameter and the plant query parameter into an OData filter:

    string `Material eq '${material}' and Plant eq '${plant}' and InventoryStockType eq '01'`

    InventoryStockType eq '01' keeps only unrestricted-use stock, the stock you can actually sell or issue. Drop that condition if you also want quality-inspection or blocked stock.

  3. Set Result to stockRecords and select Save.

    listA_MatlStkInAcctMods operation form with the $Filter expression built from the material and plant variableslistA_MatlStkInAcctMods operation form with the $Filter expression built from the material and plant variables

Step 5: Shape the response​

SAP returns the records inside an OData envelope (d.results) and the quantity, MatlWrhsStkQtyInMatlBaseUnit, as text. Two Declare Variable steps turn that into the response.

  1. Select the + after the operation, then Declare Variable. Name it storageLocations, set Type to json[], and enter this expression. It builds one entry per storage location and converts the quantity to a decimal:

    from var s in stockRecords.d?.results ?: [] select {storageLocation: s?.StorageLocation, quantity: check decimal:fromString(s?.MatlWrhsStkQtyInMatlBaseUnit ?: "0"), unit: s?.MaterialBaseUnit}
    Declare Variable form for storageLocations of type json[] with a query expression over stockRecords.d?.resultsDeclare Variable form for storageLocations of type json[] with a query expression over stockRecords.d?.results
  2. Add another Declare Variable after it. Name it totalQuantity, set Type to decimal, and enter:

    decimal:sum(...from var s in stockRecords.d?.results ?: [] select check decimal:fromString(s?.MatlWrhsStkQtyInMatlBaseUnit ?: "0"))

    The designer shows this step as decimal : sum on the canvas, because its value comes from a function call.

    Declare Variable form for totalQuantity of type decimal with a decimal:sum expressionDeclare Variable form for totalQuantity of type decimal with a decimal:sum expression

Step 6: Return the result​

  1. Add a Return step after totalQuantity and enter:

    {material: material, plant: plant, totalQuantity: totalQuantity, storageLocations: storageLocations}
    Return form with a record expression containing material, plant, totalQuantity and storageLocationsReturn form with a record expression containing material, plant, totalQuantity and storageLocations
  2. Select Save. The completed flow reads the stock, builds the breakdown, totals it and returns it.

    Completed resource flow: Start, the listA_MatlStkInAcctMods call to apiMaterialStockSrvClient, the storageLocations declaration, decimal : sum for totalQuantity, Return, and the Error HandlerCompleted resource flow: Start, the listA_MatlStkInAcctMods call to apiMaterialStockSrvClient, the storageLocations declaration, decimal : sum for totalQuantity, Return, and the Error Handler

If the SAP call fails (for example, wrong credentials or a missing communication arrangement), the Error Handler returns the error, and the client receives 500 Internal Server Error.

Run and verify​

  1. Open Configurations and supply values for sapS4HanaHostname, sapS4HanaUsername and sapS4HanaPassword, or add them to Config.toml with Edit Config.toml. See Configurations. Keep Config.toml out of source control.

    Configurable Variables page listing sapS4HanaHostname, sapS4HanaUsername and sapS4HanaPassword as required string valuesConfigurable Variables page listing sapS4HanaHostname, sapS4HanaUsername and sapS4HanaPassword as required string values
  2. Select Run. The service starts on port 9090.

  3. On the resource, select Try It, then Try It (Try resource with Hurl Client). Replace the placeholders so the request reads as follows, and run the cell:

    GET http://localhost:9090/inventory/stock/RM019

    [QueryStringParams]
    plant: 1710

    You can also call the API with any HTTP client, for example curl "http://localhost:9090/inventory/stock/RM019?plant=1710".

  4. The response lists the unrestricted-use stock of the material in each storage location of the plant, and the total:

    Hurl Try It notebook showing the GET request for RM019 in plant 1710 and a 200 OK response with totalQuantity 38 and three storage locations, 171A, 171B and 171CHurl Try It notebook showing the GET request for RM019 in plant 1710 and a 200 OK response with totalQuantity 38 and three storage locations, 171A, 171B and 171C
    {
    "material": "RM019",
    "plant": "1710",
    "totalQuantity": 38.000,
    "storageLocations": [
    {"storageLocation": "171A", "quantity": 20.000, "unit": "KG"},
    {"storageLocation": "171B", "quantity": 10.000, "unit": "KG"},
    {"storageLocation": "171C", "quantity": 8.000, "unit": "KG"}
    ]
    }

    A material with no unrestricted-use stock in the plant returns "totalQuantity": 0 and an empty storageLocations list.

The integration overview now shows the whole API: the HTTP listener, the /inventory service with its GET resource, and the SAP S/4HANA connection it uses.

StockAvailability integration overview showing httpDefaultListener connected to the /inventory HTTP service with its GET /stock/[string material] resource, which uses the apiMaterialStockSrvClient connectionStockAvailability integration overview showing httpDefaultListener connected to the /inventory HTTP service with its GET /stock/[string material] resource, which uses the apiMaterialStockSrvClient connection

What's next​

Now that the API works, you can take it further:

  • Deploy it. Ship it to WSO2 Cloud, a Docker container, Kubernetes, or a virtual machine, and put it behind your API gateway.
  • Check several materials at once. Add a POST /inventory/stock resource that takes a list of materials and builds an OData filter such as (Material eq 'RM019' or Material eq 'FG011') and Plant eq '1710', so a shopping cart needs a single call.
  • Reserve the stock. Once availability is confirmed, create a reservation with the SAP Reservation Document connector so the quantity is held for the order.
  • Explore the other operations. The Material Stock action reference covers every operation, including reading serial numbers for serialized materials.