Unofficial SDK wrapper for Zenoti's REST API. Typed client for guests, appointments, bookings, services, and therapists.
pnpm add zenoti
# or
npm install zenotiCreate a client with your API key and center ID. An optional baseUrl overrides the default https://api.zenoti.com.
import { Zenoti } from "zenoti";
const client = new Zenoti({
apiKey: "your-api-key",
centerId: "your-center-id",
// baseUrl: "https://api.zenoti.com" // optional
});create(payload: CreateGuestDto)– Create a guest withpersonal_info(first_name, last_name, email, mobile_phone)search(payload: SearchGuestDto)– Search byemail,first_name, orlast_name(at least one required)getAll(page?, size?)– List guests with pagination (defaults: page 1, size 10)get(guest_id)– Get a guest by IDgetPurchases(guest_id)– List a guest’s products
getAll(start_date, end_date)– List appointments in a date range
create(payload: CreateBookingDto)– Create a booking withdate,guests(id, items withitem_id), and optionaltherapist_idgetSlots(booking_id)– Get available slots for a bookingreserve(booking_id, slot_time, create_invoice?)– Reserve a slot (defaultcreate_invoice: false)confirm(booking_id, notes, group_name)– Confirm a reserved booking
getAll(page?, size?)– List services with pagination (defaults: page 1, size 30)search(search_string)– Search services by name; experimental, may be rate-limited
getAll()– List all therapists for the center
import { Zenoti } from "zenoti";
const client = new Zenoti({
apiKey: process.env.ZENOTI_API_KEY!,
centerId: process.env.ZENOTI_CENTER_ID!,
});
// Create a guest
const guest = await client.guests.create({
personal_info: {
first_name: "Jane",
last_name: "Doe",
email: "jane@example.com",
mobile_phone: { country_code: 1, number: "5551234567" },
},
});
// Search guests
const results = await client.guests.search({ email: "jane@example.com" });
// List appointments
const appointments = await client.appointments.getAll("2025-01-01", "2025-01-31");
// Create a booking and reserve a slot
const booking = await client.bookings.create({
date: "2025-01-15",
guests: { id: guest.id, items: { item_id: "service-uuid" } },
therapist_id: "optional-therapist-uuid",
});
const { slots } = await client.bookings.getSlots(booking.id);
await client.bookings.reserve(booking.id, slots[0].Time);
await client.bookings.confirm(booking.id, "Notes", "Group name");The SDK throws:
ValidationError– Invalid or missing input (e.g. empty search, invalid DTOs)NotFoundError– Resource not foundAuthenticationError– Invalid or missing API keyAuthorizationError– Insufficient permissions
You can import the main client, options, services, types, and errors:
import {
Zenoti,
ZenotiClientOptions,
ValidationError,
NotFoundError,
AuthenticationError,
AuthorizationError,
} from "zenoti";pnpm buildOutput: ESM (dist/index.js), CJS (dist/index.cjs), and type definitions (dist/index.d.ts).
