Indu Learning Platform
Course/Unit 4 · Data engineering for master data
Lesson 4-3

APIs: REST, OData and JSON

How systems and AI agents read and write SAP master data through REST and OData APIs, and how to call one yourself.

Watch firstWhat is a REST API? · IBM TechnologyOpen on YouTube ↗

Why APIs matter here

More and more master data traffic goes through APIs: a supplier portal creating a BP, CPI pushing changes, a Fiori app reading, an AI agent looking up a partner. REST means resources have URLs and you act on them with HTTP methods. OData is SAP's flavour of REST, adding $metadata and standard query options. JSON is the text the data comes back in.

Your clientPostman, Python, CPI, AI agentJSON payloadthe data as textOData protocol$metadata, $filter, $expandREST over HTTP(S)GET POST PATCH DELETESAP Gateway / CDS viewBUT000, ADRC underneath
You mostly work in the top three layers.

Methods and status codes

HTTP methodMeaningBP exampleOld-world analogueGETReadRead partner 100045Display in BPPOSTCreateCreate a new supplier BPLSMW / Migration CockpitPATCHChange some fieldsUpdate e-mail addressChange in BPDELETEDelete (where allowed)Delete an address usageDeletion flag
Method + URL + (for writes) a JSON body.

Anatomy of a read request

The Gateway checks authorisation, the OData service reads CDS views over the BP tables, and rows return as JSON. For debugging: 401/403 is the Gateway (user, role, API key), not your data. A 200 with an empty results list means the call worked but the filter matched nothing.

Client / agentSAP GatewayOData serviceCDS view / tablesGET …/A_BusinessPartner('100045')Authorised: route requestSELECT with keys and optionsRow(s)200 OK + JSON
Every SAP OData API you call follows this shape.

Try it: read the status code

Try it · Match

Match each HTTP status code to what it tells you.

Pick an item on the left, then its match on the right.

OData query options

Filtering, field selection and joins happen in the URL, so the server does the work. API_BUSINESS_PARTNER is an OData V2 service; its entity set A_BusinessPartner reaches addresses through the navigation property to_BusinessPartnerAddress. In V2, name search uses substringof('Steel',OrganizationBPName1); V4 uses contains(...).

OptionWhat it doesSQL equivalent$filterRestrict rowsWHERE$selectChoose fieldsSELECT col1, col2$expandFollow navigationJOIN to child table$orderbySortORDER BY$top / $skipPage through resultsLIMIT / OFFSET
If you can write SQL, you already understand OData query options.
OData URLs
# Base URL of the sandbox service (send your APIKey header)
https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_BUSINESS_PARTNER

# First 5 organisations, three fields, as JSON
.../A_BusinessPartner?$filter=BusinessPartnerCategory eq '2'
    &$select=BusinessPartner,OrganizationBPName1,CreationDate
    &$top=5&$format=json

# Partner plus its addresses in one call
.../A_BusinessPartner('1000000')?$expand=to_BusinessPartnerAddress

# Addresses in India, sorted by city
.../A_BusinessPartnerAddress?$filter=Country eq 'IN'&$orderby=CityName&$top=20

Line breaks are for readability; a real URL is one line, with spaces encoded as %20 (Postman and requests do this for you).

Try it: build the OData URL

Try it · Fill the blanks

Complete the requests against API_BUSINESS_PARTNER.

Organisations only, two fields, first 5:
.../A_BusinessPartner?=BusinessPartnerCategory eq '2'&=BusinessPartner,OrganizationBPName1&=5

One partner with its addresses:
.../A_BusinessPartner('1000000')?=to_BusinessPartnerAddress

Indian addresses sorted by city:
.../A_BusinessPartnerAddress?$filter=Country eq 'IN'&=CityName

What comes back: JSON

Curly braces hold an object, square brackets a list. OData V2 wraps results in d, lists in d.results (V4 uses value). Expanded navigation properties nest with their own results. The API names map straight back to the tables you migrated into. Asking an AI model for JSON with these exact field names makes its output checkable and API-ready.

API fieldTable.field you knowBusinessPartnerBusinessPartnerCategoryOrganizationBPName1AddressIDCityName / PostalCodeBPTaxNumberBUT000.PARTNERBUT000.TYPEBUT000.NAME_ORG1BUT020.ADDRNUMBERADRC.CITY1 / POST_CODE1DFKKBPTAXNUM.TAXNUMlink to ADRCto_BusinessPartnerTax
Long readable API names, same BP tables underneath.

Call the sandbox yourself

The SAP Business Accelerator Hub (api.sap.com) offers a sandbox for the Business Partner API. Requests send your personal key in an APIKey header.

Step through · 1 of 6
Log in toapi.sap.comFind the APIAPI_BUSINESS_PARTNERCopy API keyShow API KeyBuild requestPostman / requestsAdd headerAPIKey: <key>Read JSONd.results
Sign in to the SAP Business Accelerator Hub with a free SAP account.
Click through your first API call.
Python
import os
import requests

BASE = "https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_BUSINESS_PARTNER"
headers = {"APIKey": os.environ["SAP_API_KEY"], "Accept": "application/json"}
params = {
    "$filter": "BusinessPartnerCategory eq '2'",
    "$select": "BusinessPartner,OrganizationBPName1",
    "$top": 5,
}
r = requests.get(f"{BASE}/A_BusinessPartner", headers=headers, params=params, timeout=30)
r.raise_for_status()                        # stop on 4xx / 5xx
for bp in r.json()["d"]["results"]:
    print(bp["BusinessPartner"], bp["OrganizationBPName1"])

Writes and CSRF tokens

Writing to an on-premise or private cloud OData V2 service needs a handshake: a GET with x-csrf-token: fetch returns a token and session cookie, then the POST or PATCH sends both. An AI agent that 'proposes a BP change' makes exactly these calls; your job is deciding which checks (duplicate check, MDG change request) sit in front of it.

ClientOData serviceGET (x-csrf-token: fetch)200 + token + cookiePATCH A_BusinessPartnerAddress(...) + token204 No Content (or 400 + error JSON)
The CSRF handshake for changes.

Try it: order a write call

Try it · Put in order

Put the steps of a PATCH to a BP address in order.

  1. 1Read the credentials from an environment variable
  2. 2Send the PATCH with the token, cookie and JSON body
  3. 3Send a GET with header x-csrf-token: fetch
  4. 4Check for 204, or read the error JSON on a 400
  5. 5Keep the returned token and session cookie

Remember

  • REST = resources and HTTP methods; OData = REST plus metadata and standard query options; JSON = the payload.
  • $filter, $select, $expand, $orderby and $top map onto SQL you already know, and API fields map back to BUT000, BUT020/ADRC and tax tables.
  • Writes need a CSRF token; in an MDG landscape, governed changes go through change requests, not raw writes.

Check yourself

Which OData option returns a partner's addresses in the same response?
In an OData V2 JSON response, where do you usually find the list of records?
Which HTTP method fits 'change the e-mail on an existing BP address'?
OrganizationBPName1 in API_BUSINESS_PARTNER corresponds most closely to which table field?