npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@masonlandcattle/servicetitan-sdk

v0.6.0

Published

ServiceTitan API SDK for Node.js with retries, rate limiting, and pagination.

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-sdk

Configure

Set env vars or pass options:

  • TENANT_ID
  • APP_KEY
  • CLIENT_ID
  • SECRET_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.

  1. Set environment variables:

    • TENANT_ID
    • APP_KEY
    • CLIENT_ID
    • SECRET_KEY
  2. Execute examples:

npm run ex:crm
npm run ex:dispatch
npm run ex:equip

These 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 public

Not affiliated with ServiceTitan. Respect rate limits and terms.