Skip to content

API Reference

Kaigi API reference

Kaigi is a scheduling platform. Publish event types, expose live availability, and let invitees book meetings — over a key-less public REST surface and an API-key-authenticated v1 surface.

Base URL https://app.example.com is a placeholder — replace it with your deployment origin. This reference is also available as plain text at /llms.txt for LLM ingestion.

Overview

Kaigi is a scheduling platform. A host publishes one or more event types (meeting types), each backed by an availability schedule. Kaigi computes live bookable slots from the host's weekly hours, date overrides, Google Calendar busy times, and existing bookings, and lets an invitee confirm a slot. Booking creation writes a calendar event and sends confirmation emails as best-effort side effects.

There are two REST surfaces. The public surface under /api/public needs no credentials and powers the hosted booking page — it is exactly what a third-party integrator would call to render availability and create bookings on behalf of an invitee. The authenticated surface under /api/v1 is scoped to an API key and lets a host read their own event types and bookings.

All examples use the placeholder base URL https://app.example.com. Replace it with your own deployment origin. Requests and responses are JSON; timestamps are ISO-8601 UTC strings unless noted.

This page is also available as plain-text markdown at /llms.txt for LLM ingestion — the same content, generated from the same source.

Core concepts

Event types

An event type is a bookable meeting definition owned by a host: a title, URL slug, duration, and scheduling policy (buffers, minimum notice, booking window, slot increment). Only active event types (isActive: true) are visible on the public surface. An event type's schedulingType is either individual (one host) or round_robin (a team rotates across eligible hosts).

Availability: weekly rules and date overrides

Availability lives in a schedule with an IANA timezone. Weekly rules define recurring working-hours windows (weekday 0=Sunday..6=Saturday, wall-clock times in the schedule timezone; multiple windows per day are allowed for split shifts). A date override replaces the weekly rules for one specific local date — either marking the whole day unavailable or supplying a custom window. The slot engine subtracts Google Calendar busy times and existing confirmed bookings, then applies buffers, minimum notice, and the booking window.

Slots and days

A slot is a bookable time range with ISO-8601 UTC start and end. The days endpoint returns the subset of local calendar dates (YYYY-MM-DD, in the requested tz) that contain at least one bookable slot — useful for rendering a date picker before fetching per-day slots. The tz query parameter only controls how results are grouped and displayed; it never changes which slots exist.

Bookings and statuses

A booking captures an invitee (name, email, notes, timezone) against a slot. Status is one of the values below. Creating a booking re-validates the slot against live availability and claims it atomically in the database, so a race for the same start returns a conflict.

statusmeaning
confirmedActive booking holding the slot.
cancelledCancelled by the invitee or host; the slot is freed.
errorInternal terminal state used by the booking lifecycle reconciler.

Every booking gets a high-entropy cancel token. Only its hash is stored; the raw token is returned once when the booking is created and is embedded in the invitee's cancel link. The public cancel endpoints authenticate with this raw token.

Teams and round-robin

An event type can belong to an organization (team). A round_robin team event type rotates bookings across its eligible hosts: at booking time Kaigi picks a host who is free for the requested slot, preferring the host with the fewest upcoming confirmed bookings (ties break by host creation order). Team-scoped reads on the v1 surface require the caller to be an admin or owner of the organization.

Data objects

The v1 surface returns two canonical object shapes. The public surface returns trimmed subsets of these (only the fields listed on each endpoint).

Event type object (returned by the /api/v1/event-types endpoints):

fieldtypenotes
idstring (uuid)Event type id.
slugstringURL slug, unique per host (or per team).
titlestringDisplay name.
descriptionstring | nullOptional description.
durationMinutesnumberMeeting length in minutes.
bufferBeforeMinnumberBuffer before the meeting.
bufferAfterMinnumberBuffer after the meeting.
minNoticeMinutesnumberMinimum lead time before a slot can be booked.
bookingWindowDaysnumberHow far ahead slots are offered (days).
slotIncrementMinutesnumberGranularity of generated start times.
scheduleIdstring | nullAvailability schedule; null falls back to the host default.
colorstring | nullOptional display color.
isActivebooleanWhether the event type is public.
createdAtstring (ISO-8601)Creation timestamp.
updatedAtstring (ISO-8601)Last update timestamp.

Booking object (returned by the /api/v1/bookings endpoints):

