Learn how to reschedule and cancel bookings programmatically.
Get Booking Details
Before modifying a booking, retrieve its current state:
const response = await fetch(
`https://api.meetergo.com/v4/appointment/${appointmentId}`,
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-meetergo-api-user-id': userId
}
}
);
const booking = await response.json();
Rescheduling
Check Availability for Reschedule
When rescheduling, pass the existing appointment ID to exclude the current slot from conflict checking:
const response = await fetch(
`https://api.meetergo.com/v4/booking-availability?` + new URLSearchParams({
meetingTypeId: booking.meetingTypeId,
start: '2024-01-20',
end: '2024-01-27',
existingAppointmentId: appointmentId // Excludes current booking from conflicts
}),
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-meetergo-api-user-id': userId
}
}
);
const { availableSlots } = await response.json();
Reschedule via Booking Endpoint
Create a new booking and cancel the old one:
async function rescheduleBooking(oldBookingId, newStart) {
// 1. Get old booking details
const oldBooking = await getBooking(oldBookingId);
// 2. Create new booking
const newBooking = await fetch('https://api.meetergo.com/v4/booking', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-meetergo-api-user-id': userId
},
body: JSON.stringify({
meetingTypeId: oldBooking.meetingTypeId,
start: newStart,
hostIds: oldBooking.hosts.map(h => h.id),
attendee: {
email: oldBooking.attendees[0].email,
fullname: oldBooking.attendees[0].fullname,
phone: oldBooking.attendees[0].phone
},
// Link to original booking for tracking
rescheduledFromId: oldBookingId
})
});
// 3. Cancel old booking
await cancelBooking(oldBookingId, 'Rescheduled to new time');
return newBooking.json();
}
Cancellation
Cancel a Booking
await fetch(`https://api.meetergo.com/v4/appointment/${appointmentId}`, {
method: 'DELETE',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-meetergo-api-user-id': userId
}
});
Cancel with Reason
Include cancellation reason for tracking:
await fetch(`https://api.meetergo.com/v4/appointment/${appointmentId}`, {
method: 'DELETE',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-meetergo-api-user-id': userId
},
body: JSON.stringify({
reason: 'Customer requested cancellation',
notifyAttendees: true
})
});
Handling via Webhooks
React to reschedule and cancellation events:
app.post('/webhooks/meetergo', async (req, res) => {
res.status(200).send('OK');
const { event, data } = req.body;
switch (event) {
case 'booking_rescheduled':
await handleReschedule(data);
break;
case 'booking_cancelled':
await handleCancellation(data);
break;
}
});
async function handleReschedule(data) {
const { rescheduledAppointment, oldStartDate, oldEndDate } = data;
console.log(`Booking rescheduled from ${oldStartDate} to ${rescheduledAppointment.start}`);
// Update your systems
await db.bookings.update({
where: { meetergoId: rescheduledAppointment.id },
data: {
start: rescheduledAppointment.start,
end: rescheduledAppointment.end,
rescheduledAt: new Date(),
previousStart: oldStartDate
}
});
// Update calendar
await updateCalendarEvent(rescheduledAppointment);
// Notify internal systems
await notifyTeam('booking_rescheduled', rescheduledAppointment);
}
async function handleCancellation(data) {
const { id, cancel } = data;
console.log(`Booking ${id} cancelled: ${cancel?.reason || 'No reason'}`);
// Update your systems
await db.bookings.update({
where: { meetergoId: id },
data: {
status: 'cancelled',
cancelledAt: cancel?.cancelledAt || new Date(),
cancellationReason: cancel?.reason
}
});
// Remove from calendar
await deleteCalendarEvent(id);
// Free up resources
await releaseResources(id);
}
No-Shows
Mark attendees who didn’t show up:
await fetch(`https://api.meetergo.com/v4/attendee/${attendeeId}/no-show`, {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-meetergo-api-user-id': userId
}
});
Track no-shows for analytics:
async function handleNoShow(appointmentId, attendeeId) {
// Mark as no-show in meetergo
await fetch(`https://api.meetergo.com/v4/attendee/${attendeeId}/no-show`, {
method: 'POST',
headers
});
// Track in your analytics
await db.bookings.update({
where: { meetergoId: appointmentId },
data: {
status: 'no_show',
noShowAt: new Date()
}
});
// Update CRM
await updateCrmContact(attendeeId, {
lastNoShow: new Date(),
noShowCount: { increment: 1 }
});
}
Update Booking Notes
Add or update notes on a booking:
await fetch(`https://api.meetergo.com/v4/appointment/${appointmentId}/notes`, {
method: 'PATCH',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-meetergo-api-user-id': userId
},
body: JSON.stringify({
notes: 'Customer mentioned they need accessibility accommodations'
})
});
Add/Remove Guests
Add Guest Emails
await fetch(`https://api.meetergo.com/v4/appointment/${appointmentId}/guests`, {
method: 'PATCH',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-meetergo-api-user-id': userId
},
body: JSON.stringify({
guestEmails: ['[email protected]', '[email protected]']
})
});
Remove Guest
await fetch(
`https://api.meetergo.com/v4/appointment/${appointmentId}/guest/${encodeURIComponent(guestEmail)}`,
{
method: 'DELETE',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-meetergo-api-user-id': userId
}
}
);
Common Patterns
Self-Service Reschedule Link
Generate a reschedule link for attendees:
function generateRescheduleLink(booking) {
const baseUrl = 'https://cal.meetergo.com';
const params = new URLSearchParams({
reschedule: booking.id,
email: booking.attendees[0].email
});
return `${baseUrl}/${booking.companySlug}/${booking.meetingTypeSlug}?${params}`;
}
// Send to attendee
const rescheduleLink = generateRescheduleLink(booking);
await sendEmail(booking.attendees[0].email, {
subject: 'Need to reschedule?',
body: `Click here to pick a new time: ${rescheduleLink}`
});
Cancellation with Refund
async function cancelWithRefund(appointmentId, refundReason) {
// 1. Get booking with payment info
const booking = await getBooking(appointmentId);
// 2. Process refund if paid
if (booking.payment?.status === 'paid') {
await processRefund(booking.payment.id, refundReason);
}
// 3. Cancel the booking
await fetch(`https://api.meetergo.com/v4/appointment/${appointmentId}`, {
method: 'DELETE',
headers,
body: JSON.stringify({
reason: refundReason,
notifyAttendees: true
})
});
}
Bulk Cancellation
Cancel multiple bookings (e.g., host unavailable):
async function cancelBookingsInRange(userId, startDate, endDate, reason) {
// 1. Get all bookings in range
const response = await fetch(
`https://api.meetergo.com/v4/appointment/paginated?` + new URLSearchParams({
page: 1,
pageSize: 100,
userId: userId,
startDate: startDate,
endDate: endDate
}),
{ headers }
);
const { appointments } = await response.json();
// 2. Cancel each booking
const results = await Promise.allSettled(
appointments.map(apt =>
fetch(`https://api.meetergo.com/v4/appointment/${apt.id}`, {
method: 'DELETE',
headers,
body: JSON.stringify({ reason, notifyAttendees: true })
})
)
);
const cancelled = results.filter(r => r.status === 'fulfilled').length;
console.log(`Cancelled ${cancelled} of ${appointments.length} bookings`);
return results;
}
Best Practices
Always notify attendees - Set notifyAttendees: true for cancellations
Track reasons - Store cancellation/reschedule reasons for analytics
Handle webhooks idempotently - Same event may be delivered multiple times
Use existingAppointmentId - When checking availability for reschedule
Cancellation is permanent - There’s no undo; create a new booking if needed
Next Steps