ml-connector
XeroServiceTitan

Xero and ServiceTitan integration

Xero runs accounting for service contractors. ServiceTitan runs the jobs, scheduling, and invoicing on the field. Connecting them keeps your accounts receivable in sync with your service invoices and your purchase records aligned between the two systems. New service jobs and invoices in ServiceTitan flow into Xero without re-keying, and vendor and customer master data stays consistent across both platforms. ml-connector handles the OAuth2 credentials, rate limits, and webhooks on each side.

How Xero works

Xero is a cloud accounting platform accessed through its REST Accounting API at https://api.xero.com/api.xro/2.0/. All API requests require an OAuth2 bearer token (valid 30 minutes, refresh every 60 days with offline_access scope) and a Xero-tenant-id header to target the specific organization. Xero exposes Invoices, Purchase Orders, Payments, Accounts, Contacts, Tracking Categories, Manual Journals, and Bank Transactions. The API is rate-limited to 5 concurrent calls and 60 per minute per tenant. Xero offers webhooks for Invoice, Payment, Contact, Purchase Order, Manual Journal, and Credit Note events, but webhook payloads contain metadata only and require a follow-up GET to fetch the full record. For polling, Xero supports the If-Modified-Since header for delta sync. Pagination is page-based at 100 records per page.

How ServiceTitan works

ServiceTitan is a field-service management platform accessed through its REST API at https://api.servicetitan.io/{namespace}/v2/tenant/{tenantId}/ (production) or the integration sandbox. Authentication uses OAuth2 client credentials with a 15-minute token lifetime (900 seconds); every API call must include the ST-App-Key header, the Tenant ID in the URL path, and the OAuth2 bearer token. ServiceTitan exposes Invoices, Payments, Purchase Orders, Inventory Bills, Customers, Vendors, Items, Jobs, Appointments, and Employees. The API is rate-limited to 60 calls per second per app per tenant, with 100-second request timeouts. ServiceTitan offers V2 webhooks with HMAC-SHA256 signature verification and event types including invoice.created, invoice.updated, payment.created, customer.created, and appointment.updated. Inventory bills are read-only and generated automatically from purchase orders marked received. GL accounts are not exposed through the API.

What moves between them

Invoices and payments flow from ServiceTitan into Xero's Accounts Receivable. When a job is completed and invoiced in ServiceTitan, ml-connector reads the invoice and payment records from ServiceTitan and posts them as Invoices and Payments in Xero, mapped to the correct Xero account and using the customer from the ServiceTitan job. Outbound, purchase orders created in ServiceTitan flow into Xero as Purchase Orders so procurement stays synchronized. Customer master data (names, contact details) is synced bidirectionally so both systems share the single source of truth for who the customer is. ServiceTitan generates inventory bills automatically when a purchase order is marked received; these are read-only in the API and do not sync back to Xero, but ml-connector can track them for audit and reconciliation purposes.

How ml-connector handles it

ml-connector stores the OAuth2 credentials for Xero and ServiceTitan encrypted per customer and manages token refresh automatically: Xero tokens expire in 30 minutes and refresh tokens valid 60 days, while ServiceTitan tokens expire in 15 minutes. It listens for ServiceTitan webhook push events (invoice.created, invoice.updated, payment.created, customer.created) to trigger near-real-time syncs into Xero, and it polls Xero on a regular schedule using the If-Modified-Since header to detect changes made outside ServiceTitan. Because Xero enforces 5 concurrent calls and 60 per minute per tenant, ml-connector queues Xero API calls and respects those limits, backing off if it hits the rate limit. On the ServiceTitan side, the ST-App-Key header is sent with every request and the Tenant ID is verified on each call. ServiceTitan's inventory bills are read-only, so ml-connector does not attempt to update or create them; instead, it reads them to track procurement. Customers and vendors are matched by name or external ID to avoid creating duplicates. Every record carries timestamps and change tracking for full audit and replay on failure.

A real-world example

A mid-sized HVAC contractor runs ServiceTitan to manage job dispatch, technician scheduling, and on-site invoicing across three service territories. The accounting team uses Xero for accounts receivable, accounts payable, and general ledger. Before the integration, each day an accounting clerk logged into ServiceTitan, exported the previous day's completed invoices and payments, then manually re-entered them into Xero's invoice and payment modules, spending 30 to 45 minutes per day on re-keying. They also maintained a separate vendor master list for equipment suppliers, creating duplication and reconciliation errors. With ServiceTitan and Xero connected, completed invoices and payment records sync automatically to Xero the same day they are created in the field, and vendors are synced once so purchase order data is current in both systems. The accounting team now spends 5 minutes per day reviewing the sync log instead of 45 minutes re-keying, and month-end close starts with Accounts Receivable and Accounts Payable already reconciled.

What you can do

  • Sync completed service invoices and customer payments from ServiceTitan into Xero's Accounts Receivable, mapped to the correct GL account and customer.
  • Push purchase orders created in ServiceTitan into Xero as Purchase Orders so procurement data stays in sync.
  • Keep customer and vendor master data consistent across both systems using name matching or external ID to prevent duplicates.
  • Respect Xero's rate limits (5 concurrent calls, 60 per minute) and ServiceTitan's rate limits (60 calls per second) with automatic queuing and backoff.
  • Listen for ServiceTitan webhook events for near-real-time sync while polling Xero on a schedule for delta updates, with full audit trail and replay on failure.

Questions

What data moves between Xero and ServiceTitan?
Invoices and payments flow from ServiceTitan into Xero's Accounts Receivable. Purchase orders flow from ServiceTitan into Xero's Accounts Payable. Customer and vendor master data (names, addresses, contact information) sync bidirectionally. ServiceTitan inventory bills are read-only in the API and are tracked for audit purposes but not posted back to Xero.
How does ml-connector handle the different rate limits and token timeouts?
ml-connector caches OAuth2 tokens after fetching them and refreshes them before expiry: Xero tokens last 30 minutes and refresh tokens are good for 60 days, while ServiceTitan tokens expire in 15 minutes. It queues API calls to Xero to respect the 5-concurrent-call limit and 60-per-minute throttle, and it respects ServiceTitan's 60-per-second rate limit. When rate limits are hit, ml-connector backs off and retries automatically.
Why does ServiceTitan's inventory bill data not sync back to Xero?
ServiceTitan generates inventory bills automatically when a purchase order is marked received, and the API exposes these bills as read-only. Since Xero expects bills to be created by external vendors, ml-connector tracks inventory bills for reconciliation and audit but does not attempt to post them back to Xero. Purchase orders that generate bills are tracked with full timing and status for visibility.

Related integrations

Connect Xero and ServiceTitan

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

Get started