fieldtypenotes
idstring (uuid)Booking id.
eventTypeIdstring (uuid)Event type booked.
statusstringconfirmed | cancelled | error.
startstring (ISO-8601)Start instant (UTC).
endstring (ISO-8601)End instant (UTC).
inviteeNamestringInvitee name.
inviteeEmailstringInvitee email.
inviteeNotesstring | nullOptional invitee notes.
timezonestringInvitee IANA timezone.
meetUrlstring | nullGoogle Meet URL, when created.
cancelledAtstring | nullCancellation timestamp.
cancelledBystring | nullinvitee | host, when cancelled.
cancelReasonstring | nullOptional cancellation reason.
createdAtstring (ISO-8601)Creation timestamp.

Authentication

The public surface (/api/public) requires no authentication. The authenticated surface (/api/v1) requires an API key on every request.

Creating an API key

Sign in and open the dashboard at /dashboard/api-keys. Click “Create key”, give it a name, and copy the key when it is shown — it is displayed once and only its hash is stored, so it cannot be retrieved later. Revoke a key from the same page.

Sending the key

Pass the key in the x-api-key request header. As an alternative, an Authorization: Bearer <key> header is also accepted. A missing key returns 401 UNAUTHORIZED with message “Missing API key.”; an invalid key returns 401 UNAUTHORIZED with “Invalid API key.”. Every /api/v1 endpoint is scoped to the user who owns the key — you can only read your own event types and bookings (and team resources where you are an admin or owner).

curl https://app.example.com/api/v1/me \
  -H "x-api-key: $KAIGI_API_KEY"

CORS

Both developer surfaces send permissive, credential-less CORS headers (Access-Control-Allow-Origin: *; allowed methods GET, POST, DELETE, OPTIONS; allowed headers Content-Type, Authorization, x-api-key). Preflight OPTIONS requests return 204.

Rate limiting

Public endpoints are rate-limited per client IP to 30 requests per 60-second window (best-effort, per server instance). Exceeding the limit returns 429 RATE_LIMITED.

Errors and status codes

Errors use a consistent JSON envelope. details is optional and requestId is a per-response UUID useful for support.

{
  "error": {
    "code": "SLOT_TAKEN",
    "message": "That time was just booked.",
    "details": null
  },
  "requestId": "b3b6e0f2-8c2a-4e2a-9f1e-1c2d3e4f5a6b"
}
codestatuswhen
BAD_REQUEST400Missing/invalid JSON body, required field, or query parameter.
UNAUTHORIZED401Missing or invalid API key on an /api/v1 request.
CALENDAR_RECONNECT_REQUIRED401The host must reconnect their Google Calendar.
FORBIDDEN403Caller is not an admin/owner of the requested team.
NOT_FOUND404Profile, event type, booking, or user not found (or not owned by the caller).
EVENT_TYPE_NOT_FOUND404The event type is missing or inactive at booking time.
BOOKING_NOT_FOUND404No booking matches the token or id.
SLOT_TAKEN409The slot was claimed by a concurrent booking.
SLOT_INVALID422The requested start is not a currently bookable slot.
RATE_LIMITED429Too many public requests from this IP.
INTERNAL500Unhandled server error.

Public API

Key-less endpoints under /api/public, rooted at a host or team handle. These render availability and create/cancel bookings on behalf of an invitee. They are rate-limited per IP (30 requests / 60s) and require no credentials.

GET/api/public/{handle}

Fetch a public host or team profile with its active event types (trimmed fields).

Auth: None — public, rate-limited endpoint

Path parameters

NameTypeRequiredDescription
handlestringyesThe host's or team's public handle.

Response 200

The host (name, handle) and a list of active event types with public fields only.

{
  "host": { "name": "Ada Lovelace", "handle": "ada" },
  "eventTypes": [
    {
      "id": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
      "slug": "intro-call",
      "title": "Intro call",
      "description": "A 30-minute introduction.",
      "durationMinutes": 30
    }
  ]
}

Example

curl https://app.example.com/api/public/ada
  • Returns 404 NOT_FOUND if no profile matches the handle.
GET/api/public/{handle}/{eventSlug}

Fetch a single public event type by handle and slug.

Auth: None — public, rate-limited endpoint

Path parameters

