Skip to main content
APT
Step-by-Step Setup 10-15 minutes

Appointment CRUD Setup

Calendars & Scheduling Intermediate
Need more detail? Read the full guide for config deep-dives and best practices.

Appointment CRUD Setup

Book, read, update, and cancel appointments through the GoHighLevel Calendars API. This guide covers timezone handling, required fields, and the full appointment lifecycle.

Prerequisites

Before you begin, confirm the following:

  • A GoHighLevel sub-account with at least one calendar configured
  • A Private Integration Token (PIT) with the calendars scope enabled
  • Your locationId from Settings > Business Info
  • A valid calendarId (retrieve from GET /calendars)
  • At least one contact in your CRM to book an appointment for
  • A REST client like Postman, Insomnia, or curl installed

Set Up Authentication

Appointment endpoints require a Bearer token with the calendars scope.

  1. Go to Settings > Integrations > Private Integrations
  2. Select or create a PIT with calendars scope (read and write)
  3. Copy the token:
export GHL_TOKEN="your-private-integration-token"
export LOCATION_ID="your-location-id"

Required headers:

Authorization: Bearer $GHL_TOKEN
Content-Type: application/json
Version: 2021-07-28

Make Your First Call

Create an appointment:

curl -X POST "https://services.leadconnectorhq.com/calendars/events/appointments" \
  -H "Authorization: Bearer $GHL_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Version: 2021-07-28" \
  -d '{
    "calendarId": "your-calendar-id",
    "locationId": "'"$LOCATION_ID"'",
    "contactId": "your-contact-id",
    "startTime": "2026-03-10T10:00:00-05:00",
    "endTime": "2026-03-10T10:30:00-05:00",
    "title": "Discovery Call",
    "appointmentStatus": "confirmed",
    "assignedUserId": "team-member-id",
    "address": "https://zoom.us/j/123456789",
    "ignoreDateRange": false,
    "toNotify": true
  }'

Key fields: startTime and endTime must include timezone offsets (ISO 8601 format). Set toNotify to true to send confirmation emails. Use ignoreDateRange to bypass availability checks when needed.

Get an appointment:

curl -X GET "https://services.leadconnectorhq.com/calendars/events/appointments/{appointmentId}" \
  -H "Authorization: Bearer $GHL_TOKEN" \
  -H "Version: 2021-07-28"

Update an appointment:

curl -X PUT "https://services.leadconnectorhq.com/calendars/events/appointments/{appointmentId}" \
  -H "Authorization: Bearer $GHL_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Version: 2021-07-28" \
  -d '{
    "startTime": "2026-03-10T14:00:00-05:00",
    "endTime": "2026-03-10T14:30:00-05:00",
    "title": "Rescheduled Discovery Call"
  }'

Cancel an appointment:

curl -X DELETE "https://services.leadconnectorhq.com/calendars/events/appointments/{appointmentId}" \
  -H "Authorization: Bearer $GHL_TOKEN" \
  -H "Version: 2021-07-28"

Handle the Response

A successful POST returns 200 with the appointment object including id, calendarId, contactId, startTime, endTime, appointmentStatus, and notification details.

The appointmentStatus field can be: confirmed, new, showed, noshow, cancelled, or invalid.

A GET returns the full appointment with contact details and assigned user info. A PUT returns the updated object. A DELETE marks the appointment as cancelled.

Important timezone behavior: the API stores times in UTC internally. Always pass ISO 8601 timestamps with timezone offsets (like -05:00 for US Eastern). The response returns times in the same format.

Common errors:

  • 401 — Token invalid or expired.
  • 404 — Appointment or calendar ID not found.
  • 422 — Missing required fields. Minimum: calendarId, locationId, contactId, startTime, endTime.
  • 400 — Time slot unavailable. Use the Free Slots endpoint to check availability first, or set ignoreDateRange: true to bypass.

Test Your Setup

Confirm your appointment management works:

  1. Use the Free Slots endpoint to find an available time
  2. Create an appointment at that time with toNotify: false (to avoid sending test emails)
  3. Read the appointment by ID and verify all fields
  4. Update the time by 1 hour and confirm the change
  5. Check the GHL Calendars dashboard to see the appointment
  6. Delete the test appointment and verify it shows as cancelled

If the appointment does not appear on the calendar, verify the calendarId is valid and the assignedUserId is a team member on that calendar.

Next Steps

Read the full Appointment CRUD guide for bulk booking patterns and rescheduling workflows. Use Free Slots to check availability before booking, or add context with Appointment Notes.

Stay sharp. New guides and playbooks as they drop.