ml-connector
Sage IntacctRamp

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.

How Sage Intacct works

Sage Intacct is a cloud-based ERP that exposes vendors, AP bills, GL accounts, and cost dimensions through a single XML gateway endpoint at https://api.intacct.com/ia/xml/xmlgw.phtml. Authentication is session-based: an initial getAPISession call exchanges partner credentials and user credentials for a sessionid, which is cached for 50 minutes and automatically refreshed on the next call. HTTP 200 responses may contain application-level errors inside the XML body, so responses must be parsed for errormessage tags. Intacct has no webhook system; all data flows are pull-only, driven by scheduler or manual run. Forbidden XML control characters must be stripped before escaping entity references. Retried operations rely on a uniqueid flag in the control block for server-side deduplication.

How Ramp works

Ramp is a REST API for corporate spend management at https://api.ramp.com/developer/v1. It exposes bills, vendors, purchase orders, transactions, GL accounts, accounting dimensions, and reimbursements. Authentication uses OAuth 2.0 Client Credentials flow, with access tokens valid 10 days, recommended for ERP connectors. Ramp supports push webhooks for real-time event notifications including bills (created, updated, paid, archived), transactions (cleared, synced), vendors (updated), and reimbursements (batch_payment_reimbursed), with signature verification via HMAC-SHA256. Vendors cannot be created directly via API; they are created implicitly when a bill is created. Purchase orders are read-only and cannot be patched for line items. Payments are initiated by bill creation or update, not through a standalone payment endpoint.

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

Connect Sage Intacct and Ramp

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

Get started