NameTypeRequiredDescription
handlestringyesHost or team handle.
eventSlugstringyesEvent type slug.

Response 200

The host (name, handle) and the event type with public fields only.

{
  "host": { "name": "Ada Lovelace", "handle": "ada" },
  "eventType": {
    "id": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
    "slug": "intro-call",
    "title": "Intro call",
    "description": "A 30-minute introduction.",
    "durationMinutes": 30
  }
}

Example

curl https://app.example.com/api/public/ada/intro-call
  • Only active event types are resolvable; otherwise 404 NOT_FOUND.
GET/api/public/{handle}/{eventSlug}/days

List local calendar dates (YYYY-MM-DD) that contain at least one bookable slot.

Auth: None — public, rate-limited endpoint

Path parameters

NameTypeRequiredDescription
handlestringyesHost or team handle.
eventSlugstringyesEvent type slug.

Query parameters

NameTypeRequiredDescription
fromISO-8601 datetimeyesStart of the window (inclusive).
toISO-8601 datetimeyesEnd of the window (inclusive).
tzIANA timezonenoGrouping timezone for the returned dates. Defaults to UTC.

Response 200

An array of YYYY-MM-DD strings (in tz) that have bookable slots.

{
  "data": ["2026-07-10", "2026-07-11", "2026-07-14"]
}

Example

curl "https://app.example.com/api/public/ada/intro-call/days?from=2026-07-10&to=2026-07-20&tz=America/New_York"
  • 400 BAD_REQUEST if from or to is missing or unparseable.
  • 404 NOT_FOUND if the event type does not resolve.
GET/api/public/{handle}/{eventSlug}/slots

List live bookable slots (ISO-8601 UTC start/end) over a window.

Auth: None — public, rate-limited endpoint

Path parameters

NameTypeRequiredDescription
handlestringyesHost or team handle.
eventSlugstringyesEvent type slug.

Query parameters

NameTypeRequiredDescription
fromISO-8601 datetimeyesStart of the window (inclusive).
toISO-8601 datetimeyesEnd of the window (inclusive).
tzIANA timezonenoDisplay/grouping timezone. Does not change which slots exist. Defaults to UTC.

Response 200

An array of { start, end } slots as ISO-8601 UTC.

{
  "data": [
    { "start": "2026-07-10T15:00:00.000Z", "end": "2026-07-10T15:30:00.000Z" },
    { "start": "2026-07-10T15:30:00.000Z", "end": "2026-07-10T16:00:00.000Z" }
  ]
}

Example

curl "https://app.example.com/api/public/ada/intro-call/slots?from=2026-07-10T00:00:00Z&to=2026-07-11T00:00:00Z&tz=America/New_York"
  • 400 BAD_REQUEST if from or to is missing or unparseable.
  • 404 NOT_FOUND if the event type does not resolve.
POST/api/public/{handle}/{eventSlug}/bookings

Create a booking on a public event type. Re-validates the slot and claims it atomically.

Auth: None — public, rate-limited endpoint

Path parameters

NameTypeRequiredDescription
handlestringyesHost or team handle.
eventSlugstringyesEvent type slug.

Body parameters

NameTypeRequiredDescription
startISO-8601 datetimeyesThe exact slot start to book (must match a live slot).
namestringyesInvitee name.
emailstringyesInvitee email.
notesstringnoOptional message from the invitee.
timezoneIANA timezonenoInvitee timezone. Defaults to UTC.

Response 201

The new booking id, the raw cancel token (shown only here), a ready-made cancel URL, the host name, and the confirmed start/end.

{
  "bookingId": "b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e",
  "cancelToken": "u3Xr...redacted...9kQ",
  "cancelUrl": "https://app.example.com/booking/u3Xr...redacted...9kQ",
  "hostName": "Ada Lovelace",
  "start": "2026-07-10T15:00:00.000Z",
  "end": "2026-07-10T15:30:00.000Z"
}

Example

curl -X POST https://app.example.com/api/public/ada/intro-call/bookings \
  -H "content-type: application/json" \
  -d '{
    "start": "2026-07-10T15:00:00.000Z",
    "name": "Grace Hopper",
    "email": "grace@example.com",
    "notes": "Excited to chat",
    "timezone": "America/New_York"
  }'
  • 400 BAD_REQUEST for invalid JSON, a missing start/name/email, or an unparseable start.
  • 404 EVENT_TYPE_NOT_FOUND if the event type is missing or inactive.
  • 409 SLOT_TAKEN if a concurrent request claimed the slot first.
  • 422 SLOT_INVALID if the start is not a currently bookable slot.
