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.
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.
Methods and status codes
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.
Try it: read the status code
Match each HTTP status code to what it tells you.
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(...).
# 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=20Line 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
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.
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.
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.
Try it: order a write call
Put the steps of a PATCH to a BP address in order.
- 1Read the credentials from an environment variable
- 2Send the PATCH with the token, cookie and JSON body
- 3Send a GET with header x-csrf-token: fetch
- 4Check for 204, or read the error JSON on a 400
- 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.