ml-connector
SAP S/4HANABrex

SAP S/4HANA and Brex integration

SAP S/4HANA runs finance, procurement, and the general ledger. Brex runs corporate cards, expenses, and bill pay. Connecting the two means the card spend and expenses Brex codes against GL accounts post into SAP S/4HANA as journal entries or supplier invoices without re-keying. Vendors stay aligned between the two systems so Brex payments reference the same suppliers SAP holds. Because Brex card transactions are read-only and SAP holds the official ledger, ml-connector treats Brex as the spend source and SAP as the system of record.

How SAP S/4HANA works

SAP S/4HANA Cloud exposes business partners, supplier invoices, journal entries, purchase orders, GL accounts, and cost centers through OData V2 and V4 services on a tenant-specific URL such as my123456-api.s4hana.ondemand.com. Production access uses OAuth 2.0 client credentials provisioned through a Communication Arrangement an SAP admin must set up. Supplier invoices and journal entries can be written, while GL accounts and cost centers are read-only master data, and every write requires an X-CSRF-Token fetched first. S/4HANA has no native outbound webhooks, so records are read by polling with a filter on LastChangeDateTime.

How Brex works

Brex exposes card and cash transactions, expenses, vendors, transfers, accounting records, and custom accounting fields through its REST Developer API. Most modern calls use the v2 base at api.brex.com while payments and expense endpoints still use the v1 base at platform.brexapis.com, all authenticated with a bearer token. Card transactions are read-only, while vendors, accounting records, and fields support read and write. Brex pushes events through Svix-signed webhooks, including ACCOUNTING_RECORD_READY_FOR_EXPORT, which fires once a transaction is coded and ready for export to an ERP.

What moves between them

The main flow runs from Brex into SAP S/4HANA. Once Brex has coded a card transaction or expense and the accounting record is ready for export, ml-connector reads it and posts a journal entry or supplier invoice into SAP, mapped to the matching GL account and cost center. Vendor records flow from SAP business partners into Brex so bill-pay transfers reference suppliers that already exist on both sides. Brex accounting fields, which carry custom dimensions, are aligned with SAP cost centers and accounts so each posting lands on a valid combination. SAP GL accounts and cost centers are read-only master data, so ml-connector reads them for mapping but never writes ledger structure back into Brex.

How ml-connector handles it

ml-connector stores both credential sets encrypted. On the Brex side it sends the bearer token on every request and selects the v1 or v2 base URL per endpoint, since payments and expenses still live on the legacy host. On the SAP side it requests and caches an OAuth 2.0 client-credentials token, refreshing it before its roughly twelve-hour expiry, and fetches a fresh X-CSRF-Token before any write, re-fetching and retrying when SAP returns 403 for a stale token. GL accounts and cost centers are mapped first, so every Brex accounting record resolves to a real SAP account and cost center before a journal entry or supplier invoice is posted. The ACCOUNTING_RECORD_READY_FOR_EXPORT webhook, verified with Svix signing, triggers the work as soon as a record is coded, and a scheduled poll using LastChangeDateTime and the Brex next_cursor backfills anything a webhook missed. Brex merchant names rarely match SAP supplier names exactly, so ml-connector keeps a vendor mapping rather than guessing. After a successful post, it calls Brex to mark the record EXPORTED so the same spend is not posted twice. Both Brex and SAP return HTTP 429 when throttled, so ml-connector backs off with jitter, dedupes on the Brex record id and a BullMQ jobId, and keeps a full audit trail with replay on every record.

A real-world example

A mid-sized software company with about 250 employees runs SAP S/4HANA Cloud for finance and issues corporate cards through Brex for travel, software subscriptions, and vendor payments. Before the integration, an accountant exported coded expenses from Brex each week and keyed the journal entries into SAP by hand, which meant card spend lagged the ledger by days, dimensions were sometimes mistyped, and month-end close started with the corporate card clearing account out of balance. With SAP S/4HANA and Brex connected, each coded card transaction posts into SAP as a journal entry against the right cost center within the polling window, and vendors stay aligned for bill pay. Close starts with the card spend already reconciled, and the weekly re-keying step is gone.

What you can do

  • Post coded Brex card transactions and expenses into SAP S/4HANA as journal entries or supplier invoices against the correct GL accounts and cost centers.
  • Keep Brex vendors aligned with SAP business partners so bill-pay transfers reference the same suppliers.
  • Map Brex accounting fields and GL codes to SAP cost centers and accounts so every posting lands on a valid combination.
  • Authenticate Brex with its bearer token and SAP S/4HANA with OAuth 2.0 client credentials, fetching the X-CSRF-Token required for every write.
  • React to the ACCOUNTING_RECORD_READY_FOR_EXPORT webhook with a scheduled poll backfill, retries, jobId dedup, and a full audit trail on every record.

Questions

Which direction does data move between SAP S/4HANA and Brex?
The main flow is Brex into SAP S/4HANA. Coded card transactions and expenses move from Brex into SAP as journal entries or supplier invoices, while vendor records flow from SAP business partners into Brex for bill pay. Brex card transactions are read-only and SAP GL accounts are read-only master data, so ml-connector reads them for mapping and never writes ledger structure back into Brex.
Does Brex push spend, or does ml-connector poll for it?
Both are supported. ml-connector subscribes to the Brex ACCOUNTING_RECORD_READY_FOR_EXPORT webhook, verified with Svix signing, so a coded record triggers a post as soon as it is ready. A scheduled poll using the SAP LastChangeDateTime filter and the Brex next_cursor backfills anything a webhook missed, since SAP S/4HANA itself has no outbound webhooks and must be read by polling.
How does the integration handle SAP's X-CSRF-Token and OAuth requirements?
SAP S/4HANA requires an OAuth 2.0 client-credentials token, provisioned through a Communication Arrangement, on every call, and an X-CSRF-Token on every write. ml-connector caches the OAuth token and refreshes it before its roughly twelve-hour expiry, and it fetches a fresh CSRF token before each write. If SAP returns 403 for a stale token, it re-fetches and retries so the post still completes.

Related integrations

Connect SAP S/4HANA and Brex

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started