> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useorbitcrm.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Scheduling API

> The Scheduling API lets you manage scheduling pages, event types, meetings, and availability schedules programmatically.

The Scheduling API lets you manage scheduling pages, event types, meetings, and availability schedules programmatically. Requires `scheduling:read`, `scheduling:write`, `meetings:read`, or `meetings:write` scopes.

## Scheduling Pages

Scheduling pages are booking pages your contacts use to schedule meetings. Each page can contain multiple event types.

### Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/v1/scheduling-pages` | List scheduling pages |
| `POST` | `/v1/scheduling-pages` | Create a scheduling page |
| `GET` | `/v1/scheduling-pages/{id}` | Get a scheduling page with event types |
| `PATCH` | `/v1/scheduling-pages/{id}` | Update a scheduling page |
| `DELETE` | `/v1/scheduling-pages/{id}` | Delete a scheduling page |

### Query Parameters

Use these when listing scheduling pages:

| Parameter | Type | Description |
| - | - | - |
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page (default: 20, max: 100) |
| `status` | string | Filter by status: draft or published |

### List Scheduling Pages

```bash theme={null}
curl https://app.useorbitcrm.ai/api/v1/scheduling-pages \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "title": "Book a Demo",
      "slug": "book-a-demo",
      "description": "Schedule a product demo with our team",
      "type": "schedule",
      "page_type": "one_on_one",
      "status": "published",
      "settings": {
        "confirmation_message": "You're booked!",
        "show_avatar": true
      },
      "created_at": "2026-01-15T10:00:00Z",
      "updated_at": "2026-01-20T14:30:00Z",
      "published_at": "2026-01-16T09:00:00Z"
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "per_page": 20,
    "total_pages": 1
  }
}
```

### Create a Scheduling Page

```bash theme={null}
curl -X POST https://app.useorbitcrm.ai/api/v1/scheduling-pages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Book a Demo",
    "slug": "book-a-demo",
    "description": "Schedule a product demo",
    "page_type": "one_on_one"
  }'
```

### Get Scheduling Page

Returns the scheduling page with its event types included.

```json theme={null}
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "title": "Book a Demo",
    "slug": "book-a-demo",
    "description": "Schedule a product demo with our team",
    "type": "schedule",
    "page_type": "one_on_one",
    "status": "published",
    "settings": {
      "confirmation_message": "You're booked!",
      "show_avatar": true,
      "redirect_url": "https://example.com/confirmed",
      "default_timezone": "Europe/Paris",
      "default_phone_country": "FR"
    },
    "remove_branding": false,
    "event_types": [
      {
        "id": "660e8400-e29b-41d4-a716-446655440001",
        "title": "30 Min Meeting",
        "slug": "30-min-meeting",
        "duration_minutes": 30,
        "location_type": "google_meet",
        "is_active": true,
        "color": "#3B82F6",
        "position": 0,
        "buffer_time_before": 0,
        "buffer_time_after": 10,
        "min_notice_minutes": 60,
        "max_booking_days": 14,
        "start_time_increment": 30,
        "requires_confirmation": false,
        "guests_allowed": true
      }
    ],
    "created_at": "2026-01-15T10:00:00Z",
    "updated_at": "2026-01-20T14:30:00Z"
  }
}
```

### Update a Scheduling Page

Send only the fields you want to change. `settings` is merged into the page's existing settings, so setting one key leaves the others untouched. Protected keys (`password`, `notifications`, `email_verification`, `security`, `custom_js`, `custom_html`, `thank_you_custom_html`) are ignored by the public API.

```bash theme={null}
curl -X PATCH https://app.useorbitcrm.ai/api/v1/scheduling-pages/{id} \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "settings": {
      "default_timezone": "Europe/Paris",
      "default_phone_country": "FR"
    }
  }'
```

| Field | Type | Description |
| - | - | - |
| `title` | string | Page title (max 200 characters) |
| `description` | string | Description shown to visitors (max 1000 characters) |
| `internal_name` | string | Name shown in the dashboard only (max 200 characters) |
| `status` | string | draft or published |
| `settings` | object | Page settings, merged with the existing settings (see below) |

