Sage Intacct and Ramp integration
Ramp handles corporate spend, Sage Intacct handles accounting. Connecting them closes the gap between when a bill is approved in Ramp and when it posts to the GL. Vendor records stay in sync across both systems, and expense approvals in Ramp flow directly into Intacct without re-entry. ml-connector handles the very different APIs: Intacct's XML gateway with session-based auth and Ramp's REST API with OAuth2 and webhooks.
What moves between them
The main flow is Ramp into Sage Intacct. When bills are created, updated, or paid in Ramp, ml-connector receives a webhook notification, retrieves the full bill details, and writes or updates the corresponding AP bill in Intacct's general ledger, mapped to the GL accounts and cost dimensions configured for each Ramp workspace. Vendor records flow bidirectionally: new vendors in Ramp sync into Intacct, and dimension updates in Intacct (departments, cost centers) sync back to Ramp to ensure bill allocations land on valid accounting dimensions. Archived and rejected bills in Ramp trigger corresponding status updates in Intacct. GL accounts and accounting dimensions are read from both systems and used to validate bill line items before posting.
How ml-connector handles it
ml-connector listens to Ramp's webhooks and validates each signature using HMAC-SHA256. For each bill event, it fetches the full bill from Ramp's REST API using the stored OAuth2 client credentials, with a 10-day access token. On the Intacct side, ml-connector maintains a session via getAPISession, caches the sessionid, and refreshes it automatically every 50 minutes before expiry. The initial session call uses senderId and senderPassword (partner credentials) plus userId and userPassword, all stored encrypted per customer. Bills are written to Intacct as APBILL records, with line items mapped to GLACCOUNT and DIMENSION entities. Because Intacct has no idempotency endpoint, each write carries a uniqueid in the control block to prevent duplicate posting on retry. Errors are parsed from XML response bodies for errormessage tags, not HTTP status codes, since Intacct returns HTTP 200 even on application errors. Forbidden XML control characters are stripped before the request is serialized. Vendor creation in Intacct is only pulled, since Ramp creates vendors implicitly; the integration ensures both systems list the same vendors by querying Ramp's vendor list and comparing against Intacct's VENDOR records. Purchase orders and reimbursements flow read-only from Ramp into Intacct for reference and matching.
A real-world example
A mid-market B2B services company uses Ramp for corporate spend and Sage Intacct for accounting. Finance teams were spending hours each week exporting approved bills from Ramp, manually entering them into Intacct, and reconciling GL postings against the Ramp export. Accounting month-end required all bills to be entered before close could begin, holding up the finance calendar. With Sage Intacct and Ramp connected, bills flow from Ramp to Intacct automatically as they are approved or paid, already mapped to cost centers and GL accounts. Vendors in Ramp sync into Intacct, so bill lines always land on valid vendor records. Month-end close now starts with the AP ledger already up to date, and the team gains two days per month.
What you can do
- Receive Ramp bill webhooks in real-time and post approved bills into Sage Intacct's AP ledger with correct GL account and dimension mapping.
- Keep vendor records in sync across Ramp and Sage Intacct so both systems list the same suppliers.
- Map Ramp bill allocations to Sage Intacct GL accounts and cost dimensions, validating that every line item references an existing account.
- Authenticate Ramp with OAuth2 client credentials and Sage Intacct with session-based XML gateway credentials, auto-refreshing sessions before expiry.
- Parse Intacct XML response bodies for application errors, deduplicate writes using control block uniqueid, and strip forbidden XML control characters before serialization.
Questions
- Which direction does data move between Sage Intacct and Ramp?
- The main flow is Ramp into Sage Intacct. Bills, vendors, and transactions created or updated in Ramp post into Intacct's AP ledger. Vendors and dimensions flow bidirectionally so both systems stay in sync and bill allocations always land on valid accounts. Purchase orders and reimbursements are read-only from Ramp.
- How does the integration handle Sage Intacct's session-based authentication and 50-minute session timeout?
- ml-connector calls getAPISession once, caches the sessionid in-process, and automatically refreshes it after 49 minutes before expiry. Each subsequent operation reuses the cached session. If a call happens near the 50-minute boundary, a fresh session is obtained transparently. This eliminates session-timeout errors in production.
- Why does Sage Intacct return HTTP 200 even on application errors, and how does ml-connector handle that?
- Intacct's XML gateway returns HTTP 200 for all responses, with success or error status inside the XML body as errormessage tags. ml-connector parses every response body for those tags and treats errormessage as an application-level error, never assuming HTTP 200 means success. This prevents silent bill failures from being mistaken for successful posts.
Related integrations
More Sage Intacct integrations
Other systems that connect to Ramp
Connect Sage Intacct and Ramp
Free to use. Add your credentials, ping your real systems, and see if we fit.
Get started