GET/api/public/bookings/{token}

Look up a booking by its raw cancel token (the token from the emailed cancel link).

Auth: Cancel token in the URL path (no API key)

Path parameters

NameTypeRequiredDescription
tokenstringyesThe raw cancel token issued when the booking was created.

Response 200

A safe booking view: no host email or internal sync columns.

{
  "id": "b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e",
  "status": "confirmed",
  "start": "2026-07-10T15:00:00.000Z",
  "end": "2026-07-10T15:30:00.000Z",
  "inviteeName": "Grace Hopper",
  "eventTitle": "Intro call",
  "meetUrl": "https://meet.google.com/abc-defg-hij",
  "timezone": "America/New_York"
}

Example

curl https://app.example.com/api/public/bookings/u3Xr...redacted...9kQ
  • 404 NOT_FOUND if no booking matches the token.
POST/api/public/bookings/{token}/cancel

Cancel a booking via its raw cancel token. Idempotent on an already-cancelled booking.

Auth: Cancel token in the URL path (no API key)

Path parameters

NameTypeRequiredDescription
tokenstringyesThe raw cancel token.

Body parameters

NameTypeRequiredDescription
reasonstringnoOptional cancellation reason.

Response 200

Confirmation that the booking is cancelled.

{ "status": "cancelled" }

Example

curl -X POST https://app.example.com/api/public/bookings/u3Xr...redacted...9kQ/cancel \
  -H "content-type: application/json" \
  -d '{ "reason": "Something came up" }'
  • 404 BOOKING_NOT_FOUND if the token does not match a booking.
  • Cancelling frees the slot, deletes the calendar event, and emails both parties (best-effort).

Authenticated API (v1)

Endpoints under /api/v1, authenticated with an API key and scoped to the key's owner. Send the key in the x-api-key header (or as Authorization: Bearer <key>). A missing or invalid key returns 401 UNAUTHORIZED.

GET/api/v1/me

Return the authenticated user's basic profile.

Auth: API key (x-api-key header or Bearer token)

Response 200

The user's id, name, email, and handle.

{
  "id": "9a8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
  "name": "Ada Lovelace",
  "email": "ada@example.com",
  "handle": "ada"
}

Example

curl https://app.example.com/api/v1/me \
  -H "x-api-key: $KAIGI_API_KEY"
  • 404 NOT_FOUND if the user record is missing.
GET/api/v1/event-types

List the caller's own event types plus event types of teams they administer.

Auth: API key (x-api-key header or Bearer token)

Response 200

A data array of full event type objects (own event types followed by team event types for orgs where the caller is admin or owner).

{
  "data": [
    {
      "id": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
      "slug": "intro-call",
      "title": "Intro call",
      "description": "A 30-minute introduction.",
      "durationMinutes": 30,
      "bufferBeforeMin": 0,
      "bufferAfterMin": 0,
      "minNoticeMinutes": 120,
      "bookingWindowDays": 60,
      "slotIncrementMinutes": 15,
      "scheduleId": "8a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
      "color": "#f17463",
      "isActive": true,
      "createdAt": "2026-06-01T10:00:00.000Z",
      "updatedAt": "2026-06-01T10:00:00.000Z"
    }
  ]
}

Example

curl https://app.example.com/api/v1/event-types \
  -H "x-api-key: $KAIGI_API_KEY"
GET/api/v1/event-types/{id}

Fetch one of the caller's event types by id.

Auth: API key (x-api-key header or Bearer token)

Path parameters

NameTypeRequiredDescription
idstring (uuid)yesEvent type id.

Response 200

A single event type object.

{
  "id": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
  "slug": "intro-call",
  "title": "Intro call",
  "description": "A 30-minute introduction.",
  "durationMinutes": 30,
  "bufferBeforeMin": 0,
  "bufferAfterMin": 0,
  "minNoticeMinutes": 120,
  "bookingWindowDays": 60,
  "slotIncrementMinutes": 15,
  "scheduleId": "8a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "color": "#f17463",
  "isActive": true,
  "createdAt": "2026-06-01T10:00:00.000Z",
  "updatedAt": "2026-06-01T10:00:00.000Z"
}

