Bookings

Create a booking

Books a slot on one of your booking pages. Fetch the slots first and send the chosen slot's start and end unchanged. On a direct page the booking is confirmed straight away: the guest gets a confirmation email, the host is notified, and if the page creates Meet links a Google Calendar event is added and Google invites the guest. On an approval page the booking is pending: the host gets a request email and the guest hears nothing until the host confirms it with PATCH /bookings/{id}. With a publishable key, the start and end must match a slot that List open slots offers right now (future, inside the host's hours, within max_days_ahead), because anyone can copy that key from your page. A secret key, which only your server holds, can book any time that doesn't overlap another pending or confirmed booking, even outside the host's hours. One guest email address gets 5 booking attempts per clock hour. Scope: bookings:create. Keys: secret and publishable.

POST/bookingscreateBooking

Authorizations

bearerAuthhttp (bearer)

Authorization: Bearer clndr_sk_… (secret) or clndr_pk_… (publishable).

apiKeyHeaderapiKey

The same key in a custom header, for clients that can't set Authorization.

Server

https://www.clndr.pro/api/v1

Production

Request Body

Content-Type: application/jsonrequired

bookingPageIdstring<uuid>required

id of one of your booking pages.

guestNamestringrequired
guestEmailstring<email>required

Confirmation emails go here.

startTimestring<date-time>required

A slot's start, unchanged.

endTimestring<date-time>required

The same slot's end.

responsesarray<object>

Answers to the page's questions. Leave out questions the guest skipped. Every questionId must belong to this page: one unknown id and none of the answers are saved.

questionIdstring<uuid>required
answerstringrequired

Responses

201The new booking. It doesn't include the guest's answers; read them with Get a booking.application/json
dataobjectrequired

A booking (a meeting on the host's calendar).

idstring<uuid>required
booking_page_idstring<uuid>required
user_idstring<uuid>required

The host.

guest_namestringrequired
guest_emailstring<email>required
start_timestring<date-time>required
end_timestring<date-time>required
statusenum("pending", "confirmed", "cancelled", "completed")required

pending is waiting for the host's approval. completed is reserved and not set today.

cancellation_reasonstringnull
reminder_sentbooleannull
google_meet_linkstring,null<uri>

Set once a Google Meet link exists: at booking time for direct pages with Meet links on, at confirmation for approval pages.

google_calendar_event_idstringnull
google_calendar_idstringnull
sync_statusenum("not_synced", "pending", "synced", "failed")

Whether the booking's Google Calendar event was created, as recorded when the guest booked or the host acted in the dashboard. Confirming or cancelling through this API doesn't update it, so check google_calendar_event_id and google_meet_link after a PATCH or DELETE. not_synced means no event was needed when it was last recorded (no Meet links on the page, or not confirmed yet).

last_synced_atstring,null<date-time>
sync_failure_reasonstringnull

Why the Google Calendar event couldn't be created, for example Google Calendar is not connected.

created_atstring<date-time>required
updated_atstring<date-time>required
400A required field is missing, the body isn't JSON, guestEmail isn't an email address, the timestamps don't parse or end before they start, or responses isn't an array.application/json
errorstringrequired

What went wrong, in plain English.

401The key is missing, unknown, revoked or expired.application/json
errorstringrequired

What went wrong, in plain English.

403The key lacks bookings:create, or bookingPageId belongs to another account.application/json
errorstringrequired

What went wrong, in plain English.

409The slot can't be booked. With a publishable key the time isn't an open slot ("This time slot is not available. Fetch the slots again and pick another."); with any key, another booking got there first ("This time slot is no longer available. Please pick another."). Fetch the slots again and let the guest pick another.application/json
errorstringrequired

What went wrong, in plain English.

429Either the key's per-minute rate limit (with Retry-After and X-RateLimit headers), or this guest email has used its 5 booking attempts for the current clock hour ("Too many booking requests. Please try again later.", no headers; resets at the top of the hour).application/json
errorstringrequired

What went wrong, in plain English.

500Creating the booking failed on our side ("Failed to create meeting" or "An unexpected error occurred"). Check with List bookings whether it exists before you retry.application/json
errorstringrequired

What went wrong, in plain English.

curl https://www.clndr.pro/api/v1/bookings \
  --request POST \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "bookingPageId": "8b6f2c1e-4a1d-4f0b-9a63-2f0c5d7e9b14",
  "guestName": "Grace Hopper",
  "guestEmail": "grace@example.com",
  "startTime": "2026-10-15T08:40:00.000Z",
  "endTime": "2026-10-15T09:10:00.000Z",
  "responses": [
    {
      "questionId": "0e4b7a2c-9d1f-4b3e-a6c8-5f2d1e9b7c40",
      "answer": "Moving our sales demos onto clndr.pro."
    }
  ]
}'
{
  "data": {
    "id": "c3a7e5d1-2b9f-4c6e-8a1d-7f4b0e2c9a58",
    "booking_page_id": "8b6f2c1e-4a1d-4f0b-9a63-2f0c5d7e9b14",
    "user_id": "5d2e9f40-7c1b-4e8a-b0d6-3a9f1c2e8d77",
    "guest_name": "Grace Hopper",
    "guest_email": "grace@example.com",
    "start_time": "2026-10-15T08:40:00+00:00",
    "end_time": "2026-10-15T09:10:00+00:00",
    "status": "confirmed",
    "cancellation_reason": null,
    "reminder_sent": false,
    "google_meet_link": "https://meet.google.com/abc-defg-hij",
    "google_calendar_event_id": "6v1m0r2k8f3t5q9b7n4c",
    "google_calendar_id": "primary",
    "sync_status": "synced",
    "last_synced_at": "2026-10-10T12:31:07.481+00:00",
    "sync_failure_reason": null,
    "created_at": "2026-10-10T12:31:05.902+00:00",
    "updated_at": "2026-10-10T12:31:07.481+00:00"
  }
}