SAP S/4HANA — overview
This section explains which connector actions to use and how, so you (or an AI agent) can drive SAP S/4HANA correctly the first time. SAP exposes thousands of OData services with several interaction styles; the connector wraps all of them behind a consistent set of actions. Knowing which style a task needs is the whole game — start here, then jump to the worked example you need:
- Reading data
- Supplier invoice from a PO (MIRO)
- Bank statement (multi-line)
- Driving a transactional document manually
- Value helps
- Troubleshooting
You call actions from the Smart Chat (natural language) or the Web Editor
with run_connection_action(...). Both go through the same connector. Set up the
connection in the Abstra Console first.
All identifiers in these pages (purchase orders, company codes, suppliers, bank keys…) are placeholders — replace them with your own values.
Connection modes
Decided by the base URL you configure:
- Host mode — base URL is the SAP host (e.g.
https://my-sap-host:44300). Every activated OData service is reachable, resolved on demand. Action names are prefixed with the service:odata/api_business_partner_list_a_business_partner. - Single-service mode — base URL points at one service (e.g.
.../sap/opu/odata/sap/API_BUSINESS_PARTNER). Actions are not service-prefixed.
Authentication is Basic or OAuth2, configured on the connection.
If your SAP system needs a specific client (mandante), set it on the connection. A
wrong/absent client is a common cause of 401 even with correct credentials.
The action namespaces
Actions are grouped by interaction style. Pick the namespace that matches the task:
| Namespace | Use it for | Style |
|---|---|---|
odata/* | Reading and simple stateless writes on any entity set | Stateless CRUD |
softstate/* | Transactional BOPF documents (e.g. supplier invoice) | Soft-state session |
draft/* | Fiori Draft documents (e.g. bank statement, “Manage…” apps) | Draft session |
invoice/* | Curated supplier-invoice-from-PO helper (MIRO) | One-call helper |
statement/* | Curated bank-statement helper | One-call helper |
Action naming
Action-name suffixes are snake_case, derived from the SAP $metadata names:
odata/api_..._list_a_business_partner,get_a_business_partner,create_*,update_*,delete_*softstate/open_headers,update_headers,do_assignment,post,readdraft/open_c_arbankstatement,update_c_arbankstatement,add_c_arbankstatement_item,activate,discard,read
Discovering actions and their fields
The catalog can be large:
- List actions to find candidates by name.
- Get an action to see its exact field schema before calling it — per-entity
fields are loaded on demand, so
getActionis how you learn the parameters.
from abstra.connectors import list_connection_actions, get_connection_action
actions = list_connection_actions(connection_name="my_sap")
schema = get_connection_action(
connection_name="my_sap",
action_name="odata/api_business_partner_get_a_business_partner",
)
print(schema) # payloadSchema + returnSchema
Prefer the curated actions (invoice/*, statement/*) when they fit — they
do the whole transaction in one call and avoid the pitfalls below. Drop to
softstate/* / draft/* only for documents without a curated helper.
The transactional model (read before writing documents)
Creating real business documents (invoices, bank statements, …) is not a single POST. SAP drives these through a stateful session you open, fill incrementally, then effectivate. Two flavors:
- Soft-state / BOPF (e.g.
MM_SUPPLIER_INVOICE_MANAGE): keys likeNodeKey+State; ended with apostaction. - Fiori Draft (e.g.
FAR_MANAGE_BS_SRV): keys likeDraftUUID+IsActiveEntity; ended with anactivateaction.
Both follow the same shape:
open → set header fields → set / derive line items → post | activate
└──────────── you hold an opaque sessionId throughout ────────────┘
open_*returns asessionIdand the draft keys. Every subsequent action takes thatsessionId. You never buildguid'…'URLs and never touch CSRF tokens or cookies — the connector manages the session.post/activateeffectivate and end the session.discardrolls back.
create/add what the draft already madeWhen you open a transactional document, SAP frequently auto-creates the first
line-item row (empty). You fill it with update (a MERGE), not with
create/add. A plain POST to a line-item entity set on these services raises a
RAISE_SHORTDUMP. To add more lines, POST through the parent’s navigation (the
connector’s add_* / curated helpers do this for you) — never the flat item entity
set.
Quick decision guide
- Read / list / get one record →
odata/list_*,odata/get_*. - Create/update a simple, non-transactional entity →
odata/create_* / update_*. - Supplier invoice from a PO (MIRO) →
invoice/create_supplier_invoice_from_po(afterinvoice/lookup_purchase_order_for_invoice). - Bank statement →
statement/create_bank_statement(passlines). - Any other transactional document →
softstate/*ordraft/*:open → update → (derive) → post / activate, holding thesessionId; fill auto-created rows withupdate, add extra rows withadd.
If a curated action exists for your document, use it. Otherwise open a session and MERGE fields after opening — never rely on a single create/POST to carry a whole transactional document.