---
title: "Create appointment booking (Public)"
description: "Create a new appointment booking. Can be used by external users without authentication. The contact is resolved by the first identity the request supplies, in this order: contact_id, then contact_phone (alias phone), then contact_name plus contact_email. A phone that is not already in the workspace creates a contact; a phone that matches an existing one books against it and does not overwrite its name."
---

> Documentation Index
> Fetch the complete documentation index at: https://developer.channelautomations.com/llms.txt
> Use this file to discover all available pages before exploring further.

Path: Channel Automation API › Calendar

`POST /api/calendar/book`

Create a new appointment booking. Can be used by external users without authentication. The contact is resolved by the first identity the request supplies, in this order: contact_id, then contact_phone (alias phone), then contact_name plus contact_email. A phone that is not already in the workspace creates a contact; a phone that matches an existing one books against it and does not overwrite its name.

## Request body

_Required._

- `workspace_id` (`post/api/calendar/book.workspace_id`; string, required) — Workspace ID
  - example `"workspace-uuid"`
- `slot_id` (`post/api/calendar/book.slot_id`; string, optional) — The `id` of a time returned by the availability endpoints. Supplying it replaces date, start_time, end_time and timezone entirely, and it wins if those are sent too. The id is re-resolved against live availability rather than trusted, so an invented time or a slot that filled up since it was offered is rejected with a 400 instead of booked. Ids embed the event type, so they must not be cached beyond the current conversation.
  - example `"9497f193-774e-489e-9687-8cea9237c41d:2026-09-22T00:00:00.000Z"`
- `contact_id` (`post/api/calendar/book.contact_id`; string, optional) — Existing contact ID (optional if creating new contact)
  - example `"existing-contact-uuid"`
- `contact_name` (`post/api/calendar/book.contact_name`; string, optional) — Contact name (required for new contacts)
  - example `"John Smith"`
- `contact_email` (`post/api/calendar/book.contact_email`; string, optional) — Contact email (required for new contacts)
  - format `email`; example `"john@example.com"`
- `contact_phone` (`post/api/calendar/book.contact_phone`; string, optional) — Contact phone number (optional)
  - example `"+1234567890"`
- `event_title` (`post/api/calendar/book.event_title`; string, optional) — Title of the appointment
  - example `"Kitchen Consultation"`
- `event_description` (`post/api/calendar/book.event_description`; string, optional) — Description of the appointment
  - example `"Discuss renovation plans"`
- `date` (`post/api/calendar/book.date`; string, optional) — Date in mm-dd-yyyy format (user-friendly)
  - example `"07-15-2025"`
- `start_time` (`post/api/calendar/book.start_time`; string, optional) — Start time in hh:mm AM/PM format (user-friendly)
  - example `"9:00 AM"`
- `end_time` (`post/api/calendar/book.end_time`; string, optional) — End time in hh:mm AM/PM format (user-friendly)
  - example `"10:00 AM"`
- `timezone` (`post/api/calendar/book.timezone`; string, optional) — IANA timezone identifier
  - example `"America/New_York"`
- `location` (`post/api/calendar/book.location`; string, optional) — Location of the appointment
  - example `"Customer's home"`
- `notes` (`post/api/calendar/book.notes`; string, optional) — Additional notes
  - example `"Prefer morning appointments"`
- `product_interest` (`post/api/calendar/book.product_interest`; string, optional) — Product or service of interest
  - example `"Kitchen Renovation"`

## Example requests

### New user-friendly date/time format (recommended)

```json
{
  "workspace_id": "workspace-uuid",
  "contact_name": "John Smith",
  "contact_email": "john@example.com",
  "contact_phone": "+1234567890",
  "event_title": "Kitchen Consultation",
  "event_description": "Discuss renovation plans",
  "date": "07-15-2025",
  "start_time": "2:30 PM",
  "end_time": "3:30 PM",
  "timezone": "America/New_York",
  "location": "Customer's home",
  "product_interest": "Kitchen Renovation"
}
```

### Booking with existing contact (user-friendly format)

```json
{
  "contact_id": "existing-contact-uuid",
  "workspace_id": "workspace-uuid",
  "event_title": "Follow-up Consultation",
  "date": "07-16-2025",
  "start_time": "10:00 AM",
  "end_time": "11:00 AM",
  "timezone": "America/Chicago",
  "location": "Virtual Meeting",
  "product_interest": "Bathroom Renovation"
}
```

### Book a time returned by availability (smallest possible body)

```json
{
  "workspace_id": "61395",
  "contact_phone": "+15551234567",
  "slot_id": "9497f193-774e-489e-9687-8cea9237c41d:2026-09-22T00:00:00.000Z"
}
```

### Phone-first booking, no name or email needed

```json
{
  "workspace_id": "61395",
  "contact_phone": "+15551234567",
  "event_type_id": "36816f8e-8f68-47f4-bdaa-26619bc16b03",
  "start_time": "2026-09-18T16:00:00.000Z",
  "end_time": "2026-09-19T00:00:00.000Z",
  "timezone": "America/Los_Angeles"
}
```

