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
| Field | Type | Required | Description |
|---|
meetingTypeId | string | Yes | Meeting type UUID |
start | string | Yes | Start time (ISO 8601 with timezone) |
hostIds | string[] | Yes* | Host user UUIDs |
queueId | string | Yes* | Queue ID for round-robin (alternative to hostIds) |
attendee | object | Yes | Attendee information |
duration | number | No | Duration in minutes (for multi-duration meeting types) |
channel | string | No | Video platform: zoom, google_meet, teams, whereby, phone, in_person |
location | string | No | Location for in-person meetings |
skipNotifications | boolean | No | Skip email notifications (default: false) |
*Either hostIds or queueId is required
Attendee Object
| Field | Type | Required | Description |
|---|
email | string | Yes | Attendee email |
firstname | string | No | First name |
lastname | string | No | Last name |
phone | string | No | Phone number |
company | string | No | Company name |
customFields | object | No | Custom 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)