Complete guide to integrating ZvenBook's booking system API into your applications.
Get up and running with ZvenBook in under 5 minutes. This guide will walk you through creating your first booking.
npm install @zvenbook/sdkOr use your preferred package manager: yarn add @zvenbook/sdk or pnpm add @zvenbook/sdk
import { createSdk } from '@zvenbook/sdk';
const sdk = createSdk({
baseUrl: 'https://your-zvenbook-instance.vercel.app'
// No API key required for public endpoints
});
// Health check
const health = await sdk.health();
console.log(health); // { ok: true }Replace the baseUrl with your deployed ZvenBook instance URL.
async function bookAppointment() {
try {
// 1. List available tenants or use tenantId from environment variables
const { tenants } = await sdk.listTenants();
const tenantId = tenants[0]._id || process.env.NEXT_PUBLIC_TENANT_ID;
// 2. Get services and providers
const [{ services }, { providers }] = await Promise.all([
sdk.listServices({ tenantId }),
sdk.listProviders({ tenantId })
]);
// 3. Check availability
const { slots } = await sdk.availability({
tenantId,
serviceId: services[0]._id,
providerId: providers[0]._id,
start: '2024-01-15T08:00:00Z',
end: '2024-01-15T18:00:00Z',
timezone: 'Europe/Stockholm'
});
// 4. Create booking
const booking = await sdk.createBooking({
tenantId,
serviceId: services[0]._id,
providerId: providers[0]._id,
start: slots[0].start,
end: slots[0].end,
contactEmail: 'customer@example.com',
contactFirstName: 'John',
contactLastName: 'Doe'
});
console.log('Booking created:', booking);
} catch (error) {
console.error('Booking failed:', error);
}
}Tenants represent separate organizations or business units. Each tenant has isolated data including services, providers, and bookings.
Best Practice: Use meaningful tenant IDs like your company name or domain (e.g., 'acme-corp', 'salon-downtown').
Services define what can be booked - haircuts, consultations, equipment rentals, etc. Each service has duration, buffer times, and capacity settings.
await sdk.createService({
tenantId: 'salon',
name: 'Haircut & Style',
durationMin: 60, // Service takes 60 minutes
bufferBeforeMin: 10, // 10 min prep time
bufferAfterMin: 15, // 15 min cleanup time
capacity: 1 // One customer at a time
});Providers are the people or resources that deliver services - stylists, doctors, conference rooms, etc. They have working schedules and can be assigned to multiple services.
await sdk.createProvider({
tenantId: 'salon',
name: 'Alex Johnson',
timezone: 'Europe/Stockholm',
email: 'alex@salon.com'
});
// Set working hours
await sdk.createWeeklyRule({
tenantId: 'salon',
providerId: 'alex',
timezone: 'Europe/Stockholm',
days: [
{ weekday: 1, start: '09:00', end: '17:00' }, // Monday
{ weekday: 2, start: '09:00', end: '17:00' }, // Tuesday
// ... more days
]
});/availabilityGet available time slots for a service and provider.
/service-availabilityGet availability across services (optionally filtered by a provider).
/bookingsCreate a new booking with automatic email confirmation.
/meetings/createCreate a virtual meeting link (Google/Microsoft) for a time window.
/cancel/:tokenCancel a booking using its cancellation token (no auth required).
/booking/:tokenFetch booking details using a public token (no auth required).
/reschedule/:tokenReschedule a booking to a new time slot.
/providers/workloadGet provider workload statistics for a date range.
Weekly rules, working intervals, blocksManage provider schedules and exceptions.
GET /weekly-rules
POST /weekly-rules
PUT /weekly-rules/:id
DELETE /weekly-rules/:id
GET /working-intervals
POST /working-intervals
DELETE /working-intervals/:id
GET /blocks
POST /blocks
DELETE /blocks/:idFor a complete list of all endpoints with detailed parameters and examples, check out our comprehensive SDK documentation and the README file.
Real-world examples of integrating ZvenBook into different platforms and frameworks.
import { createSdk } from '@zvenbook/sdk';
import { useState, useEffect } from 'react';
const sdk = createSdk({ baseUrl: process.env.NEXT_PUBLIC_ZVENBOOK_URL });
export default function BookingWidget({ tenantId, serviceId }) {
const [slots, setSlots] = useState([]);
const [providers, setProviders] = useState([]);
useEffect(() => {
async function loadData() {
const { providers } = await sdk.listProviders({ tenantId });
setProviders(providers);
if (providers.length > 0) {
const { slots } = await sdk.availability({
tenantId, serviceId, providerId: providers[0]._id,
start: new Date().toISOString(),
end: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
timezone: 'Europe/Stockholm'
});
setSlots(slots);
}
}
loadData();
}, [tenantId, serviceId]);
const bookSlot = async (slot) => {
await sdk.createBooking({
tenantId, serviceId, providerId: providers[0]._id,
start: slot.start, end: slot.end,
contactEmail: 'customer@example.com',
contactFirstName: 'John', contactLastName: 'Doe'
});
};
return (
<div className="space-y-2">
{slots.map(slot => (
<button key={slot.start} onClick={() => bookSlot(slot)}
className="p-2 bg-blue-500 text-white rounded">
{new Date(slot.start).toLocaleString()}
</button>
))}
</div>
);
}const { createSdk } = require('@zvenbook/sdk');
const express = require('express');
const sdk = createSdk({ baseUrl: process.env.ZVENBOOK_URL });
const app = express();
app.use(express.json());
app.post('/book-appointment', async (req, res) => {
try {
const booking = await sdk.createBooking({
tenantId: req.body.tenantId,
serviceId: req.body.serviceId,
providerId: req.body.providerId,
start: req.body.start,
end: req.body.end,
contactEmail: req.body.email,
contactFirstName: req.body.firstName,
contactLastName: req.body.lastName
});
res.json({ success: true, booking });
} catch (error) {
res.status(400).json({ error: error.message });
}
});// Create a virtual meeting link
const { url, platform } = await sdk.createMeeting({
tenantId: 'tenant_123',
providerId: 'provider_123',
subject: 'Consultation',
start: '2024-01-16T10:00:00Z',
end: '2024-01-16T11:00:00Z'
});
// platform: 'google' | 'microsoft'
// url: meeting join link
// Provider workload analytics
const { providers } = await sdk.getProviderWorkload({
tenantId: 'salon-123',
start: '2024-01-01T00:00:00Z',
end: '2024-01-31T23:59:59Z'
});
providers.forEach(provider => {
console.log(provider.name + ': ' + provider.booking_count + ' bookings');
});ZvenBook includes a comprehensive email system with automatic confirmations, reminders, and cancellation notifications.
Sent automatically when bookings are created with ICS calendar attachments.
Automatic reminders sent 24 hours before appointments.
Sent when bookings are cancelled with calendar removal.
Updated calendar invitations when bookings are rescheduled.
Email functionality requires environment variables to be configured:
RESEND_API_KEY=your-resend-api-key
FROM_EMAIL=bookings@yourdomain.com
BASE_URL=https://yourdomain.comThe API uses standard HTTP status codes and returns detailed error messages in JSON format.
Invalid request parameters or missing required fields.
Booking conflicts with existing appointments or business rules.
Resource not found (service, provider, booking, etc.).
// Example error response
{
"error": "Time overlaps with existing booking",
"code": "BOOKING_CONFLICT",
"details": {
"conflictingBooking": "booking-123",
"suggestedSlots": [
{ "start": "2024-01-15T11:00:00Z", "end": "2024-01-15T12:00:00Z" }
]
}
}