### Legacy ISO 8601 format (still supported)

```json
{
  "workspace_id": "workspace-uuid",
  "contact_name": "Jane Doe",
  "contact_email": "jane@example.com",
  "event_title": "Legacy Format Test",
  "start_time": "2025-07-15T14:00:00Z",
  "end_time": "2025-07-15T15:00:00Z",
  "product_interest": "Testing"
}
```

## Code samples

### cURL

```bash
curl --request POST \
  --url https://api.channelautomation.com/api/calendar/book \
  --header 'Content-Type: application/json' \
  --data @- <<'EOF'
{
  "workspace_id": "workspace-uuid",
  "contact_name": "John Smith",
  "contact_email": "john@example.com",
  "contact_phone": "+1234567890",
  "event_title": "Kitchen Consultation",
  "event_description": "Discuss renovation plans",
  "date": "07-15-2025",
  "start_time": "2:30 PM",
  "end_time": "3:30 PM",
  "timezone": "America/New_York",
  "location": "Customer's home",
  "product_interest": "Kitchen Renovation"
}
EOF
```

### TypeScript

```typescript
const url = 'https://api.channelautomation.com/api/calendar/book';
const options = {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    workspace_id: 'workspace-uuid',
    contact_name: 'John Smith',
    contact_email: 'john@example.com',
    contact_phone: '+1234567890',
    event_title: 'Kitchen Consultation',
    event_description: 'Discuss renovation plans',
    date: '07-15-2025',
    start_time: '2:30 PM',
    end_time: '3:30 PM',
    timezone: 'America/New_York',
    location: 'Customer\'s home',
    product_interest: 'Kitchen Renovation'
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```

### Python

```python
import requests

url = "https://api.channelautomation.com/api/calendar/book"

payload = {
    "workspace_id": "workspace-uuid",
    "contact_name": "John Smith",
    "contact_email": "john@example.com",
    "contact_phone": "+1234567890",
    "event_title": "Kitchen Consultation",
    "event_description": "Discuss renovation plans",
    "date": "07-15-2025",
    "start_time": "2:30 PM",
    "end_time": "3:30 PM",
    "timezone": "America/New_York",
    "location": "Customer's home",
    "product_interest": "Kitchen Renovation"
}
headers = {"Content-Type": "application/json"}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
```

## Responses

### 201

Booking created successfully

#### Example

```json
{
  "success": true,
  "booking": {
    "id": "appointment-uuid",
    "contact_id": "contact-uuid",
    "workspace_id": "workspace-uuid",
    "created_by": "464cf603-5a10-4470-a100-331fc0766680",
    "title": "Kitchen Renovation - John Smith",
    "description": "Kitchen Renovation booking for John Smith (john@example.com)",
    "appointment_date": "2025-07-15T09:00:00Z",
    "duration_minutes": 60,
    "location": "Customer's home",
    "created_at": "2025-07-08T10:00:00Z",
    "updated_at": "2025-07-08T10:00:00Z"
  },
  "appointment": {
    "id": "appointment-uuid",
    "contact_id": "contact-uuid",
    "workspace_id": "workspace-uuid",
    "created_by": "464cf603-5a10-4470-a100-331fc0766680",
    "title": "Kitchen Renovation - John Smith",
    "description": "Kitchen Renovation booking for John Smith (john@example.com)",
    "appointment_date": "2025-07-15T09:00:00Z",
    "duration_minutes": 60,
    "location": "Customer's home",
    "created_at": "2025-07-08T10:00:00Z",
    "updated_at": "2025-07-08T10:00:00Z"
  },
  "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
  "contact_created": false,
  "contact_resolved_via": "phone",
  "slot_id": "9497f193-774e-489e-9687-8cea9237c41d:2026-09-22T00:00:00.000Z",
  "message": "Booking created successfully"
}
```

- `success` (`post/api/calendar/book.response.201.success`; boolean, optional)
  - example `true`
- `booking` (`post/api/calendar/book.response.201.booking`; object, optional)
  - `id` (`post/api/calendar/book.response.201.booking.id`; string, optional) — Unique appointment identifier
    - example `"appointment-uuid"`
  - `contact_id` (`post/api/calendar/book.response.201.booking.contact_id`; string, optional) — Associated contact ID
    - example `"contact-uuid"`
  - `workspace_id` (`post/api/calendar/book.response.201.booking.workspace_id`; string, optional) — Workspace ID
    - example `"workspace-uuid"`
  - `created_by` (`post/api/calendar/book.response.201.booking.created_by`; string, optional) — ID of user who created the appointment
    - example `"464cf603-5a10-4470-a100-331fc0766680"`
  - `title` (`post/api/calendar/book.response.201.booking.title`; string, optional) — Appointment title
    - example `"Kitchen Renovation - John Smith"`
  - `description` (`post/api/calendar/book.response.201.booking.description`; string, optional) — Appointment description
    - example `"Kitchen Renovation booking for John Smith (john@example.com)"`
  - `appointment_date` (`post/api/calendar/book.response.201.booking.appointment_date`; string, optional) — Date and time of the appointment
    - format `date-time`; example `"2025-07-15T09:00:00Z"`
  - `duration_minutes` (`post/api/calendar/book.response.201.booking.duration_minutes`; integer, optional) — Duration of the appointment in minutes
    - example `60`
  - `location` (`post/api/calendar/book.response.201.booking.location`; string, optional) — Location of the appointment
    - example `"Customer's home"`
  - `created_at` (`post/api/calendar/book.response.201.booking.created_at`; string, optional) — When the appointment was created
    - format `date-time`; example `"2025-07-08T10:00:00Z"`
  - `updated_at` (`post/api/calendar/book.response.201.booking.updated_at`; string, optional) — When the appointment was last updated
    - format `date-time`; example `"2025-07-08T10:00:00Z"`
