GET /v1/calendar/bookings#
List bookings (by member window or by phone). Two modes. **Member window** (member + from + to, optionally status): one member's bookings whose start falls in [from, to), earliest first, the feed behind the console's list and calendar views. **Caller-ID lookup** (phone alone): the upcoming bookings made with that phone number, any formatting, matching is digits-only, earliest first, capped at 5, terminal and past bookings excluded. This is the same lookup a voice agent's find_bookings tool performs from the caller ID, so reschedule/cancel works without a spoken booking reference.
Parameters
| Name |
In |
Type |
Required |
Description |
member |
query |
string |
|
Member id. Required unless phone is given. |
from |
query |
string |
|
Window start, RFC3339. Required unless phone is given. |
to |
query |
string |
|
Window end, RFC3339. Required unless phone is given. |
status |
query |
string |
|
Member-window mode only: filter by status: pending, accepted, cancelled, rejected. |
phone |
query |
string |
|
Caller-ID lookup: the phone a booking was made with (any formatting). When present the member window params are ignored. |
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl "https://api.voiceland.ai/v1/calendar/bookings" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"items": [
{
"start": "2026-09-01T06:00:00Z",
"status": "accepted",
"uid": "n7Qk2p"
}
]
}
POST /v1/calendar/bookings#
Book an appointment. Commits a booking at an open slot. email is optional for phone-only bookings; phone is optional for web/API ones. answers supplies responses to the event type's custom questions, keyed by question key (a required question that is unanswered returns 422). The booking reserves the member's time through a single day-ledger, so it can never double-book; a taken slot returns 409. A start past the event type's booking window, on a member out-of-office date, or that would exceed a per-day/week/month limit is rejected with 422. The response status is accepted for an ordinary event type, or pending when the event type requires confirmation (the slot is still reserved; a team manager must confirm before the invite and reminder go out). For a video-call event type (location_type meet), the response and the confirmation email carry the meeting_url join link once the member's connected calendar provisions it. Pass an Idempotency-Key header (or idempotency_key field) so a retried create returns the original booking instead of a duplicate. Include a recurrence rule to make this the first of a repeating series.
Request body
application/json
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/bookings" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"answers": {
"reason": "annual checkup"
},
"duration": 30,
"email": "jane@example.com",
"event_type_id": "consultation",
"member_id": "dr-a",
"name": "Jane Doe",
"recurrence": {
"count": 4,
"freq": "weekly"
},
"start": "2026-09-01T06:00:00Z",
"timezone": "Europe/Athens"
}'
Example response
{
"end": "2026-09-01T06:30:00Z",
"start": "2026-09-01T06:00:00Z",
"status": "accepted",
"title": "Consultation",
"uid": "n7Qk2p..."
}
GET /v1/calendar/bookings/{uid}#
Get a booking. Returns one booking and its attendees by the unguessable booking reference.
Parameters
| Name |
In |
Type |
Required |
Description |
uid |
path |
string |
Yes |
Booking reference. |
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl "https://api.voiceland.ai/v1/calendar/bookings/{uid}" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"attendees": [],
"booking": {
"status": "accepted",
"uid": "n7Qk2p"
}
}
POST /v1/calendar/bookings/{uid}/cancel#
Cancel a booking. Cancels a booking and frees its slot. Idempotent. An attendee who gave an email receives a cancellation with a calendar update.
Parameters
| Name |
In |
Type |
Required |
Description |
uid |
path |
string |
Yes |
Booking reference. |
Request body
application/json
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/bookings/{uid}/cancel" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "changed plans"
}'
Example response
{
"status": "cancelled",
"uid": "n7Qk2p"
}
POST /v1/calendar/bookings/{uid}/confirm#
Confirm a pending booking. Approves a booking that is awaiting host confirmation, moving it from pending to accepted. The slot was already reserved at creation, so this is a status change only. Idempotent on an already-accepted booking.
Parameters
| Name |
In |
Type |
Required |
Description |
uid |
path |
string |
Yes |
Booking reference. |
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/bookings/{uid}/confirm" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"status": "accepted",
"uid": "n7Qk2p"
}
POST /v1/calendar/bookings/{uid}/no-show#
Mark a booking as a no-show. Flags (or clears) a booking whose attendee did not turn up. no_show defaults to true when omitted; pass false to clear. This does NOT free the time (the slot was still held) - it is a reporting signal that feeds the no-show rate in insights. A cancelled or rejected booking cannot be marked no-show (422). Emits a booking.no_show webhook when set.
Parameters
| Name |
In |
Type |
Required |
Description |
uid |
path |
string |
Yes |
Booking reference. |
Request body
application/json
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/bookings/{uid}/no-show" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"no_show": true
}'
Example response
{
"no_show": true,
"status": "accepted",
"uid": "n7Qk2p"
}
PUT /v1/calendar/bookings/{uid}/notes#
Set a booking's internal notes. Sets the host-only internal note on a booking (prep notes, context). It is never shown to the booker and never appears on the public booking detail. Sending an empty string clears it.
Parameters
| Name |
In |
Type |
Required |
Description |
uid |
path |
string |
Yes |
Booking reference. |
Request body
application/json
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X PUT "https://api.voiceland.ai/v1/calendar/bookings/{uid}/notes" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"notes": "Returning patient, review last visit first."
}'
Example response
{
"internal_notes": "Returning patient, review last visit first.",
"uid": "n7Qk2p"
}
POST /v1/calendar/bookings/{uid}/reject#
Reject a pending booking. Declines a booking awaiting confirmation, freeing its slot and marking it rejected. Idempotent on a booking that is already terminal.
Parameters
| Name |
In |
Type |
Required |
Description |
uid |
path |
string |
Yes |
Booking reference. |
Request body
application/json
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/bookings/{uid}/reject" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "fully booked"
}'
Example response
{
"status": "rejected",
"uid": "n7Qk2p"
}
POST /v1/calendar/bookings/{uid}/reschedule#
Reschedule a booking. Moves a booking to a new start time, re-validating the new slot. The attendee's existing calendar invite moves rather than being re-sent.
Parameters
| Name |
In |
Type |
Required |
Description |
uid |
path |
string |
Yes |
Booking reference. |
Request body
application/json
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/bookings/{uid}/reschedule" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"start": "2026-09-01T07:00:00Z"
}'
Example response
{
"start": "2026-09-01T07:00:00Z",
"status": "accepted",
"uid": "n7Qk2p"
}
GET /v1/calendar/holiday-lists#
List your holiday lists. Returns the holiday lists available to you: the built-in Greek national list first (id greek-national, builtin: true, computed, linkable, not editable) followed by the lists you have created. A member links any number of lists via holiday_list_ids (on POST /calendar/members), and every listed date is excluded from that member's availability, no slots are offered and no booking is accepted on those days.
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl "https://api.voiceland.ai/v1/calendar/holiday-lists" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"items": [
{
"builtin": true,
"days": [
{
"date": "2026-01-01",
"name": "Πρωτοχρονιά",
"name_en": "New Year's Day"
}
],
"id": "greek-national",
"name": "Ελληνικές εθνικές αργίες",
"name_en": "Greek national holidays"
},
{
"days": [
{
"date": "2026-07-17",
"name": "Εορτή πολιούχου"
}
],
"id": "argies-iatreiou",
"name": "Αργίες ιατρείου"
}
]
}
POST /v1/calendar/holiday-lists#
Create or update a holiday list. Upserts a named holiday list. days are whole closed days (date YYYY-MM-DD + optional name); duplicates collapse (your own name for a date wins) and days come back sorted. Set clone_greek: true to seed the list with the Greek national holidays for the ?from=/?to= year range before your own days apply, so cloning the national list and adding your own closures is one request. To remove a day, send the list again without it: the stored days are replaced, not merged. Link the list to a member with holiday_list_ids to exclude its dates from that member's availability; a member may link several lists. The id greek-national is reserved for the built-in national list and is refused here, link it directly instead.
Parameters
| Name |
In |
Type |
Required |
Description |
from |
query |
string |
|
With clone_greek: first year to seed (default: the current year). |
to |
query |
string |
|
With clone_greek: last year to seed, inclusive (default: next year). |
Request body
application/json
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/holiday-lists" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"clone_greek": true,
"days": [
{
"date": "2026-07-17",
"name": "Εορτή πολιούχου"
}
],
"name": "Αργίες ιατρείου"
}'
Example response
{
"days": [
{
"date": "2026-01-01",
"name": "Πρωτοχρονιά"
},
{
"date": "2026-07-17",
"name": "Εορτή πολιούχου"
}
],
"id": "argies-iatreiou",
"name": "Αργίες ιατρείου"
}
DELETE /v1/calendar/holiday-lists/{id}#
Delete a holiday list. Deletes a holiday list. Members still naming its id simply stop excluding those dates, the link is ignored, never an error.
Parameters
| Name |
In |
Type |
Required |
Description |
id |
path |
string |
Yes |
Holiday list id. |
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X DELETE "https://api.voiceland.ai/v1/calendar/holiday-lists/{id}" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"deleted": true
}
GET /v1/calendar/holidays/greek#
Read the Greek national holidays. Returns the Greek national public holidays for a year range, the fixed feasts plus the movable ones that follow the Orthodox Easter (Clean Monday, Good Friday, Easter Monday, Holy Spirit Monday). Computed, always current, read-only; each day carries the Greek name and an English name_en. Link the built-in list to a member directly with the reserved id greek-national in holiday_list_ids, or make an editable copy with POST /calendar/holiday-lists and clone_greek: true.
Parameters
| Name |
In |
Type |
Required |
Description |
from |
query |
string |
|
First year (default: the current year). |
to |
query |
string |
|
Last year, inclusive (default: next year; at most 6 years per read). |
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl "https://api.voiceland.ai/v1/calendar/holidays/greek" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"days": [
{
"date": "2026-01-01",
"name": "Πρωτοχρονιά"
},
{
"date": "2026-04-10",
"name": "Μεγάλη Παρασκευή"
}
],
"from_year": 2026,
"name": "Ελληνικές εθνικές αργίες",
"to_year": 2027
}
GET /v1/calendar/members/{memberID}/event-types#
List a member's event types. Returns the bookable event types offered by one member of your calendar. Each carries its offered durations (minutes) and availability.
Parameters
| Name |
In |
Type |
Required |
Description |
memberID |
path |
string |
Yes |
Member id. |
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl "https://api.voiceland.ai/v1/calendar/members/{memberID}/event-types" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"items": [
{
"durations": [
15,
30
],
"id": "consult",
"title": "Consultation"
}
]
}
POST /v1/calendar/members/{memberID}/event-types#
Create or update an event type. Upserts an event type for a member. durations is one or more meeting lengths in minutes; the first is the default. schedule_id points at an availability schedule (empty = the member's default). buffer_before_min/buffer_after_min pad each booking; min_notice_min is the minimum lead time. location_type/location_value carry the meeting place; a location_type of meet provisions a video call on the member's connected calendar (Google Meet or Microsoft Teams) and puts the join link on each booking's meeting_url. hidden keeps the event type off the public list (reachable only by direct link, mint one with the rotate-link route below). requires_confirmation holds every booking as pending until a team manager confirms it, the slot is reserved meanwhile (so it can't be double-booked), but the calendar invite and reminder are sent only on confirmation; a reject frees the slot. max_future_days caps how far ahead a booker may schedule (0 = no cap). max_per_day/max_per_week/max_per_month cap how many bookings of this event type may exist in the rolling day/week/month (0 = no cap). default_recurrence makes every booking repeat by default. questions are extra booker-facing intake fields (key, label, type one of text/textarea/select/checkbox, required, options for select) collected on the booking page and stored with the booking. special_category flags the event type as handling health information (PHI).
Parameters
| Name |
In |
Type |
Required |
Description |
memberID |
path |
string |
Yes |
Member id. |
Request body
application/json
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/members/{memberID}/event-types" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"buffer_after_min": 10,
"default_recurrence": {
"count": 4,
"freq": "weekly"
},
"durations": [
15,
30
],
"hidden": false,
"max_future_days": 60,
"max_per_day": 8,
"min_notice_min": 120,
"questions": [
{
"key": "reason",
"label": "Reason for visit",
"required": true,
"type": "text"
}
],
"requires_confirmation": false,
"schedule_id": "default",
"title": "Consultation"
}'
Example response
{
"durations": [
15,
30
],
"id": "consultation",
"schedule_id": "default",
"title": "Consultation"
}
POST /v1/calendar/members/{memberID}/event-types/{id}/rotate-link#
Mint or rotate an event type's private link. Generates a fresh unguessable link_hash for an event type and returns it, invalidating any previous private link. A hidden event type is reachable on the public booking page only with ?hash= set to this value, so this is how you hand out (or revoke and reissue) a private booking link. The hash is never returned on the public event-type detail.
Parameters
| Name |
In |
Type |
Required |
Description |
memberID |
path |
string |
Yes |
Member id. |
id |
path |
string |
Yes |
Event type id. |
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl -X POST "https://api.voiceland.ai/v1/calendar/members/{memberID}/event-types/{id}/rotate-link" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"id": "consultation",
"link_hash": "kJ8s2ntQ4mZ0pR7vXaLbWc9fY1hd3Ge"
}
GET /v1/calendar/slots#
Read open booking slots. Returns the bookable start instants for an event type and duration over a date range. Each entry in available carries the machine start (UTC, RFC3339, book with this exact value) and a label already formatted in the booker's timezone and language. lang picks the label language (el default, en). The flat slots array of bare UTC instants is also returned. Slots respect the event type's booking window (max_future_days), the member's out-of-office dates and the member's linked holiday lists, starts past the horizon or on a blocked date are never offered. Reads only local availability, never a live third-party call, so it is fast enough for a live agent to call mid-conversation.
Parameters
| Name |
In |
Type |
Required |
Description |
member_id |
query |
string |
Yes |
Member id. |
event_type_id |
query |
string |
Yes |
Event type id. |
duration |
query |
string |
|
Meeting length in minutes; omit for the event type default. |
start |
query |
string |
Yes |
Range start, RFC3339. |
end |
query |
string |
Yes |
Range end, RFC3339. |
timezone |
query |
string |
|
Booker IANA timezone (drives the localized labels). |
lang |
query |
string |
|
Label language: el (default) or en. |
Responses
| Code |
Description |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Example request
curl "https://api.voiceland.ai/v1/calendar/slots" \
-H "Authorization: Bearer VL_API_KEY"
Example response
{
"available": [
{
"label": "Τρι 1 Σεπ, 09:00",
"start": "2026-09-01T06:00:00Z"
},
{
"label": "Τρι 1 Σεπ, 09:30",
"start": "2026-09-01T06:30:00Z"
}
],
"lang": "el",
"slots": [
"2026-09-01T06:00:00Z",
"2026-09-01T06:30:00Z"
],
"timezone": "Europe/Athens"
}
Schemas#
Error#
Error envelope returned for non-2xx responses.
| Field |
Type |
Required |
Description |
error |
object |
Yes |
|