The same `settings` keys are accepted when creating a page with `POST /v1/scheduling-pages`.

### Scheduling Page Settings

| Key | Type | Description |
| - | - | - |
| `default_timezone` | string | IANA timezone (e.g. `Europe/Paris`) the page starts in. Invitees can still switch to another timezone. Omit or set to `null` to detect the invitee's timezone from their browser. |
| `locked_timezone` | string | IANA timezone every invitee sees, with no option to change it (in-person events). Takes precedence over `default_timezone`. |
| `default_phone_country` | string | ISO 3166-1 alpha-2 country code (e.g. `FR`, `US`) the phone field starts on. Invitees can still pick another country. Omit or set to `null` to detect it from the visitor's location. |
| `confirmation_message` | string | Message shown after a booking is made |
| `redirect_url` | string | URL invitees are sent to after booking, instead of the confirmation message |
| `show_avatar` | boolean | Whether the host's avatar is shown on the page |

Timezones must be valid IANA zones and `default_phone_country` a two-letter country code; anything else is rejected with `400 invalid_request`.

> [!TIP]
>
> **Regional booking pages:** a French demo page should open on Paris time and +33 even for a teammate previewing it from New York, and a US page the other way round. Set `default_timezone` and `default_phone_country` per page, or use **Settings → Timezone display** and **Settings → Phone country code** in the scheduling editor.

## Event Types

Event types define the different kinds of meetings available on a scheduling page (e.g., "30 Min Demo", "15 Min Quick Call"). Event type endpoints are nested under their parent scheduling page.

### Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/v1/scheduling-pages/{id}/event-types` | List event types for a page |
| `POST` | `/v1/scheduling-pages/{id}/event-types` | Create an event type |
| `GET` | `/v1/scheduling-pages/{id}/event-types/{eventTypeId}` | Get an event type |
| `PATCH` | `/v1/scheduling-pages/{id}/event-types/{eventTypeId}` | Update an event type |
| `DELETE` | `/v1/scheduling-pages/{id}/event-types/{eventTypeId}` | Delete an event type |

### Event Type Fields

| Field | Type | Description |
| - | - | - |
| `title` | string | Display name (e.g., "30 Min Meeting") |
| `slug` | string | URL-friendly identifier (auto-generated from title if omitted) |
| `duration_minutes` | integer | Meeting duration in minutes (default: 30) |
| `location_type` | string | google\_meet, zoom, microsoft\_teams, phone, in\_person, or custom |
| `buffer_time_before` | integer | Minutes of buffer before the meeting (default: 0) |
| `buffer_time_after` | integer | Minutes of buffer after the meeting (default: 0) |
| `min_notice_minutes` | integer | Minimum advance notice required (default: 60) |
| `max_booking_days` | integer | How far in advance bookings are allowed (default: 14) |
| `start_time_increment` | integer | Time slot intervals: 5, 10, 15, 30, or 60 minutes |
| `requires_confirmation` | boolean | Reserved. Bookings are always confirmed immediately; this setting currently has no effect |
| `guests_allowed` | boolean | Whether attendees can add guests |

## Meetings

Meetings represent booked appointments. You can list, retrieve, update the status of, or delete meetings.

### Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/v1/meetings` | List meetings |
| `GET` | `/v1/meetings/{id}` | Get a meeting, with its Fathom or Fireflies recordings (`?include_transcript=true` adds the transcript text) |
| `POST` | `/v1/meetings/{id}/notes` | Write (or read) the AI notes of a meeting's recording |
| `PATCH` | `/v1/meetings/{id}` | Update a meeting (status, notes). Cancelling cleans up Zoom and calendar. |
| `DELETE` | `/v1/meetings/{id}` | Delete a meeting. Cleans up the associated Zoom meeting and calendar event. |

### Query Parameters

Use these when listing meetings:

