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

# Rescheduling & Cancellation

> Handle booking changes via the API

Learn how to reschedule and cancel bookings programmatically.

## Get Booking Details

Before modifying a booking, retrieve its current state:

```javascript theme={null}
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:

```javascript theme={null}
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:

```javascript theme={null}
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

```javascript theme={null}
await fetch(`https://api.meetergo.com/v4/appointment/${appointmentId}/cancel`, {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'x-meetergo-api-user-id': userId
  }
});
```

### Cancel with Reason

Include cancellation reason for tracking:

```javascript theme={null}
await fetch(`https://api.meetergo.com/v4/appointment/${appointmentId}/cancel`, {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
    'x-meetergo-api-user-id': userId
  },
  body: JSON.stringify({
    reason: 'Customer requested cancellation'
  })
});
```

## Handling via Webhooks

React to reschedule and cancellation events:

```javascript theme={null}
app.post('/webhooks/meetergo', async (req, res) => {
  res.status(200).send('OK');

  const payload = req.body;

  switch (payload.webhookType) {
    case 'booking_rescheduled':
      await handleReschedule(payload);
      break;
    case 'booking_cancelled':
      await handleCancellation(payload);
      break;
  }
});

async function handleReschedule(data) {
  const { rescheduledAppointment, oldStartDate } = 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(payload) {
  const { id, cancel } = payload;

  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:

```javascript theme={null}
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:

```javascript theme={null}
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:

```javascript theme={null}
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

```javascript theme={null}
await fetch(`https://api.meetergo.com/v4/appointment/${appointmentId}/guest`, {
  method: 'PATCH',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
    'x-meetergo-api-user-id': userId
  },
  body: JSON.stringify({
    guestEmails: ['colleague@example.com', 'manager@example.com']
  })
});
```

### Remove Guest

```javascript theme={null}
await fetch(
  `https://api.meetergo.com/v4/appointment/${appointmentId}/guest`,
  {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
      'x-meetergo-api-user-id': userId
    },
    body: JSON.stringify({
      attendeeId: attendeeId,
      email: guestEmail
    })
  }
);
```

## Common Patterns

### Self-Service Reschedule Link

Generate a reschedule link for attendees:

```javascript theme={null}
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

```javascript theme={null}
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}/cancel`, {
    method: 'POST',
    headers: { ...headers, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      reason: refundReason
    })
  });
}
```

### Bulk Cancellation

Cancel multiple bookings (e.g., host unavailable):

```javascript theme={null}
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}/cancel`, {
        method: 'POST',
        headers: { ...headers, 'Content-Type': 'application/json' },
        body: JSON.stringify({ reason })
      })
    )
  );

  const cancelled = results.filter(r => r.status === 'fulfilled').length;
  console.log(`Cancelled ${cancelled} of ${appointments.length} bookings`);

  return results;
}
```

## Best Practices

<Check>
  **Always notify attendees** - Set `notifyAttendees: true` for cancellations
</Check>

<Check>
  **Track reasons** - Store cancellation/reschedule reasons for analytics
</Check>

<Check>
  **Handle webhooks idempotently** - Same event may be delivered multiple times
</Check>

<Check>
  **Use existingAppointmentId** - When checking availability for reschedule
</Check>

<Warning>
  **Cancellation is permanent** - There's no undo; create a new booking if needed
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Bookings" icon="calendar-check" href="/developer-docs/core-concepts/bookings">
    Create bookings via API
  </Card>

  <Card title="Webhooks" icon="webhook" href="/developer-docs/webhooks/events">
    Handle booking events
  </Card>
</CardGroup>