- `appointment` (`post/api/calendar/book.response.201.appointment`; object, optional)
  - `id` (`post/api/calendar/book.response.201.appointment.id`; string, optional) — Unique appointment identifier
    - example `"appointment-uuid"`
  - `contact_id` (`post/api/calendar/book.response.201.appointment.contact_id`; string, optional) — Associated contact ID
    - example `"contact-uuid"`
  - `workspace_id` (`post/api/calendar/book.response.201.appointment.workspace_id`; string, optional) — Workspace ID
    - example `"workspace-uuid"`
  - `created_by` (`post/api/calendar/book.response.201.appointment.created_by`; string, optional) — ID of user who created the appointment
    - example `"464cf603-5a10-4470-a100-331fc0766680"`
  - `title` (`post/api/calendar/book.response.201.appointment.title`; string, optional) — Appointment title
    - example `"Kitchen Renovation - John Smith"`
  - `description` (`post/api/calendar/book.response.201.appointment.description`; string, optional) — Appointment description
    - example `"Kitchen Renovation booking for John Smith (john@example.com)"`
  - `appointment_date` (`post/api/calendar/book.response.201.appointment.appointment_date`; string, optional) — Date and time of the appointment
    - format `date-time`; example `"2025-07-15T09:00:00Z"`
  - `duration_minutes` (`post/api/calendar/book.response.201.appointment.duration_minutes`; integer, optional) — Duration of the appointment in minutes
    - example `60`
  - `location` (`post/api/calendar/book.response.201.appointment.location`; string, optional) — Location of the appointment
    - example `"Customer's home"`
  - `created_at` (`post/api/calendar/book.response.201.appointment.created_at`; string, optional) — When the appointment was created
    - format `date-time`; example `"2025-07-08T10:00:00Z"`
  - `updated_at` (`post/api/calendar/book.response.201.appointment.updated_at`; string, optional) — When the appointment was last updated
    - format `date-time`; example `"2025-07-08T10:00:00Z"`
- `contact_id` (`post/api/calendar/book.response.201.contact_id`; string, optional) — The contact the booking was attached to, however it was resolved
  - format `uuid`
- `contact_created` (`post/api/calendar/book.response.201.contact_created`; boolean, optional) — True when this request created the contact rather than matching one
  - example `false`
- `contact_resolved_via` (`post/api/calendar/book.response.201.contact_resolved_via`; string, optional, nullable) — Which identity in the request the contact was resolved from
  - one of `"contact_id"`, `"phone"`, `"name_email"`; example `"phone"`
- `slot_id` (`post/api/calendar/book.response.201.slot_id`; string, optional, nullable) — Echoed back when the booking was made from a slot id, else null
  - example `"9497f193-774e-489e-9687-8cea9237c41d:2026-09-22T00:00:00.000Z"`
- `message` (`post/api/calendar/book.response.201.message`; string, optional)
  - example `"Booking created successfully"`

### 400

Missing required fields or invalid data

#### Example

```json
{
  "success": false,
  "error": "Missing required fields: workspace_id, start_time, end_time"
}
```

- `success` (`post/api/calendar/book.response.400.success`; boolean, optional)
  - example `false`
- `error` (`post/api/calendar/book.response.400.error`; string, optional)
  - example `"Missing required fields: workspace_id, start_time, end_time"`

### 409

Time slot conflict

#### Example

```json
{
  "success": false,
  "error": "Contact already has a booking at this time"
}
```

- `success` (`post/api/calendar/book.response.409.success`; boolean, optional)
  - example `false`
- `error` (`post/api/calendar/book.response.409.error`; string, optional)
  - example `"Contact already has a booking at this time"`

### 500

Internal server error

#### Example

```json
{
  "error": "Internal server error",
  "details": "string",
  "success": false
}
```

- `error` (`post/api/calendar/book.response.500.error`; string, optional)
  - example `"Internal server error"`
- `details` (`post/api/calendar/book.response.500.details`; string, optional)
- `success` (`post/api/calendar/book.response.500.success`; boolean, optional)
  - example `false`


Source: https://developer.channelautomations.com/api/post-api-calendar-book/index.md