| Parameter | Type | Description |
| - | - | - |
| `page` | integer | Page number (default: 1) |
| `per_page` | integer | Results per page (default: 20, max: 100) |
| `status` | string | Filter: scheduled, completed, cancelled, pending\_confirmation, no\_show, rescheduled |
| `since` | string | ISO date. Only meetings starting after this time. |
| `until` | string | ISO date. Only meetings starting before this time. |
| `scheduling_page_id` | string | Filter by scheduling page UUID |

### List Meetings

```bash theme={null}
curl "https://app.useorbitcrm.ai/api/v1/meetings?status=scheduled&since=2026-02-01T00:00:00Z" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "id": "770e8400-e29b-41d4-a716-446655440010",
      "attendee_name": "Jane Smith",
      "attendee_email": "jane@example.com",
      "start_time": "2026-02-10T14:00:00Z",
      "end_time": "2026-02-10T14:30:00Z",
      "timezone": "America/New_York",
      "status": "scheduled",
      "meeting_link": "https://meet.google.com/abc-defg-hij",
      "notes": null,
      "guests": [],
      "contact_id": "880e8400-e29b-41d4-a716-446655440020",
      "host_user_id": "990e8400-e29b-41d4-a716-446655440030",
      "event_type_id": "660e8400-e29b-41d4-a716-446655440001",
      "scheduling_page_id": "550e8400-e29b-41d4-a716-446655440000",
      "created_at": "2026-02-08T09:15:00Z",
      "updated_at": "2026-02-08T09:15:00Z"
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "per_page": 20,
    "total_pages": 1
  }
}
```

### Update a Meeting

You can update the `status` (to *pending\_confirmation*, *scheduled*, *completed*, *cancelled*, *rescheduled*, or *no\_show*), `notes`, and `cancellation_reason` (when cancelling).

> [!NOTE]
>
> **Cancellation cleanup:** When you set the status to *cancelled*, OrbitForms automatically deletes the associated Zoom meeting (if one was created), removes the calendar event, and sends a cancellation notification email to the attendee.

```bash theme={null}
curl -X PATCH https://app.useorbitcrm.ai/api/v1/meetings/{id} \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "completed",
    "notes": "Great demo call, follow-up scheduled"
  }'
```

### Recordings and AI notes

When a workspace connects Fathom or Fireflies, each recording is attached to the meeting it belongs to (matched by attendee email and time). `GET /v1/meetings/{id}` then returns a `transcripts` array: one entry per recording with `provider`, `title`, `started_at`, `duration_seconds`, `attendees`, `share_url`, the notetaker's own `provider_summary` and `provider_action_items`, and `ai_notes` once they are written. Pass `include_transcript=true` to add each recording's `transcript` text (speaker-labelled lines, up to 200,000 characters; `transcript_truncated` is `true` when cut).

`POST /v1/meetings/{id}/notes` returns the recording's AI notes: a 3-6 sentence `summary`, `key_points`, and `action_items`, each with the `owner` and `due_date` said in the call and the `task_id` it became. Notes already written are returned free; new notes use one AI credit. Pass `transcript_id` to pick a recording (the newest one with a transcript otherwise) and `refresh: true` to write new notes (free again if the last ones are under 10 minutes old). Needs `meetings:read`. Errors: `402` out of AI credits, `429` too many AI requests, `503` AI unavailable. To turn an action item into a task, create it with `POST /v1/tasks`.

```bash theme={null}
curl -X POST https://app.useorbitcrm.ai/api/v1/meetings/{id}/notes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

```json theme={null}
{
  "data": {
    "meeting_id": "770e8400-e29b-41d4-a716-446655440010",
    "transcript_id": "aa0e8400-e29b-41d4-a716-446655440040",
    "notes": {
      "version": 1,
      "summary": "Jane needs SSO before signing and wants a two-week trial.",
      "key_points": ["SSO is a blocker", "Budget approved for Q1"],
      "action_items": [
        { "id": "n4f2a1c-1", "text": "Send the SSO setup guide to Jane", "owner": "Alex", "due_date": "2026-02-12", "task_id": null }
      ],
      "transcript_clipped": false
    },
    "generated_at": "2026-02-10T15:02:11Z",
    "model": "claude-opus-5-5",
    "cached": false,
    "credits_used": 1
  }
}
```

## Availability Schedules

Availability schedules define working hours and date-specific overrides (holidays, vacation, etc.) for team members. These endpoints are **read-only** via the public API since availability is tied to individual user calendars.

### Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/v1/availability-schedules` | List availability schedules |
| `GET` | `/v1/availability-schedules/{id}` | Get schedule with date overrides |

