Skip to main content
Bookings (appointments) represent scheduled meetings between hosts and attendees. Each booking links a meeting type to a specific time slot.

Booking Lifecycle

Create a Booking

curl -X POST "https://api.meetergo.com/v4/booking" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "meetingTypeId": "770e8400-e29b-41d4-a716-446655440002",
    "start": "2024-01-15T09:00:00+01:00",
    "hostIds": ["550e8400-e29b-41d4-a716-446655440000"],
    "attendee": {
      "email": "[email protected]",
      "firstname": "Jane",
      "lastname": "Doe"
    }
  }'

Request Body

FieldTypeRequiredDescription
meetingTypeIdstringYesMeeting type UUID
startstringYesStart time (ISO 8601 with timezone)
hostIdsstring[]Yes*Host user UUIDs
queueIdstringYes*Queue ID for round-robin (alternative to hostIds)
attendeeobjectYesAttendee information
durationnumberNoDuration in minutes (for multi-duration meeting types)
channelstringNoVideo platform: zoom, google_meet, teams, whereby, phone, in_person
locationstringNoLocation for in-person meetings
skipNotificationsbooleanNoSkip email notifications (default: false)
*Either hostIds or queueId is required

Attendee Object

FieldTypeRequiredDescription
emailstringYesAttendee email
firstnamestringNoFirst name
lastnamestringNoLast name
phonestringNoPhone number
companystringNoCompany name
customFieldsobjectNoCustom field values

Response (Standard)

{
  "appointmentId": "appt-uuid-12345",
  "secret": "secret-token-xyz"
}
Store the secret to cancel or reschedule without authentication.

Response (Double Opt-In)

If the meeting type requires email confirmation:
{
  "bookingType": "DoubleOptIn",
  "provisionalBookingId": "provisional-uuid-123"
}
The booking is finalized after the attendee confirms via email.

Get Appointments

Get Paginated Appointments

curl -X GET "https://api.meetergo.com/v4/appointment/paginated/?page=1&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-meetergo-api-user-id: {userId}"

Get Single Appointment

curl -X GET "https://api.meetergo.com/v4/appointment/{appointmentId}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "x-meetergo-api-user-id: {userId}"

Response

{
  "id": "appt-uuid-12345",
  "start": "2024-01-15T09:00:00+01:00",
  "end": "2024-01-15T09:30:00+01:00",
  "isCancelled": false,
  "meetingType": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "name": "Discovery Call",
    "duration": 30
  },
  "attendees": [
    {
      "id": "att-uuid-789",
      "email": "[email protected]",
      "firstname": "Jane",
      "lastname": "Doe"
    }
  ],
  "hosts": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "email": "[email protected]",
      "givenName": "John",
      "familyName": "Smith"
    }
  ]
}

Cancel an Appointment

As Host (Authenticated)

curl -X POST "https://api.meetergo.com/booking/cancel/{appointmentId}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cancellationReason": "Unable to attend"
  }'

With Secret (Unauthenticated)

For self-service cancellation by attendees:
curl -X POST "https://api.meetergo.com/booking/confirm/cancel/{appointmentId}/{secret}" \
  -H "Content-Type: application/json" \
  -d '{
    "cancellationReason": "Schedule conflict"
  }'
Both methods trigger:
  • Cancellation emails to all parties
  • booking_cancelled webhook event
  • Calendar event removal (if integrated)

Reschedule an Appointment

With Secret (Unauthenticated)

curl -X POST "https://api.meetergo.com/booking/confirm/reschedule/" \
  -H "Content-Type: application/json" \
  -d '{
    "appointmentId": "appt-uuid-12345",
    "secret": "secret-token-xyz",
    "start": "2024-01-16T10:00:00+01:00"
  }'

As Host (Authenticated)

curl -X POST "https://api.meetergo.com/booking/reschedule/{appointmentId}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "start": "2024-01-16T10:00:00+01:00"
  }'

Response

{
  "appointmentId": "appt-uuid-12345",
  "secret": "secret-token-xyz"
}
Rescheduling triggers:
  • Updated calendar invites
  • Notification emails
  • booking_rescheduled webhook event

Custom Fields

Pass custom data with bookings:
{
  "meetingTypeId": "770e8400-e29b-41d4-a716-446655440002",
  "start": "2024-01-15T09:00:00+01:00",
  "hostIds": ["550e8400-e29b-41d4-a716-446655440000"],
  "attendee": {
    "email": "[email protected]",
    "firstname": "Jane",
    "customFields": {
      "company_size": "50-200",
      "referral_source": "Google",
      "use_case": "Sales scheduling"
    }
  }
}
Custom fields are:
  • Included in webhook payloads
  • Visible in the dashboard
  • Synced to CRM integrations

Round-Robin Bookings

For team meeting types, use queueId instead of hostIds:
{
  "meetingTypeId": "770e8400-e29b-41d4-a716-446655440002",
  "start": "2024-01-15T09:00:00+01:00",
  "queueId": "queue-uuid-123",
  "attendee": {
    "email": "[email protected]"
  }
}
The system automatically selects the next available team member based on:
  • Round-robin rotation
  • Current availability
  • Existing bookings

Error Handling

Time Slot Unavailable

{
  "statusCode": 400,
  "message": "The selected time slot is no longer available",
  "error": "Bad Request"
}
Solution: Query fresh availability and select another slot.

Invalid Duration

{
  "statusCode": 400,
  "message": "Duration must match one of the allowed durations for this meeting type",
  "error": "Bad Request"
}
Solution: Check the meeting type’s allowed durations.

Missing Host

{
  "statusCode": 400,
  "message": "hostIds or queueId is required",
  "error": "Bad Request"
}
Solution: Provide either hostIds array or queueId.

Best Practices

Always query availability first - Don’t book without checking available slots
Store the secret - You’ll need it for self-service cancel/reschedule
Handle race conditions - Slots can be booked between availability query and booking
Use webhooks - Get real-time notifications instead of polling
Time format - Always include timezone offset in ISO 8601 format (e.g., +01:00)