ml-connector
Sage X3Gusto

Sage X3 and Gusto integration

Sage X3 runs finance and manufacturing for mid-market companies. Gusto runs payroll and HR. Connecting the two keeps your workforce records aligned and posts every payroll run's labor costs directly into X3's general ledger, allocated to the cost centers where work happened. New hires and terminations in Gusto flow into X3's employee records, and the GL journals that Gusto calculates after each payroll run post into X3 without re-keying. ml-connector bridges the very different APIs on each side and synchronizes the data on a schedule you control.

How Sage X3 works

Sage X3 is an on-premise and cloud ERP exposing suppliers, customers, purchase orders, sales invoices, products, GL accounts, and GL entries through REST (api1 and GraphQL Xtrem) APIs. The cloud product authenticates with OAuth2 client credentials (JWT bearer) via Connected Application for GraphQL, or HTTP Basic Authentication for the legacy REST api1 path. Sage X3 has no native webhook system for cloud connectors, so records are read by polling with delta detection using the updatedDate and modifiedDateTime fields. Access tokens expire in 5 minutes, and Sage X3 is available in on-premise and cloud-hosted deployments with customer-specific server URLs and port numbers.

How Gusto works

Gusto exposes employees, jobs, compensations, payrolls, contractors, locations, bank accounts, and company benefits through a REST API at https://api.gusto.com with all endpoints prefixed /v1/. Every call requires OAuth2 Authorization Code flow (3-legged) with tokens scoped to a single company; access tokens expire in 2 hours and refresh tokens never expire but rotate on refresh. Gusto can push payroll events (created, updated, processed, paid) and employee events (created, updated, terminated) to a registered webhook endpoint, which must return 2xx within 10 seconds and handles retries up to 16 times over 3 days. Gusto enforces 200 requests per minute per OAuth grant with a rolling window.

What moves between them

The main flow is Gusto into Sage X3. After each payroll run, ml-connector reads Gusto's payroll records and posts the corresponding labor cost journals into X3's general ledger, mapped to the matching X3 GL accounts and cost centers. Employee records flow the same direction so X3 headcount reflects Gusto hires, terminations, and rehires. Pay schedules and earning types are aligned so payroll allocations land on valid X3 dimensions. GL postings are read-only in Gusto, so ml-connector never writes financial entries back to Gusto. The sync runs on a cadence tied to your payroll calendar, typically after each pay period close.

How ml-connector handles it

ml-connector stores both credential sets encrypted and manages Gusto's OAuth2 token refresh cycle independently for each company, since each Gusto token is scoped to a single company only. For Sage X3, it accepts the customer-specific server URL and port, refreshes the JWT bearer token every 5 minutes before expiry, and uses delta polling with the updatedDate field to detect changes since the last sync. Cost centers in X3 are mapped to Gusto's locations and earning types first, so every payroll journal line references a GL account and cost center that already exists in X3. Gusto's 200-request-per-minute rate limit is observed and backed off on 429 responses. For on-premise Sage X3 deployments, ml-connector handles the longer token refresh cycle and validates entity paths against the customer's specific X3 instance. Every record carries a full audit trail and can be replayed if a downstream GL posting fails, with the full sync history stored for troubleshooting.

A real-world example

A mid-sized logistics and services company runs Sage X3 on-premise for finance, procurement, and operations across three regional warehouses, and uses Gusto for payroll and benefits administration for 150+ employees. Before the integration, the accounting team exported payroll registers from Gusto every two weeks and manually entered labor totals into X3 by hand, allocating costs across warehouse locations and job codes. Month-end close required chasing discrepancies between X3 headcount and payroll records, and employee changes (hires, terminations) had to be manually entered into both systems. With Sage X3 and Gusto connected, each payroll run's GL entries flow automatically into X3, allocated to the correct warehouse cost centers and GL accounts, employee records stay in sync, and the month-end reconciliation starts with the labor accounts already verified and balanced.

What you can do

  • Post Gusto payroll GL journals into Sage X3's general ledger after every pay run, allocated to the correct cost centers and warehouse locations.
  • Keep Sage X3 employee records aligned with Gusto hires, terminations, and rehires in real time.
  • Map Gusto locations and earning types to Sage X3 GL accounts and cost centers so payroll lands on valid X3 dimensions.
  • Manage OAuth2 token refresh for Gusto (per-company scope) and JWT bearer token rotation for Sage X3 (5-minute expiry), with full state tracking.
  • Poll Gusto and Sage X3 on a schedule tied to your payroll calendar, with cost center reconciliation, retries, and a complete audit trail on every record.

Questions

Which direction does data move between Sage X3 and Gusto?
The main flow is Gusto into Sage X3. Payroll GL journals and employee records move from Gusto into X3, while cost centers and GL accounts are aligned so Gusto earnings post to the correct X3 dimensions. Gusto's GL records are read-only, so ml-connector does not write financial entries back to Gusto. Reference data like locations and earning types is mapped first to ensure valid X3 destinations.
How does ml-connector handle the different token expiry cycles between Gusto and Sage X3?
Gusto access tokens expire in 2 hours and are refreshed automatically using the non-expiring refresh token, which rotates on each refresh. Sage X3 JWT tokens expire in 5 minutes and are refreshed before expiry. ml-connector manages both cycles independently, caching X3 tokens to minimize refresh calls, and stores all credentials encrypted with a master key per customer.
How does the integration work if Sage X3 is deployed on-premise?
ml-connector accepts the customer-specific server URL and port for on-premise X3 deployments, since Sage X3 publishes no shared base address. The sync runs on a schedule tied to your payroll calendar, polling both systems for changes with delta detection using updatedDate fields. On-premise deployments may have lower rate limits constrained by server capacity, so ml-connector respects and backs off on HTTP 429 responses.

Related integrations

Connect Sage X3 and Gusto

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

Get started