### Query Parameters

| Parameter | Type | Description |
| - | - | - |
| `user_id` | string | Filter schedules by a specific user UUID |

### Get Availability Schedule

Returns the schedule with its weekly rules and any date-specific overrides.

```bash theme={null}
curl https://app.useorbitcrm.ai/api/v1/availability-schedules/{id} \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "data": {
    "id": "aa0e8400-e29b-41d4-a716-446655440040",
    "user_id": "990e8400-e29b-41d4-a716-446655440030",
    "name": "Working Hours",
    "timezone": "America/New_York",
    "is_default": true,
    "rules": [
      { "day": 1, "start": "09:00", "end": "17:00", "enabled": true },
      { "day": 2, "start": "09:00", "end": "17:00", "enabled": true },
      { "day": 3, "start": "09:00", "end": "17:00", "enabled": true },
      { "day": 4, "start": "09:00", "end": "17:00", "enabled": true },
      { "day": 5, "start": "09:00", "end": "17:00", "enabled": true }
    ],
    "date_overrides": [
      {
        "id": "bb0e8400-e29b-41d4-a716-446655440050",
        "date": "2026-02-17",
        "is_unavailable": true,
        "reason": "Holiday"
      }
    ],
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-10T08:00:00Z"
  }
}
```

## Calendar

These public-facing endpoints power the booking widget. They allow your contacts to check available time slots and book meetings without authentication. The availability endpoint accounts for the host's calendar events, buffer times, and date overrides. The booking endpoint creates the calendar event, generates the meeting link (Zoom or Google Meet), and sends a confirmation email to both parties. Microsoft Teams support coming soon.

> [!NOTE]
>
> These are public-facing endpoints used by the booking widget. They do not require an API key or authentication.

### Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/api/calendar/availability` | Get available time slots for booking |
| `POST` | `/api/calendar/book` | Book a meeting |

### Get Available Time Slots

Returns available time slots for a given host on a given date. Slots are calculated based on the host's availability schedule, existing calendar events, buffer times, and minimum notice requirements. Pass `event_type_id` (recommended) so the event type's duration, buffer, and booking-window rules apply; for round-robin and group pages, also pass `scheduling_page_id`.

#### Query Parameters

| Parameter | Type | Description |
| - | - | - |
| `user_id` | string | UUID of the host whose calendar to check (required) |
| `team_id` | string | UUID of the team that owns the scheduler (required) |
| `date` | string | Date to check, `YYYY-MM-DD` (required) |
| `duration` | integer | Meeting duration in minutes (default: event type setting, or 30) |
| `timezone` | string | IANA timezone, e.g. America/New\_York (default: UTC) |
| `event_type_id` | string | Event type UUID whose settings drive slot generation (recommended) |
| `scheduling_page_id` | string | Scheduling page UUID, for round-robin/group context (optional) |

```bash theme={null}
curl "https://app.useorbitcrm.ai/api/calendar/availability?user_id=990e8400-e29b-41d4-a716-446655440030&team_id=550e8400-e29b-41d4-a716-446655440000&date=2026-02-10&event_type_id=660e8400-e29b-41d4-a716-446655440001&timezone=America/New_York"
```

```json theme={null}
{
  "date": "2026-02-10",
  "duration": 30,
  "timezone": "America/New_York",
  "available_slots": [
    {
      "start": "2026-02-10T14:00:00.000Z",
      "end": "2026-02-10T14:30:00.000Z"
    },
    {
      "start": "2026-02-10T14:30:00.000Z",
      "end": "2026-02-10T15:00:00.000Z"
    }
  ]
}
```

