ml-connector
IFS CloudExpensify

IFS Cloud and Expensify integration

IFS Cloud runs your enterprise finance and operations. Expensify tracks employee expenses and corporate card spending. Connecting the two keeps your general ledger current with approved employee spending and eliminates manual re-entry of expense accruals. After each expense report approval in Expensify, ml-connector reads the transactions, maps them to your IFS Cloud GL accounts and cost centers, and posts the accrual journal automatically. Your finance team gains visibility into real-time corporate spending without re-keying.

How IFS Cloud works

IFS Cloud exposes GL accounts, cost centers, accounting dimensions, supplier invoices, purchase orders, and journal entries through OData v4 REST API with a tenant-specific base URL. Authentication uses OAuth2 client credentials with a 60-minute token lifetime against a per-tenant auth realm. IFS Cloud offers no standard webhook subscription API; manual Event Actions can be configured in the IFS admin UI to POST on business events, but this requires per-customer setup and is not API-driven. Integration typically uses pull-based polling on OData with filters on modified timestamps. Rate limiting is approximately 1000 requests per minute per tenant, and page size is recommended to stay under 5000 elements to avoid 500 errors. Mutation operations require ETag headers for optimistic concurrency control.

How Expensify works

Expensify is a cloud expense management platform that exports approved expense reports, individual transactions, employee data, and corporate card feeds via REST polling API only. Authentication uses a static API key pair (partnerUserID and partnerUserSecret) passed inline with every request. Expensify has no webhooks or push notification endpoints; all data retrieval is via scheduled polling requests with date-range or status filters. The platform runs against production only with no sandbox environment. GL account codes are attached to expense categories within a policy, and custom tags function as accounting dimensions for project, class, or cost center allocation. Vendor names appear as free-text merchant fields on individual expenses rather than as a structured master. Employee state is returned in diff responses after update, not via a direct read endpoint.

What moves between them

The main data flow is from Expensify into IFS Cloud. After an expense report is approved in Expensify, ml-connector polls the export API for new reports on a schedule you define, reads the line-item transactions and assigned cost center tags, and posts an accrual journal entry into IFS Cloud's general ledger. Each line is mapped to the corresponding IFS Cloud GL account (derived from the expense category) and cost center dimension (from the Expensify tag). Reference data such as cost centers and GL accounts are validated against IFS Cloud before posting to prevent orphaned entries. Employee expense data flows one direction only; ml-connector does not write back to Expensify.

How ml-connector handles it

ml-connector stores both the Expensify API key pair and IFS Cloud OAuth2 client credentials encrypted and refreshes the IFS Cloud bearer token before it expires (typically 50 minutes into the 60-minute lifetime) to avoid token timeout errors during long-running flows. Expensify does not support request signatures or webhook verification; security relies on the API key being treated as a secret and all calls being encrypted over HTTPS. On the IFS Cloud side, all mutations require ETag headers for optimistic concurrency control, so ml-connector reads the full journal entry template first, captures the ETag, and includes it in the POST to the journal endpoint. Cost centers and GL accounts are validated from IFS Cloud's CodePartValueSet before posting to ensure they exist and are active; if validation fails, the journal entry is queued for replay after the missing dimension is created. Because Expensify polling has no retries or acknowledgment mechanism, ml-connector tracks processed report IDs locally to avoid duplicate posts. Rate limiting on both sides is handled with exponential backoff and jitter: IFS Cloud returns HTTP 429 when the 1000-requests-per-minute limit is approached, and Expensify requests that fail are backed off and retried. Every journal entry and the approval workflow that triggered it carries a full audit trail in ml-connector, so a failed post can be reviewed and replayed without losing history.

A real-world example

A mid-sized professional services firm uses IFS Cloud for project accounting and finance, and Expensify for employee expense tracking and corporate card reconciliation across 150 employees. Before the integration, the accounting team exported Expensify reports weekly, coded each expense line to the correct project and cost center, and manually entered accrual journals into IFS Cloud. Month-end close required three days of reconciliation between Expensify spending and the posted accruals. With IFS Cloud and Expensify connected, each approved report automatically posts its accrual into the correct GL account and project dimension, so the general ledger reflects real-time spending. The accounting team eliminates the manual re-entry step and starts month-end close with the expense accounts already reconciled.

What you can do

  • Export approved expense reports from Expensify on a schedule and post accrual journals into IFS Cloud's general ledger with a single flow.
  • Map Expensify expense categories and cost center tags to IFS Cloud GL accounts and accounting dimensions without manual coding.
  • Validate cost centers and GL accounts against IFS Cloud before posting to prevent orphaned journal entries.
  • Refresh IFS Cloud OAuth2 tokens before expiry and handle Expensify API key rotation without service interruption.
  • Audit every expense transaction from Expensify through posting in IFS Cloud, with full replay capability for failed entries.

Questions

Which direction does data move between IFS Cloud and Expensify?
Data flows one direction: from Expensify into IFS Cloud. Approved expense reports are read from Expensify and posted as accrual journals into IFS Cloud's general ledger, mapped to the correct GL accounts and cost centers. IFS Cloud is the system of record for finance; ml-connector does not write back to Expensify.
How does ml-connector handle IFS Cloud's ETag requirement for journal posting?
IFS Cloud requires an ETag header for mutation operations to enforce optimistic concurrency control. ml-connector reads the full journal entry template from IFS Cloud first, captures the ETag from the response, and includes it in the POST request to create the new journal entry. This ensures the entry is not lost if IFS Cloud has modified the template between the read and the write.
What happens if a cost center or GL account in Expensify does not exist in IFS Cloud?
ml-connector validates all cost centers and GL accounts against IFS Cloud's CodePartValueSet before posting the journal entry. If a dimension is missing, the entry is queued for replay after the dimension is created in IFS Cloud, ensuring no orphaned or invalid entries are posted to the ledger.

Related integrations

Connect IFS Cloud and Expensify

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

Get started