Skip to main content

Write to SAP S/4HANA using the API Tool

Updated this week

Introduction

This template shows how to send data from Savant back into SAP S/4HANA by calling SAP’s application-layer APIs. The goal is simple: take records you prepared or computed in Savant, map them into the shape SAP expects, and post them so SAP runs its normal validation and posting logic.

Journal Entries are used below as the concrete example, but the same pattern works for many write-back flows in S/4HANA (ex: create or update business objects via SAP services exposed through SOA Manager or other SAP API surfaces).

Business Impact

Write-back turns Savant from “analytics output” into “operational input.”

Common use cases:

  • Finance adjustments: allocations, accruals, reclasses

  • Data stewardship: correcting master data fields in upstream systems (where allowed)

  • Process automation: take an exception list produced in Savant and push approved updates into SAP

  • Closing workflows: generate postings from reconciliations and push them back into SAP with traceability

What This Template Does

You will:

  1. Prepare a dataset in Savant that represents the business transaction you want SAP to record

  2. Configure an API Tool node to call an SAP endpoint

  3. Construct the request body (SOAP in this example) using fields from your dataset

  4. Send requests either synchronously or asynchronously depending on volume and latency needs

  5. Capture SAP responses for monitoring, retries, and audit logs

Before You Start

You’ll need a few things from your SAP team (Basis / integration partner):

  • The endpoint URL for the service you will call (often configured via SOA Manager for SOAP services)

  • The WSDL (for SOAP) or OpenAPI spec (for REST) so you know the exact required structure

  • Authentication approach for each environment (dev/test/prod)

  • Any required SAP headers, SOAPAction settings, client parameters, and namespaces

  • Guidance on monitoring and error handling (ex: where to see processing results in SAP)

Data In – What Savant Expects

The cleanest pattern is: one row per “line-level” record, and then group those rows into a higher-level “document” when you build the API request.

For the Journal Entry example:

  • Each row represents a journal entry line item

  • A shared journal_entry_id groups multiple rows into one posted Journal Entry

  • Header-level fields can either be repeated on every row, or derived from the “first row” in a group

Suggested columns (adapt to your SAP service requirements):

  • Grouping: journal_entry_id

  • Header: company_code, document_date, posting_date, currency, plus message metadata like message_id, creation_datetime_utc, sender_business_system_id

  • Line item: line_number, gl_account, amount, debit_credit_code, document_item_text, cost_center (and any additional assignment fields your org requires)

Data Out – What Gets Written to SAP

Savant will send an HTTP request to SAP’s service endpoint. In this example that’s a SOAP POST that creates journal entries in bulk.

Key idea: Savant does not “write to HANA” – it writes to SAP through the application layer, so SAP’s standard posting rules, validations, and persistence behavior apply.

Template steps

Step 1 – Load or build the dataset in Savant

  • Bring in your source data (file, connector, database)

  • Transform it into the target write-back shape (the “one row per line-level record” model)

  • Validate it early (ex: ensure debits and credits balance per journal_entry_id)

Optional but recommended:

  • Add a status field (ex: ready_to_post) so you can control what gets posted

  • Add an idempotency key (often message_id) so retries don’t create duplicates

Step 2 – Add an API Tool node

When configuring the API Tool, you can dynamically insert values from your dataset into the URL, headers, or body by referencing a column name in double curly braces:

  • {{column_name}}

Examples:

  • URL: .../endpoint?sap-client={{sap_client}}

  • Header: X-Correlation-ID: {{message_id}}

  • Body: <CompanyCode>{{company_code}}</CompanyCode>

Now configure:

  • Method: typically POST for create, PATCH/PUT for update (depends on SAP API)

  • URL: provided by SAP team (often includes sap-client query param in SOAP setups)

  • Headers:

    • For SOAP, Content-Type: text/xml; charset=utf-8 is common

    • Some services require a SOAPAction header (value depends on WSDL)

  • Auth:

    • Common in non-prod: Basic Auth

    • Common in prod: tighter controls (mTLS, SSO, gateway policies)

Step 3 – Build the request body from your dataset

This is the heart of the template. General pattern:

  • For each grouped “document” (ex: a Journal Entry), construct one request that includes:

    • Message/header information

    • Document header fields

    • A repeated list of line items populated from the rows in that group

Journal Entry example (conceptually):

  • <MessageHeader> populated from metadata columns

  • <JournalEntry> header populated from header columns

  • <Item> repeated for each line item row in that journal_entry_id group

Implementation tips:

  • Keep your XML/JSON request in one place (the API Tool body)

  • Use Savant’s field placeholder syntax to insert values dynamically

  • If SAP expects numeric formatting or fixed date formats, normalize them in Savant first

Step 4 – Choose synchronous vs asynchronous posting

Pick based on volume and operational needs:

  • Synchronous: you get a definitive response immediately – best for small volumes and interactive runs

  • Asynchronous: SAP queues and processes in the background – best for bulk posting and reducing timeout risk

In real life, most “bulk create” scenarios behave better asynchronously.

Step 5 – Capture responses, monitor, and retry safely

At minimum, store:

  • Request identifier (ex: message_id)

  • SAP response status and any returned document numbers

  • Error payloads for troubleshooting

Monitoring:

  • Your SAP team will usually point you to the right place (often AIF monitoring for interface messages in many landscapes)

Retries:

  • Only retry in a way that won’t create duplicate postings

  • Use idempotency keys where possible

  • If the SAP API does not support idempotency, implement a “posted ledger” in Savant (or downstream) keyed by message_id + journal_entry_id

Journal Entries example – mapping checklist

When your example is Journal Entries, sanity-check these before posting:

  • Every journal_entry_id group balances (total debits = total credits)

  • Company code is consistent within a group

  • Currency is consistent within a group (unless your SAP service supports multi-currency line items)

  • GL accounts exist and are allowed for posting

  • Posting date and document date are valid and in open periods

  • Required CO assignments are present when needed (ex: cost center)

Troubleshooting Quick Hits

  • 400/415 errors – request shape or Content-Type mismatch (SOAP 1.1 vs 1.2 is a common culprit)

  • Auth failures – credentials, network allowlists, TLS requirements, or gateway policy mismatches

  • “Posted with errors” – SAP accepted the message but rejected business validation; inspect the detailed error message path SAP provides

  • Timeouts – switch to async and/or reduce payload size per request (batching)

Did this answer your question?