ml-connector
SAP S/4HANAExpensify

SAP S/4HANA and Expensify integration

SAP S/4HANA holds your general ledger, cost centers, and procurement master data. Expensify collects and approves employee expenses. Connecting them keeps your labor and travel costs reconciled automatically. Approved expense reports from Expensify post into SAP as journal entries allocated to the correct cost center and GL account, eliminating manual data entry during month-end close. ml-connector bridges the very different APIs on each side and moves reports on a schedule you control.

How SAP S/4HANA works

Expensify is a cloud-based expense management platform accessed through a REST API at https://integrations.expensify.com/Integration-Server/ExpensifyIntegrations. Authentication uses API key pairs (partnerUserID and partnerUserSecret) passed inline with every request. Expensify exposes expense reports, individual expenses and transactions, employees, policies and workspaces, corporate card transactions, and approval status. All data is retrieved by polling with date-range or status filters; Expensify has no webhooks. Employee state is returned in diff responses after updates. Corporate card data is read-only. Expensify is an expense management tool only, with no vendor master, invoicing, purchase order, or payment entities.

How Expensify works

SAP S/4HANA exposes finance, procurement, and master data through OData V2 and V4 REST APIs at tenant-specific URLs such as https://[tenant-id]-api.s4hana.ondemand.com/sap/opu/odata/sap/[SERVICE_NAME]. Authentication uses OAuth 2.0 Client Credentials with scopes defined per Communication Arrangement; the token endpoint URL is tenant-specific and must be copied from the Communication Arrangement, not constructed manually. SAP exposes cost centers, GL accounts, suppliers, purchase orders, and journal entries as key entities. GL Account and Cost Center APIs are read-only; GL Account Line Items are not designed for bulk extracts. SAP Cloud Public has no single OData API for outgoing payments. On-Premise deployments require the sap-client query parameter. No native webhooks; data is accessed via polling with LastChangeDateTime filters or delta tokens.

What moves between them

The main flow runs from Expensify into SAP S/4HANA. Approved expense reports are read from Expensify on a schedule (typically weekly or monthly before close). Each report's expenses are mapped to GL accounts and cost centers in SAP based on the employee's department or project tag in Expensify. Journal entries are then posted into SAP's general ledger with the expense amounts, cost center, and GL account. Cost center and GL account reference data flows bi-directionally to keep Expensify policies and cost tags aligned with the current SAP chart of accounts. Expense reports are read-only in Expensify, so ml-connector does not write updates back into Expensify.

How ml-connector handles it

ml-connector retrieves Expensify API credentials (partnerUserID and partnerUserSecret) and SAP OAuth 2.0 credentials (client ID, client secret, and the customer's tenant-specific token endpoint URL) and stores them encrypted. On each scheduled run, ml-connector polls Expensify for approved reports within the date range using the API key credentials, extracts individual expenses and their policy or cost tags, then looks up the matching GL account and cost center in SAP using OData queries. It validates that each GL account and cost center exist in SAP before posting, so invalid mappings are caught and reported rather than creating orphan journal entries. ml-connector then posts a journal entry for each report to SAP's general ledger using the GL account and cost center dimensions. SAP OAuth tokens are short-lived (typically 12 hours), so ml-connector caches tokens and refreshes them before expiry to avoid authorization failures mid-run. Every expense, approval, and GL posting is logged in the audit trail and can be replayed if a downstream SAP call fails. Because Expensify has no webhooks, polling is scheduled to run before your month-end close window.

A real-world example

A mid-sized professional services firm uses SAP S/4HANA for accounting and project cost tracking, and Expensify for employee travel and out-of-pocket reimbursement. Before the integration, the finance team exported approved reports from Expensify weekly, categorized each expense to the correct SAP cost center and GL account by reading the employee's project assignment, and manually keyed journal entries into SAP. Month-end close required a reconciliation pass to ensure that all Expensify reports had been posted and that the total expense GL account matched the weekly entries. With SAP S/4HANA and Expensify connected, each approved report automatically posts to SAP's general ledger, allocated to the correct cost center and GL account based on the employee and project tag. The finance team no longer re-keys expenses, and month-end close starts with the expense accounts already reconciled and audited.

What you can do

  • Post approved Expensify expense reports to SAP S/4HANA's general ledger, allocated to the correct cost center and GL account.
  • Map Expensify employee departments and project tags to SAP cost centers and GL accounts for automated allocation.
  • Validate GL accounts and cost centers in SAP before posting to prevent orphan journal entries.
  • Authenticate Expensify with API keys and SAP S/4HANA with OAuth 2.0 using tenant-specific token endpoints.
  • Run on a schedule before your month-end close window, with full audit trails and replay capability on every report.

Questions

How does ml-connector know which GL account and cost center to use for each Expensify expense?
ml-connector uses the expense report's employee and policy or cost tag from Expensify to look up the matching cost center in SAP. The policy or tag is configured to map to a specific GL account and cost center pair. Before posting, ml-connector queries SAP to validate that both the GL account and cost center exist; if either is missing, the report is flagged for review.
Can ml-connector sync cost centers and GL accounts from SAP back into Expensify to keep policies in sync?
Yes. ml-connector reads the current cost center and GL account master data from SAP via OData queries and uses that to validate or update the cost tags configured in Expensify policies. This keeps the two systems aligned so that new cost centers or GL account changes in SAP flow through to the expense policies.
What happens if an Expensify report fails to post into SAP?
ml-connector logs the failure with the report ID, GL account, and cost center in the audit trail. The report remains unposted and does not block other reports. When the underlying issue is fixed (for example, a missing cost center is added to SAP), you can replay the failed report from the audit history to post it retroactively.

Related integrations

Connect SAP S/4HANA and Expensify

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

Get started