ml-connector
QADServiceTitan

QAD and ServiceTitan integration

QAD runs manufacturing and finance as the system of record. ServiceTitan runs field service operations for home and commercial trades. Connecting the two moves the revenue and cost that ServiceTitan generates in the field into QAD's general ledger without re-keying. Job invoices and payments recorded in ServiceTitan post into QAD as customer receivables and cash, while inventory bills from received purchase orders flow into QAD accounts payable. ml-connector handles the different APIs on each side and moves the data on a schedule you control.

How QAD works

QAD Adaptive ERP exposes suppliers, customers, purchase orders, supplier invoices, AP payments, GL accounts, cost centers, items, and goods receipts through REST business document APIs, documented in Swagger inside each customer instance. The cloud product authenticates with a JWT session or OAuth2 bearer token against a tenant-specific URL, so there is no shared hostname. Older on-premise sites run QAD Enterprise Edition with the QXtend SOAP framework instead. QAD supplier invoices use a three-way match, so goods receipts must post before the matching AP invoice. QAD has no public webhook system for cloud connectors, so finance records are read by polling.

How ServiceTitan works

ServiceTitan exposes invoices, payments, inventory bills, purchase orders, vendors, customers, and business units through its V2 REST API, organized into namespaces such as accounting, inventory, crm, and settings. Every call uses an OAuth2 client-credentials bearer token plus an ST-App-Key header, with the tenant ID embedded in the URL path and the token valid for 15 minutes. Invoices, payments, and customers are readable and writable; inventory bills (AP) are read-only and generated when a purchase order is received; there is no GL chart-of-accounts endpoint. ServiceTitan can also push V2 webhooks for events such as invoice.created and payment.created, signed with HMAC-SHA256.

What moves between them

The main flow runs from ServiceTitan into QAD. ml-connector reads ServiceTitan invoices and payments and posts them into QAD as customer receivables and cash applications, and reads ServiceTitan inventory bills and posts them into QAD as supplier invoices. Customer and vendor records are aligned in both directions so both systems share the same masters. ServiceTitan business units, which serve as its cost-center dimension, map to QAD cost centers so every posting carries a valid GL dimension. ServiceTitan inventory bills are read-only and derived from received purchase orders, so ml-connector never writes AP entries back into ServiceTitan.

How ml-connector handles it

ml-connector stores both credential sets encrypted. For ServiceTitan it requests a client-credentials token, caches it for its 15-minute lifetime, and sends it with the ST-App-Key header and the tenant ID in the URL path on every call. For QAD it accepts the full tenant URL per customer, since QAD publishes no shared base URL, and validates entity paths against that instance. ServiceTitan can push V2 webhooks for invoice and payment events, verified by recomputing the HMAC-SHA256 signature over the raw body; where webhooks are not enabled, ml-connector polls the accounting endpoints on a schedule using offset pagination. Because QAD finance is pull-only, all reads of QAD reference data are polled. Business units are mapped to QAD cost centers first, and customers and vendors are reconciled, so every invoice, payment, and AP bill references masters and dimensions that already exist in QAD. Inventory bills only appear after a purchase order is received, so ml-connector keys AP postings off that derived record. ServiceTitan caps requests at 60 per second per tenant and enforces a 100-second server timeout, so ml-connector throttles within those limits and retries with backoff. ServiceTitan does not provide an idempotency key, so on writes ml-connector queries for an existing record before creating one. Every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A regional HVAC and plumbing contractor with about 200 field technicians runs ServiceTitan for dispatch, job invoicing, payments, and parts purchasing, while the parent group standardizes finance on QAD Adaptive ERP. Before the integration, the accounting team exported invoice and payment registers from ServiceTitan each week and re-keyed the totals into QAD, then matched parts bills from received purchase orders by hand, which delayed close and left receivables out of step between the two systems. With QAD and ServiceTitan connected, each invoice and payment flows into QAD against the matching cost center as it posts, inventory bills land in QAD accounts payable once their purchase orders are received, and customers and vendors stay aligned. Month-end close starts with revenue, cash, and parts cost already reconciled, and the manual re-keying step is gone.

What you can do

  • Post ServiceTitan invoices and payments into QAD as customer receivables and cash applications.
  • Pull ServiceTitan inventory bills from received purchase orders into QAD accounts payable.
  • Keep customers and vendors aligned across QAD and ServiceTitan so both systems share the same masters.
  • Map ServiceTitan business units to QAD cost centers so every posting carries a valid GL dimension.
  • Authenticate ServiceTitan with OAuth2 client credentials and the ST-App-Key header, and QAD with its tenant-specific token, with retries and a full audit trail.

Questions

Which direction does data move between QAD and ServiceTitan?
The main flow is ServiceTitan into QAD. Invoices, payments, and inventory bills move from ServiceTitan into QAD as receivables, cash, and accounts payable, while customers and vendors are aligned in both directions. ServiceTitan inventory bills are read-only and generated from received purchase orders, so ml-connector does not write AP entries back into ServiceTitan.
How does the integration handle ServiceTitan authentication and rate limits?
ServiceTitan uses an OAuth2 client-credentials token that is valid for 15 minutes plus an ST-App-Key header on every call, with the tenant ID in the URL path. ml-connector caches the token for its full lifetime rather than requesting one per call, and it stays within the 60-calls-per-second-per-tenant limit and the 100-second timeout, backing off and retrying when needed.
What happens with GL accounts, since ServiceTitan does not expose them?
ServiceTitan has no chart-of-accounts endpoint, so GL detail lives in QAD. ml-connector maps ServiceTitan business units, which act as its cost-center dimension, to QAD cost centers and GL accounts, so each invoice, payment, and AP bill posts to a valid QAD account. Because ServiceTitan does not provide an idempotency key, ml-connector queries for an existing record before creating one on writes.

Related integrations

Connect QAD and ServiceTitan

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

Get started