SAP S/4HANA Cloud – Gotchas
SAP S/4HANA Cloud is SAP's intelligent cloud ERP suite covering finance, procurement, sales, and more, exposed via OData v2/v4 APIs through the SAP API Business Hub.
20 gotchas across 10 resources
These are connector-specific behaviors and limitations to be aware of when integrating.
Bill Credit Notes2 gotchas
billCreditNotesAddreference is required on create (SAP rejects a supplier credit note without a document reference) and note is limited to 25 characters. number is assigned by SAP and read-only — it is the SAP document number, not the caller's reference. subsidiary.id is required and selects the company the credit note posts to — it cannot be supplied any other way. A posted credit note reads back as status: authorised and is immutable: update is unsupported, and delete posts a reversal rather than removing the document.
billCreditNotesDeleteDeleting cancels the posted credit note: SAP posts a reversal document and the credit note reads back as
voided. Only a bill credit note can be cancelled here: the id of a bill returns 404 and nothing is
cancelled (use DELETE /accounting/bills/{id}). If the document type can't be verified (for example SAP is
unavailable), the request fails and nothing is cancelled; a 429 or 5xx can be retried.
Bill Payments1 gotcha
billPaymentsAddSAP S/4HANA Cloud creates the bill payment as a standalone financial accounting posting. It does not run
SAP's automatic payment program. company_id, supplier.id and account.id are required. If SAP rejects the
posting (for example an unknown bank account or a supplier not set up in the company), the request fails with a
400 and nothing is posted.
Bills3 gotchas
billsAllSupplier credit notes are excluded from this list and returned under the bill-credit-notes resource instead.
billsAddRequired fields on create: company_id, bill_date, supplier.id, currency, total and line_items.
The posting date is set to bill_date.
Each line item is either a purchase-order line or a G/L line:
- Lines with
line_items[].purchase_order.idare posted against that purchase order. Optionally provideline_items[].purchase_order.line_numberfor the purchase order item. - All other lines are G/L lines and require
line_items[].ledger_account.id(or.code). A line with neither a purchase order nor a ledger account is rejected with a 400.
line_items[].tax_rate.code takes the SAP tax code (e.g. V1). SAP S/4HANA Cloud does not expose tax
rates as readable data, so the tax code must be supplied directly.
billsDeleteCancellation is supported and reverses the posted supplier invoice. By default, reversal reason 01 is used and the posting date is set to today (UTC). Override via pass_through is supported.
Only a bill can be cancelled here: the id of a bill credit note returns 404 and nothing is cancelled (use
DELETE /accounting/bill-credit-notes/{id}). If the document type can't be verified (for example SAP is
unavailable), the request fails and nothing is cancelled; a 429 or 5xx can be retried.
Credit Notes2 gotchas
creditNotesAllCredit notes are SAP FI customer credit memos read from the accounting-document line
items, grouped into one record per document. type is always
accounts_receivable_credit; status is authorised, or paid once the customer item has
been cleared. Every posting line of the document other than the customer line is returned
as a line_items entry — including tax lines, which appear as a line on the tax account
rather than as total_tax. sub_total, total_tax, balance and allocations are not
returned. created_at is the date the document was entered and date_issued its document
date; both carry a date only (midnight UTC).
Supported filters are updated_since, created_since and number; customer_id is not
supported. The date filters compare on whole days (the time part is ignored) and are
inclusive of the day given. number is the SAP document number and is only unique within a
company and fiscal year, so filter[number] can return several records — use id
(company:fiscal_year:document) to address a single one.
limit applies to SAP posting lines, not to credit notes: a page can hold fewer credit
notes than limit, the last credit note on a page can be returned with only some of its
line_items, and no next cursor is returned. Results are newest first. Use the maximum
limit (200) and narrow the set with created_since or updated_since; a document with
more lines than fit on a page cannot be read completely from the list — fetch it by id.
creditNotesAddSAP S/4HANA Cloud creates a pure FI customer credit memo (the accounts-receivable mirror of
an invoice on this connector). This is not an SD credit memo request or billing document —
no pricing, no sales-order link, and it will not appear in SD reporting. company_id,
customer.id, currency, a positive total_amount and at least one line_items[] entry
with ledger_account.id or ledger_account.code (the revenue account to debit) are
required; a zero or negative total_amount is rejected, because the connector always posts
the credit direction and SAP would otherwise accept a reversed document silently. The
line_items[].total_amount values must add up to total_amount, each as a positive
number — SAP rejects an unbalanced document, an unknown ledger account, a customer not
set up in the company, and an account that requires a tax code or a line description;
the request then fails with a 400 and nothing is posted.
note is written as the 25-character document header text and reference as the
16-character document reference; both are returned on reads. line_items[].description
is written as the line text (50 characters) and is required by SAP for some accounts.
line_items[].department_id posts the cost center and line_items[].tracking_categories[0].id
the profit center; the header-level department_id and tracking_categories are ignored.
Tax is not posted: tax_code, total_tax and line_items[].tax_rate are ignored, so a
revenue account that requires a tax code cannot be used — post tax as its own line on the
tax account. allocations and terms are ignored; the credit is not applied to any
invoice. number is assigned by SAP and cannot be set. Posted credit notes are immutable:
update and delete are unsupported, and SAP's correction path is a separate reversal
document.
Customers3 gotchas
customersAddCreating a customer requires a correspondence language and a business partner grouping. They default to EN
and BP01. Override either one with pass_through (extend_object), for example:
"pass_through": [{"service_id": "sap-s4hana-cloud", "extend_object": {"BusinessPartnerGrouping": "BP02", "CorrespondenceLanguage": "DE"}}]
Which grouping to use depends on the SAP tenant. Each tenant configures whether a grouping assigns
numbers automatically. If the grouping requires a manually assigned number, SAP returns
400 Grouping <code> has external number assignment. Please enter a valid number. Either use a grouping
that assigns numbers automatically, or supply the number in the same extend_object as
"BusinessPartner": "<8–10 digit number, unique in the tenant>".
An address with a country is required. Provide addresses[0] with at least country (e.g. US, DE).
Without it, SAP returns 400 Country/Region Key ... is a required entry field.
customersUpdateOnly first_name, last_name, company_name, display_name and status can be updated.
Updates that include addresses, bank_accounts, emails, phone_numbers or websites are rejected
with a 400. Set those values when creating the record, or change them directly in SAP.
customersDeleteSAP does not allow deleting a customer that has been used in transactions. Delete blocks the customer instead:
the record stays in SAP and subsequent reads return status: inactive. Updating status to active
unblocks it.
Goods Receipts2 gotchas
goodsReceiptsAllOnly goods receipts against a purchase order are returned; other inbound and outbound goods movements recorded in the same document series are excluded from the list. Fetching by id is not restricted this way — see the get-one endpoint.
id is a composite of the document number and its fiscal year in the form
<document>:<year>, for example 5000000123:2026. Pass it back unchanged to
GET /accounting/goods-receipts/{id}. receipt_number, display_id and downstream_id
carry the bare document number.
No filters are supported: the accounting system records no last-changed timestamp on a
goods receipt, so filter[updated_since] cannot be honoured, and filter[supplier_id] and
filter[purchase_order_id] are not available either. Any filter is rejected with a 400
UnsupportedFiltersError. Only sort[by]=created_at is supported, and updated_at is
null. created_at carries the creation date at midnight UTC — the accounting system
records the creation time in a separate field this release does not read, so the time
component is always 00:00:00Z and receipts created on the same day have no guaranteed
order under sort[by]=created_at.
Supplier, purchase order and location are recorded per line. The header supplier,
purchase_order_id, po_number and location_id are populated only when every line
agrees; when a receipt spans several purchase orders or suppliers they are null and
line_items[].purchase_order carries the link. location_id is the plant and storage
location joined as <plant>/<storage location>. quantity_ordered, unit_price and
line_items[].purchase_order.line_id are not available; line_items[].purchase_order.line_number
is populated instead. line_items[].total_amount is populated only when an amount was
entered on the goods movement; the value of a receipt priced from its purchase order is not
exposed.
Goods receipts are immutable. A cancellation is posted as a separate reversal document: the
reversal is returned as its own receipt with status: cancelled, and the original document
is also reported as cancelled. meta.total_count is populated.
goodsReceiptsOneid must be the composite <document>:<year> value returned by the list endpoint, for
example 5000000123:2026. A bare document number, or any other shape, is rejected with a
400. Fetching by id returns the document whether or not it is a purchase-order receipt; the
purchase-order scope applies to the list endpoint only.
created_at carries the document's creation date at midnight UTC: the accounting system
records the creation time in a separate field that this release does not read, so the time
component is always 00:00:00Z.
Invoices2 gotchas
invoicesAllnumber is the SAP document number, which is only unique within a company code, so filter[number] can
return invoices from more than one company code. Use the full id
(<company code>:<fiscal year>:<document number>, e.g. 1710:2026:1800000001) to identify an invoice.
invoicesAddSAP S/4HANA Cloud creates the invoice as a financial accounting posting, not a billing document: no pricing, output or billing workflow is triggered.
Required: company_id, customer.id, currency, total, and at least one line item with
ledger_account.id.
totalmust equal the sum ofline_items[].total_amount.- The G/L account is taken from each line's
ledger_account. The top-levelledger_accountis not used. - The customer and each line's G/L account must already be set up in the company code given in
company_id.GET /accounting/subsidiarieslists the company codes. - Optional per line:
department_id(cost center) andtracking_categories[0].id(profit center).
If SAP rejects the posting (for example an unknown ledger account, a customer not set up in the company, or an
unbalanced document), the request fails with a 400 and nothing is posted.
Journal Entries1 gotcha
journalEntriesAddcompany_id (the SAP company code) is required. Journal entries are posted as standard G/L postings; the
SAP document type cannot be changed. If SAP rejects the posting (for example an unknown company code or ledger
account, or an unbalanced entry), the request fails with a 400 and nothing is posted.
Payments1 gotcha
paymentsAddSAP S/4HANA Cloud creates the payment as a financial accounting posting. It is not a bank statement import
or a payment-program run. company_id, customer.id and account.id are required. If SAP rejects the posting
(for example an unknown bank account or a customer not set up in the company), the request fails with a 400
and nothing is posted.
Suppliers3 gotchas
suppliersAddCreating a supplier requires a correspondence language and a business partner grouping. They default to EN
and BP01. Override either one with pass_through (extend_object), for example:
"pass_through": [{"service_id": "sap-s4hana-cloud", "extend_object": {"BusinessPartnerGrouping": "BP02", "CorrespondenceLanguage": "DE"}}]
Which grouping to use depends on the SAP tenant. Each tenant configures whether a grouping assigns
numbers automatically. If the grouping requires a manually assigned number, SAP returns
400 Grouping <code> has external number assignment. Please enter a valid number. Either use a grouping
that assigns numbers automatically, or supply the number in the same extend_object as
"BusinessPartner": "<8–10 digit number, unique in the tenant>".
An address with a country is required. Provide addresses[0] with at least country (e.g. US, DE).
Without it, SAP returns 400 Country/Region Key ... is a required entry field.
suppliersUpdateOnly first_name, last_name, company_name, display_name and status can be updated.
Updates that include addresses, bank_accounts, emails, phone_numbers or websites are rejected
with a 400. Set those values when creating the record, or change them directly in SAP.
suppliersDeleteSAP does not allow deleting a supplier that has been used in transactions. Delete blocks the supplier instead:
the record stays in SAP and subsequent reads return status: inactive. Updating status to active
unblocks it.