ZvenBook API Documentation

Complete guide to integrating ZvenBook's booking system API into your applications.

Quick Start

Get up and running with ZvenBook in under 5 minutes. This guide will walk you through creating your first booking.

1. Install the SDK

npm install @zvenbook/sdk

Or use your preferred package manager: yarn add @zvenbook/sdk or pnpm add @zvenbook/sdk

2. Initialize the 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.

3. Complete Integration Example

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);
  }
}

Core Concepts

Tenants

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

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

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
  ]
});

API Endpoints

GET/availability

Get available time slots for a service and provider.

Parameters: tenantId, serviceId, providerId, start, end, timezone
GET/service-availability

Get availability across services (optionally filtered by a provider).

Parameters: tenantId, providerId?, start, end, timezone
POST/bookings

Create a new booking with automatic email confirmation.

Body: tenantId, serviceId, providerId, start, end, contactEmail, contactFirstName, contactLastName
POST/meetings/create

Create a virtual meeting link (Google/Microsoft) for a time window.

Body: tenantId, providerId, subject, start, end
GET/cancel/:token

Cancel a booking using its cancellation token (no auth required).

Public endpoint: Safe to use in customer-facing applications
GET/booking/:token

Fetch booking details using a public token (no auth required).

POST/reschedule/:token

Reschedule a booking to a new time slot.

Body: start, end
GET/providers/workload

Get provider workload statistics for a date range.

Parameters: tenantId, start, end
SCHEDULEWeekly rules, working intervals, blocks

Manage 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/:id

📚 Complete API Reference

For a complete list of all endpoints with detailed parameters and examples, check out our comprehensive SDK documentation and the README file.

Integration Examples

Real-world examples of integrating ZvenBook into different platforms and frameworks.

React/Next.js Booking Widget

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>
  );
}

Express.js Backend Integration

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 });
  }
});

Advanced Features

// 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');
});

Email System

ZvenBook includes a comprehensive email system with automatic confirmations, reminders, and cancellation notifications.

✅ Booking Confirmations

Sent automatically when bookings are created with ICS calendar attachments.

⏰ 24h Reminders

Automatic reminders sent 24 hours before appointments.

❌ Cancellation Emails

Sent when bookings are cancelled with calendar removal.

🔄 Reschedule Confirmations

Updated calendar invitations when bookings are rescheduled.

Setup Required

Email functionality requires environment variables to be configured:

RESEND_API_KEY=your-resend-api-key
FROM_EMAIL=bookings@yourdomain.com
BASE_URL=https://yourdomain.com

Error Handling

The API uses standard HTTP status codes and returns detailed error messages in JSON format.

400Bad Request

Invalid request parameters or missing required fields.

409Conflict

Booking conflicts with existing appointments or business rules.

404Not Found

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" }
    ]
  }
}

Support & Resources

Need Help?

Get in touch with our support team for technical assistance.

support@zvenbook.se

Community

Join our community for discussions and updates.

GitHub Repository