Skip to main content

What are Bookings?

Bookings represent scheduled appointments between your business and customers. Each booking has a time slot, service, contact information, and optional host or team assignment.

Booking Object

{
  "id": "book_abc123xyz",
  "confirmation_number": "BOOK_ABC123XYZ",
  "status": "confirmed",
  "start_at": "2025-12-03T14:00:00Z",
  "end_at": "2025-12-03T15:00:00Z",
  "service_name": "Haircut",
  "organization_name": "Acme Salon",
  "location": {
    "type": "onsite",
    "value": "123 Main St, Suite 100"
  }
}

Booking Fields

id
string
Unique identifier for the booking
confirmation_number
string
Human-readable confirmation number (uppercase version of ID)
status
enum
Booking status: confirmed, pending, canceled
start_at
string
ISO 8601 timestamp of when the booking starts (UTC)
end_at
string
ISO 8601 timestamp of when the booking ends (UTC)
service_name
string
Name of the booked service
organization_name
string
Name of the business
location
object
Where the appointment takes place
  • type: onsite, phone, meet_url, or custom
  • value: Address, phone number, or meeting link

Booking Status Lifecycle

1

confirmed

Booking is confirmed and the time slot is reserved.Next states: canceled
2

canceled

Booking was cancelled by customer or business.Final state - Time slot is released

Available Operations

Two Authentication Methods

The Booking API uses different authentication for different scenarios:

1. API Key Authentication

For your application to create bookings on behalf of customers:
curl -X POST https://api.kordless.ai/api/calendar/v1/public/bookings \
  -H "x-kordless-key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{...}'
Used for: Creating bookings, fetching availability

2. Confirmation + Contact Verification

For customers to manage their own bookings:
curl "https://api.kordless.ai/api/calendar/v1/public/bookings/confirmation/[email protected]"
Used for: Lookup, cancel, reschedule operations This keeps your API key secure while allowing customer self-service.

Complete Booking Flow

const API_KEY = process.env.KORDLESS_API_KEY;
const ORG_SLUG = 'acme-salon';

// 1. Get services
const orgResponse = await fetch(
  `https://api.kordless.ai/api/calendar/v1/public/org/${ORG_SLUG}`,
  { headers: { 'x-kordless-key': API_KEY } }
);
const { services } = await orgResponse.json();

// 2. Get available slots
const params = new URLSearchParams({
  org_slug: ORG_SLUG,
  service_slug: services[0].slug,
  from: '2025-12-03T00:00:00Z',
  to: '2025-12-03T23:59:59Z'
});

const slotsResponse = await fetch(
  `https://api.kordless.ai/api/calendar/v1/public/availability?${params}`,
  { headers: { 'x-kordless-key': API_KEY } }
);
const { slots } = await slotsResponse.json();

// 3. Create booking
const bookingResponse = await fetch(
  'https://api.kordless.ai/api/calendar/v1/public/bookings',
  {
    method: 'POST',
    headers: {
      'x-kordless-key': API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      org_slug: ORG_SLUG,
      service_slug: services[0].slug,
      starts_at: slots[0].startsAt,
      ends_at: slots[0].endsAt,
      timezone: 'America/New_York',
      contact: {
        name: 'Jane Doe',
        email: '[email protected]'
      }
    })
  }
);

const { booking } = await bookingResponse.json();
console.log(`Confirmation: ${booking.confirmation_number}`);

Customer Self-Service Flow

// Customer looks up their booking
const lookupResponse = await fetch(
  `https://api.kordless.ai/api/calendar/v1/public/bookings/confirmation/${confirmationNumber}?contact=${customerEmail}`
);
const { booking } = await lookupResponse.json();

// Customer cancels
await fetch(
  `https://api.kordless.ai/api/calendar/v1/public/bookings/confirmation/${confirmationNumber}/cancel?contact=${customerEmail}`,
  { method: 'POST' }
);

Best Practices

Before creating a booking, verify the time slot is available:
const { slots } = await getAvailability({
  org_slug: 'acme-salon',
  service_slug: 'haircut',
  from: startDate,
  to: endDate
});

if (slots.length === 0) {
  throw new Error('No available slots');
}

// Use the first available slot
await createBooking({
  starts_at: slots[0].startsAt,
  ends_at: slots[0].endsAt,
  ...
});
Prevent duplicate bookings when retrying failed requests:
const idempotencyKey = `booking-${userId}-${Date.now()}`;

await fetch(url, {
  headers: {
    'Idempotency-Key': idempotencyKey,
    ...
  },
  ...
});
The same key returns the same result for 24 hours.
Time slots can be booked by others between checking availability and creating:
try {
  const booking = await createBooking(data);
  return { success: true, booking };
} catch (error) {
  if (error.status === 409) {
    // Slot was just booked
    const newSlots = await getAvailability({...});
    return {
      success: false,
      message: 'Slot no longer available',
      alternatives: newSlots
    };
  }
  throw error;
}
Always store confirmation numbers for customer reference:
const { booking } = await createBooking(data);

// Store in your database
await db.appointments.create({
  confirmationNumber: booking.confirmation_number,
  customerId: customer.id,
  bookedAt: new Date()
});

// Send to customer
await sendEmail({
  to: customer.email,
  subject: 'Booking Confirmed',
  body: `Your confirmation number: ${booking.confirmation_number}`
});

Webhooks Integration

Receive real-time notifications when bookings are created, updated, or cancelled:
{
  "event": "booking.created",
  "timestamp": "2025-12-03T10:00:00Z",
  "data": {
    "booking": {
      "id": "book_abc123",
      "confirmation_number": "BOOK_ABC123",
      "status": "confirmed",
      ...
    }
  }
}
Available Events:
  • booking.created - New booking created
  • booking.updated - Booking rescheduled
  • booking.cancelled - Booking cancelled
Set up Webhooks

Next Steps