ml-connector
Sage X3ServiceTitan

Sage X3 and ServiceTitan integration

Service contractors use ServiceTitan to manage field jobs, dispatch, and invoicing, while Sage X3 holds their GL accounts, suppliers, and inventory costs. Connecting the two keeps your job costs, inventory receipts, and supplier invoices in sync between field and finance. Field jobs flow into Sage X3 as GL postings by cost code, and inventory bills from ServiceTitan update your purchase order history and supplier accounts in Sage X3 without manual re-entry. ml-connector bridges the very different authentication models and data formats on each side.

How Sage X3 works

Sage X3 is an on-premise and cloud ERP that exposes suppliers, purchase orders, products, GL accounts, and GL entries through REST (api1) and GraphQL (Xtrem) APIs. Sage X3 authenticate with OAuth2 client credentials for GraphQL or HTTP Basic Authentication for the legacy REST api1 path, and requires a customer-specific server URL, port, and folder name since there is no central tenant registry. Access tokens expire in 5 minutes, and refresh tokens are valid for 30 days. Sage X3 does not support outbound webhooks, so changes are detected by polling with updatedDate and modifiedDateTime fields on records.

How ServiceTitan works

ServiceTitan is a cloud field-service-management platform that exposes customers, jobs, appointments, invoices, payments, inventory bills, purchase orders, and vendors through REST APIs. ServiceTitan authenticates with OAuth2 client-credentials grant, requires an App Key sent as a header on every request, and requires the Tenant ID in the URL path. Tokens are valid for 900 seconds. ServiceTitan supports outbound webhooks with HMAC-SHA256 signature verification for events like job.created, invoice.updated, and appointment.scheduled. AP Bills (inventory bills) are read-only and generated automatically when a purchase order is marked received.

What moves between them

The main flow runs from ServiceTitan into Sage X3. Field jobs and appointments created in ServiceTitan push via webhook to ml-connector, which maps job types and labor cost to Sage X3 GL accounts and cost codes, then posts the labor entry into Sage X3 general ledger on the next poll cycle. Inventory bills from ServiceTitan (generated when a purchase order is marked received) are synced into Sage X3 as unmatched invoice lines against the corresponding supplier and purchase order. Vendor and inventory master data is aligned in both directions so job materials and labor allocate to valid Sage X3 accounts.

How ml-connector handles it

ml-connector receives ServiceTitan webhooks with HMAC-SHA256 signatures and verifies each one against the shared webhook secret before processing. It stores ServiceTitan OAuth2 credentials encrypted and refreshes the bearer token when a call returns 401; it also presents the required ST-App-Key header on every ServiceTitan request. On the Sage X3 side, it accepts the customer-specific server URL, port, and folder name, uses either OAuth2 or HTTP Basic Auth as configured, and handles the 5-minute access token expiry by refreshing proactively rather than waiting for a 401. Job GL postings are mapped first to validate that the target GL account and cost center exist in Sage X3 before posting. Because ServiceTitan AP Bills are read-only, ml-connector never writes back to ServiceTitan invoicing; it reads bills and maps them to purchase orders in Sage X3 for matching and reconciliation. Every record carries a full audit trail and can be replayed if a downstream Sage X3 call fails.

A real-world example

A regional electrical contractor with a head office and five service branches runs ServiceTitan for dispatch and field invoicing and Sage X3 on-premise for finance, procurement, and inventory. Before the integration, the back-office team received ServiceTitan job summaries by email each week, manually tallied labor and materials by cost center, and re-entered them into Sage X3 GL alongside supplier invoices. Month-end close required cross-referencing job tickets against GL postings, and discrepancies meant rework. With ServiceTitan and Sage X3 connected, each job that completes in the field pushes a GL entry directly into Sage X3, and inventory bills from ServiceTitan are linked to the matching purchase orders so the finance team spends month-end on reconciliation instead of re-entry.

What you can do

  • Post field job labor and material costs from ServiceTitan into Sage X3 general ledger by cost center, mapped to the correct GL accounts.
  • Sync ServiceTitan inventory bills (purchase order receipts) into Sage X3 as unmatched invoice lines for supplier matching and reconciliation.
  • Authenticate ServiceTitan with OAuth2 and the required App Key header, and Sage X3 with OAuth2 or HTTP Basic Auth depending on your deployment.
  • Receive job and appointment updates from ServiceTitan via webhook push with HMAC-SHA256 verification, and poll Sage X3 on a schedule to post cost entries.
  • Maintain a full audit trail on every record and replay failed GL postings without re-posting duplicates.

Questions

Which direction does data move between Sage X3 and ServiceTitan?
The main flow is ServiceTitan into Sage X3. Job costs, materials, and inventory bills move from ServiceTitan into Sage X3 general ledger and purchase order history. Master data such as vendors, cost centers, and GL accounts are aligned in both directions. ServiceTitan does not accept GL postings back, so ml-connector reads only from ServiceTitan invoicing and bills.
How does ml-connector handle Sage X3's different server URLs and token expiry?
ml-connector accepts the full server URL, port, and X3 folder name per customer, since Sage X3 does not publish a central tenant registry. It refreshes access tokens proactively before the 5-minute expiry rather than waiting for a 401, avoiding authentication gaps during high-volume job posting. For on-premise Sage X3, HTTP Basic Auth is configured during customer setup; for cloud Sage X3, OAuth2 is used.
What happens to ServiceTitan inventory bills that have already been posted to Sage X3?
ml-connector tracks posted bills by external ID and does not re-post them. If a bill is corrected or voided in ServiceTitan, the change is detected on the next poll and the audit log shows the correction. Sage X3 reconciliation tools can match the updated bill line to the purchase order and supplier invoice as usual.

Related integrations

Connect Sage X3 and ServiceTitan

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

Get started