Round-robin pages return an additional `round_robin: true` flag and an `available_host_count` on each slot.

### Book a Meeting

Books a meeting for the selected time slot. Creates a calendar event on the host's calendar, generates a meeting link (Zoom or Google Meet depending on the event type configuration; Microsoft Teams coming soon), and sends a confirmation email to both the host and attendee. Booking a slot that is already taken returns a `409` error.

#### Request Body

| Parameter | Type | Description |
| - | - | - |
| `user_id` | string | UUID of the host to book with (required) |
| `team_id` | string | UUID of the team that owns the scheduler (required) |
| `start` | string | Meeting start time, ISO 8601 — from the availability response (required) |
| `end` | string | Meeting end time, ISO 8601 (required) |
| `attendee_email` | string | Attendee email address (required) |
| `attendee_name` | string | Attendee full name (optional; defaults to the email address) |
| `title` | string | Calendar event title (optional) |
| `description` | string | Calendar event description (optional) |
| `timezone` | string | IANA timezone of the attendee (optional) |
| `event_type_id` | string | Event type UUID being booked (optional, recommended) |
| `scheduling_page_id` | string | Scheduling page UUID (optional) |
| `guests` | string\[] | Array of additional guest email addresses (optional) |
| `notes` | string | Additional notes or message from the attendee (optional) |
| `lead_capture_data` | object | Lead capture field responses, e.g. phone number (optional) |
| `custom_fields` | object | Custom field values (optional) |

```bash theme={null}
curl -X POST https://app.useorbitcrm.ai/api/calendar/book \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "990e8400-e29b-41d4-a716-446655440030",
    "team_id": "550e8400-e29b-41d4-a716-446655440000",
    "event_type_id": "660e8400-e29b-41d4-a716-446655440001",
    "scheduling_page_id": "550e8400-e29b-41d4-a716-446655440000",
    "start": "2026-02-10T14:00:00.000Z",
    "end": "2026-02-10T14:30:00.000Z",
    "timezone": "America/New_York",
    "attendee_name": "Jane Smith",
    "attendee_email": "jane@example.com",
    "guests": ["colleague@example.com"],
    "notes": "Interested in the enterprise plan"
  }'
```

Returns `201 Created` with the meeting record, the calendar event, and the meeting link:

```json theme={null}
{
  "success": true,
  "meeting": {
    "id": "770e8400-e29b-41d4-a716-446655440099",
    "event_type_id": "660e8400-e29b-41d4-a716-446655440001",
    "scheduling_page_id": "550e8400-e29b-41d4-a716-446655440000",
    "host_user_id": "990e8400-e29b-41d4-a716-446655440030",
    "contact_id": "880e8400-e29b-41d4-a716-446655440020",
    "start_time": "2026-02-10T14:00:00.000Z",
    "end_time": "2026-02-10T14:30:00.000Z",
    "status": "scheduled",
    "meeting_link": "https://meet.google.com/abc-defg-hij",
    "timezone": "America/New_York",
    "created_at": "2026-02-08T12:00:00Z"
  },
  "event": {
    "id": "calendar-event-id",
    "summary": "30 Min Meeting with Jane Smith",
    "start": "2026-02-10T14:00:00.000Z",
    "end": "2026-02-10T14:30:00.000Z",
    "htmlLink": "https://calendar.google.com/event?eid=..."
  },
  "meeting_link": "https://meet.google.com/abc-defg-hij"
}
```

## Required Scopes

| Scope | Description |
| - | - |
| `scheduling:read` | Read scheduling pages, event types, and availability schedules |
| `scheduling:write` | Create and update scheduling pages and event types |
| `scheduling:delete` | Delete scheduling pages and event types |
| `meetings:read` | Read meetings |
| `meetings:write` | Update meetings (status changes, notes) |
| `meetings:delete` | Delete meetings |

[Next: Rate Limits](https://docs.useorbitcrm.ai/developers/api/rate-limits.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.