Skip to main content
The ServiceTitan source uses the v2 REST APIs and is alpha. It covers 48 resources. Shared pagination, projection, and checkpoint behavior have regression coverage. Live tenant reads have not been validated. The source is backed by an HTTP manifest. Use servicetitan@v2 to select API v2; servicetitan resolves to this default version.

Configuration

Create an application with read permissions for the resources you select and connect it to the tenant. Credentials and app access must match the environment. Filament obtains and renews a client-credentials access token and sends the application key in ST-App-Key. Connection testing reads the first jobs export page; it does not establish access to every API family. See the official API documentation.

Resources

Select the resources your application can access. Other ServiceTitan resources, including reporting, forms, equipment systems, and newer export feeds, are outside the current resource set.

Modes

All resources support full reads. Incremental reads are available for 42: 40 export resources use ServiceTitan’s opaque continueFrom token; non_job_timesheets and payrolls use modifiedOnOrAfter with a fixed lower bound throughout pagination and sort=+ModifiedOn. These six resources support full reads only: job_types, campaigns, campaign_costs, campaign_categories, technician_shifts, and membership_status_changes. Use incremental upsert for mutable export records. No cursor-column selection or lookback is supported for export tokens. The first incremental run walks the complete export. A preceding full run does not seed its incremental token. Subsequent successful runs resume at the saved token. Append writes can retain replayed records after failures; they do not produce a deduplicated current view. gross_pay_items uses the gross pay item id as its primary key and saves the export’s continueFrom token for incremental reads. payrollId identifies the parent payroll and must not be used to deduplicate its earnings items. ServiceTitan permits null item IDs; keyed writes reject such records without advancing the run’s checkpoint. Use full read with replace for accounts containing items without IDs. See the official payroll schema. For existing pipelines, select incremental read and upsert write explicitly. The first incremental run establishes the export checkpoint with a complete read. Changing the key does not repair rows already overwritten by payroll-level upserts or remove duplicate rows left by previous append runs; rebuild affected destination data from a complete export before relying on incremental updates. Use full replace for technician_shifts. Technician shifts can be hard-deleted upstream, requiring replacement to remove missing rows. Ordinary export upserts do not infer deletes from records absent in a delta.

Behavior

Export requests set includeRecentChanges=false, accepting ServiceTitan’s approximately 15-minute export visibility delay. Each page uses hasMore and continueFrom, including empty pages. The terminal token is delivered separately from rows and becomes durable only after successful run commit. Failed runs replay from the prior committed token. Missing or malformed envelopes and cursor cycles fail the run. Invalid saved tokens are not silently discarded. job_types, campaigns, and technician_shifts request active=Any on every page. Transactional full reads use 5,000-row pages; the two timestamp streams use 1,000-row pages. includeTotal=true is sent on each transactional page. Exports do not send pageSize. Requests share a 45-per-second limiter across all resource readers in a run, with a burst of one. There is one reader per selected resource (up to 48); adding readers does not multiply the request budget. Separate runs and pipelines have independent limiters. Requests use the HTTP engine’s retry handling for throttling and server errors. Nested arrays and objects stay JSON. Date/time values remain strings, preserving seven-digit fractional seconds. Integer IDs use 64-bit integers, and decimal values travel as text to preserve digits. The trailing raw column retains unprojected properties. job_history keeps one row per jobId, its complete history array, and nullable lastEventDate, the lexical maximum nonempty event date. Export upserts use Filament’s insertion-order version policy. If an export returns an older version after a newer version, the older record can replace the newer destination row. Rows are not ordered by modifiedOn or lastEventDate. Begin with a fresh backfill and keep separate tenants in separate destination tables or namespaces.