Example

curl https://app.example.com/api/v1/event-types/3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f \
  -H "x-api-key: $KAIGI_API_KEY"
  • 404 NOT_FOUND if the event type does not exist or is not owned by the caller.
GET/api/v1/event-types/{id}/slots

List live bookable slots for one of the caller's event types over a window.

Auth: API key (x-api-key header or Bearer token)

Path parameters

NameTypeRequiredDescription
idstring (uuid)yesEvent type id.

Query parameters

NameTypeRequiredDescription
fromISO-8601 datetimeyesStart of the window (inclusive).
toISO-8601 datetimeyesEnd of the window (inclusive).
tzIANA timezonenoDisplay/grouping timezone. Defaults to UTC.

Response 200

An array of { start, end } slots as ISO-8601 UTC.

{
  "data": [
    { "start": "2026-07-10T15:00:00.000Z", "end": "2026-07-10T15:30:00.000Z" },
    { "start": "2026-07-10T15:30:00.000Z", "end": "2026-07-10T16:00:00.000Z" }
  ]
}

Example

curl "https://app.example.com/api/v1/event-types/3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f/slots?from=2026-07-10T00:00:00Z&to=2026-07-11T00:00:00Z" \
  -H "x-api-key: $KAIGI_API_KEY"
  • 400 BAD_REQUEST if from or to is missing or unparseable.
  • 404 NOT_FOUND if the event type is not owned by the caller.
GET/api/v1/bookings

List bookings where the caller is the host.

Auth: API key (x-api-key header or Bearer token)

Response 200

A data array of booking objects.

{
  "data": [
    {
      "id": "b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e",
      "eventTypeId": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
      "status": "confirmed",
      "start": "2026-07-10T15:00:00.000Z",
      "end": "2026-07-10T15:30:00.000Z",
      "inviteeName": "Grace Hopper",
      "inviteeEmail": "grace@example.com",
      "inviteeNotes": "Looking forward to it.",
      "timezone": "America/New_York",
      "meetUrl": "https://meet.google.com/abc-defg-hij",
      "cancelledAt": null,
      "cancelledBy": null,
      "cancelReason": null,
      "createdAt": "2026-07-01T12:00:00.000Z"
    }
  ]
}

Example

curl https://app.example.com/api/v1/bookings \
  -H "x-api-key: $KAIGI_API_KEY"
POST/api/v1/bookings

Create a booking on one of the caller's own event types. Supports idempotency.

Auth: API key (x-api-key header or Bearer token)

Body parameters

NameTypeRequiredDescription
eventTypeIdstring (uuid)yesAn event type owned by the caller.
startISO-8601 datetimeyesThe exact slot start to book.
namestringyesInvitee name.
emailstringyesInvitee email.
notesstringnoOptional invitee notes.
timezoneIANA timezonenoInvitee timezone. Defaults to UTC.
idempotencyKeystringnoIf a booking already exists for this key, it is returned unchanged instead of creating a new one.

Response 201

The created booking object and a cancel URL. (The raw cancel token itself is not returned on this surface.)

{
  "booking": {
    "id": "b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e",
    "eventTypeId": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
    "status": "confirmed",
    "start": "2026-07-10T15:00:00.000Z",
    "end": "2026-07-10T15:30:00.000Z",
    "inviteeName": "Grace Hopper",
    "inviteeEmail": "grace@example.com",
    "inviteeNotes": "Looking forward to it.",
    "timezone": "America/New_York",
    "meetUrl": "https://meet.google.com/abc-defg-hij",
    "cancelledAt": null,
    "cancelledBy": null,
    "cancelReason": null,
    "createdAt": "2026-07-01T12:00:00.000Z"
  },
  "cancelUrl": "https://app.example.com/booking/u3Xr...redacted...9kQ"
}

Example

curl -X POST https://app.example.com/api/v1/bookings \
  -H "x-api-key: $KAIGI_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "eventTypeId": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
    "start": "2026-07-10T15:00:00.000Z",
    "name": "Grace Hopper",
    "email": "grace@example.com",
    "idempotencyKey": "order-1234"
  }'
  • 400 BAD_REQUEST if eventTypeId, start, name, or email is missing, or start is unparseable.
  • 404 NOT_FOUND if the event type is not owned by the caller.
  • 409 SLOT_TAKEN if the slot was just claimed; 422 SLOT_INVALID if the start is not bookable.
