@masonlandcattle/servicetitan-sdk
v0.6.0
Published
ServiceTitan API SDK for Node.js with retries, rate limiting, and pagination.
Maintainers
Readme
ServiceTitan SDK (Node.js / TypeScript)
A pragmatic ServiceTitan API client with:
- Robust auth (Client Credentials)
- Retries with exponential backoff + jitter
- Honors Retry-After, handles 429/5xx
- Rate limiting with Bottleneck (concurrency + minTime)
- URL builder and pagination helpers (
getAll) - Modular resources (Jobs, Appointments, Materials, Accounting/Invoices)
Install
npm install @masonlandcattle/servicetitan-sdkConfigure
Set env vars or pass options:
TENANT_IDAPP_KEYCLIENT_IDSECRET_KEY- Optional:
ENVIRONMENT=production|development
Usage (namespaced client)
import { createClient } from "@masonlandcattle/servicetitan-sdk";
const st = createClient({
tenantId: process.env.TENANT_ID!,
appKey: process.env.APP_KEY!,
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.SECRET_KEY!,
environment: (process.env.ENVIRONMENT as any) || "production",
retries: 3,
maxConcurrent: 5,
minTimeMs: 100,
});
// List jobs (single page)
const page = await st.jpm.listJobs({ page: 1, pageSize: 100 });
// List all jobs server-side (aggregates pages)
const allJobs = await st.jpm.listJobs({ status: "Open" }, { all: true, pageSize: 500 });
// Create a job note
await st.jpm.createJobNote(123456, { text: "Hello from SDK", pinToTop: true });
// Materials (with get-all)
const materials = await st.pricebook.listMaterials({}, { all: true, pageSize: 500 });Resources and quick examples
Below is a brief tour of the main resource namespaces. Each list function supports { all?: boolean; pageSize?: number } to fetch all pages server‑side.
Initialize once and reuse:
import { createClient } from "@masonlandcattle/servicetitan-sdk";
const st = createClient({
tenantId: process.env.TENANT_ID!,
appKey: process.env.APP_KEY!,
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.SECRET_KEY!,
});Accounting (st.accounting)
- Invoices, Payments, GL Accounts, Inventory Bills, AP Credits/Payments, Tax Zones, etc.
const invoices = await st.accounting.listInvoices({ customerId: 1234 }, { all: true });
await st.accounting.markInvoicesAsExported([111, 222]);
const gl = await st.accounting.listGlAccounts({ type: "Asset" }, { all: true });CRM (st.crm)
- Customers, Contacts, Locations, Leads, Bookings.
const customers = await st.crm.listCustomers({ search: "Acme" }, { all: true });
const contacts = await st.crm.listContacts({ updatedAfter: "2024-01-01" }, { all: true });
const locations = await st.crm.listLocations({ customerId: 1234 }, { all: true });Dispatch (st.dispatch)
- Teams, Zones, Arrival Windows, Technician Shifts, Appointment Assignments.
const teams = await st.dispatch.listTeams({}, { all: true });
const windows = await st.dispatch.listArrivalWindows({ date: "2025-01-01" }, { all: true });Equipment Systems (st.equipmentSystems)
- Installed Equipment and metadata.
const eq = await st.equipmentSystems.listInstalledEquipment({ search: "Carrier" }, { all: true });Forms (st.forms)
- Forms, Jobs + Forms, Submissions.
const forms = await st.forms.listForms({}, { all: true });Inventory (st.inventory)
- Purchase Orders (+ types/markups/requests), Receipts, Transfers, Returns, Trucks, Vendors, Warehouses.
const pos = await st.inventory.listPurchaseOrders({ status: "Open" }, { all: true });
const receipts = await st.inventory.listReceipts({ dateFrom: "2025-01-01" }, { all: true });JPM (Jobs/Projects) (st.jpm)
- Jobs, Appointments, Projects, WBS, types/statuses.
const jobs = await st.jpm.listJobs({ status: "Open" }, { all: true });
const appts = await st.jpm.listAppointments({ scheduledOnOrAfter: "2025-01-01" }, { all: true });Marketing (st.marketing) and Marketing Ads (st.marketingAds)
- Campaigns/Categories/Costs/Suppressions; Ads Attributions and Performance.
const campaigns = await st.marketing.listCampaigns({}, { all: true });
const webLead = await st.marketingAds.createWebLeadFormAttribution({ webSessionData: {}, leadId: 42 });Marketing Reputation (st.marketingReputation)
- Reviews.
const reviews = await st.marketingReputation.listReviews({ createdOnOrAfter: "2025-01-01" }, { all: true });Memberships (st.memberships)
- Memberships, Types, Recurring Service Types/Events/Services, Invoice Templates.
const memberships = await st.memberships.listMemberships({ customerId: 1234 }, { all: true });Payroll (st.payroll)
- Timesheets (+ non-job, per-job), Timesheet Codes, Payrolls, Adjustments, Job Splits, Location Labor Rates.
const codes = await st.payroll.listTimesheetCodes({}, { all: true });
const payrolls = await st.payroll.listPayrolls({ createdOnOrAfter: "2025-01-01" }, { all: true });Pricebook (st.pricebook)
- Materials, Services, Equipment, Images, Discounts & Fees, Categories, Client-Specific Pricing.
const materials = await st.pricebook.listMaterials({ updatedAfter: "2025-01-01" }, { all: true });Reporting (st.reporting)
- Report Categories and mappings, Dynamic Value Sets.
const cats = await st.reporting.listReportCategories({}, { all: true });Sales Estimates (st.salesEstimates)
- Estimates and Estimate Items.
const ests = await st.salesEstimates.listEstimates({ jobNumber: "131179" }, { all: true });Scheduling Pro (st.schedulingPro)
- Routers, Schedulers.
const schedulers = await st.schedulingPro.listSchedulers({}, { all: true });Service Agreements (st.serviceAgreements)
- Agreements and export endpoints.
const agreements = await st.serviceAgreements.listServiceAgreements({}, { all: true });Settings (st.settings)
- Employees, Technicians, Business Units, Tag Types, User Roles.
const techs = await st.settings.listTechnicians({}, { all: true });Task Management (st.taskManagement)
- Tasks and Client-Side Data.
const tasks = await st.taskManagement.listTasks({ status: "Open" }, { all: true });Telecom (st.telecom)
- Calls + media.
const calls = await st.telecom.listCalls({ createdOnOrAfter: "2025-01-01" }, { all: true });Timesheets V2 (st.timesheetsV2)
- Activities, Types, Categories.
const activities = await st.timesheetsV2.listActivities({}, { all: true });Job Bookings (st.jbce)
- Call Reasons.
const reasons = await st.jbce.listCallReasons({}, { all: true });Customer Interactions (st.customerInteractions)
- Technician Ratings.
const ratings = await st.customerInteractions.listTechnicianRatings({ createdOnOrAfter: "2025-01-01" }, { all: true });Alternate import style (functional)
import { ServiceTitanClient, CRM } from "@masonlandcattle/servicetitan-sdk";
const st = new ServiceTitanClient({ /* creds */ });
const customers = await CRM.listCustomers(st, { updatedAfter: "2024-01-01" }, { all: true });Local development / testing without publishing
Run local example scripts directly against the source using tsx.
Set environment variables:
TENANT_IDAPP_KEYCLIENT_IDSECRET_KEY
Execute examples:
npm run ex:crm
npm run ex:dispatch
npm run ex:equipThese scripts import from ../src, so there's no need to publish/install.
API Shape
/{category}/v2/tenant/{TENANT_ID}/{subject}
Use client.buildPath({ category, subject, idOrSubpath }) and client.request(method, path, { params, data }). To fetch every page server-side, pass { all: true, pageSize?: number } to supported list functions.
Publish
npm run build
npm publish --access publicNot affiliated with ServiceTitan. Respect rate limits and terms.