GET/api/v1/bookings/{id}

Fetch one of the caller's bookings by id.

Auth: API key (x-api-key header or Bearer token)

Path parameters

NameTypeRequiredDescription
idstring (uuid)yesBooking id.

Response 200

A single booking object.

{
  "id": "b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e",
  "eventTypeId": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
  "status": "confirmed",
  "start": "2026-07-10T15:00:00.000Z",
  "end": "2026-07-10T15:30:00.000Z",
  "inviteeName": "Grace Hopper",
  "inviteeEmail": "grace@example.com",
  "inviteeNotes": "Looking forward to it.",
  "timezone": "America/New_York",
  "meetUrl": "https://meet.google.com/abc-defg-hij",
  "cancelledAt": null,
  "cancelledBy": null,
  "cancelReason": null,
  "createdAt": "2026-07-01T12:00:00.000Z"
}

Example

curl https://app.example.com/api/v1/bookings/b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e \
  -H "x-api-key: $KAIGI_API_KEY"
  • 404 NOT_FOUND if the booking does not exist or the caller is not its host.
POST/api/v1/bookings/{id}/cancel

Cancel one of the caller's bookings by id. The caller must be the assigned host or an admin/owner of the event type's team.

Auth: API key (x-api-key header or Bearer token)

Path parameters

NameTypeRequiredDescription
idstring (uuid)yesBooking id.

Body parameters

NameTypeRequiredDescription
reasonstringnoOptional cancellation reason.

Response 200

The cancelled booking, wrapped as { booking } and using the same booking view as the other v1 booking endpoints.

{
  "booking": {
    "id": "b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e",
    "eventTypeId": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
    "status": "cancelled",
    "start": "2026-07-10T15:00:00.000Z",
    "end": "2026-07-10T15:30:00.000Z",
    "inviteeName": "Grace Hopper",
    "inviteeEmail": "grace@example.com",
    "inviteeNotes": "Looking forward to it.",
    "timezone": "America/New_York",
    "meetUrl": "https://meet.google.com/abc-defg-hij",
    "cancelledAt": "2026-07-02T09:00:00.000Z",
    "cancelledBy": "host",
    "cancelReason": "Something came up",
    "createdAt": "2026-07-01T12:00:00.000Z"
  }
}

Example

curl -X POST https://app.example.com/api/v1/bookings/b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e/cancel \
  -H "x-api-key: $KAIGI_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "reason": "Something came up" }'
  • 404 BOOKING_NOT_FOUND if the booking is missing or the caller may not cancel it.
  • Idempotent: cancelling an already-cancelled booking returns it unchanged.
GET/api/v1/team-bookings

List bookings across a team's event types. The caller must be an admin or owner of the organization.

Auth: API key (x-api-key header or Bearer token)

Query parameters

NameTypeRequiredDescription
organizationIdstring (uuid)yesThe organization (team) to list bookings for.

Response 200

A data array of booking objects, each with an added eventTitle field.

{
  "data": [
    {
      "id": "b7e0c2d1-4f3a-4b5c-8d6e-7f8a9b0c1d2e",
      "eventTypeId": "3f2c1e90-7a1b-4c3d-9e0f-1a2b3c4d5e6f",
      "status": "confirmed",
      "start": "2026-07-10T15:00:00.000Z",
      "end": "2026-07-10T15:30:00.000Z",
      "inviteeName": "Grace Hopper",
      "inviteeEmail": "grace@example.com",
      "inviteeNotes": null,
      "timezone": "America/New_York",
      "meetUrl": "https://meet.google.com/abc-defg-hij",
      "cancelledAt": null,
      "cancelledBy": null,
      "cancelReason": null,
      "createdAt": "2026-07-01T12:00:00.000Z",
      "eventTitle": "Team intro"
    }
  ]
}

Example

curl "https://app.example.com/api/v1/team-bookings?organizationId=5d4c3b2a-1e0f-4a9b-8c7d-6e5f4a3b2c1d" \
  -H "x-api-key: $KAIGI_API_KEY"
  • 400 BAD_REQUEST if organizationId is missing.
  • 403 FORBIDDEN if the caller is not an admin or owner of the team.