updateAppointment
This interface updates an existing appointment in the connected CRM. It is called when a user edits an appointment from within App Connect's appointment panel.
Input parameters
| Parameter | Description |
|---|---|
user |
An object describing the Chrome extension user associated with the action that triggered this interface. |
authHeader |
The HTTP Authorization header to be transmitted with the API request to the target CRM. |
appointmentId |
The CRM ID of the appointment to update. |
patchBody |
An object containing the fields to update. See Patch body schema. |
Patch body schema
| Property | Type | Description |
|---|---|---|
title |
string | New title for the appointment. |
summary |
string | New notes or body text. |
startTimeUtc |
string | Updated ISO-8601 UTC start time. |
durationMinutes |
number | Updated duration in minutes. |
contacts |
array | (Optional) Replacement list of attendee IDs or contact objects. When provided, existing attendees not in this list are removed. |
Return value(s)
An object with the following property:
| Parameter | Description |
|---|---|
appointment |
The full updated appointment object. |
If the appointment cannot be found or updated, return:
| Parameter | Description |
|---|---|
successful |
false |
returnMessage |
An object with message, messageType, and ttl. |
Example
return {
appointment: {
id: "12345",
thirdPartyAppointmentId: "12345",
title: "Updated intake call",
description: "Rescheduled",
startTimeUtc: "2024-03-16T10:00:00.000Z",
durationMinutes: 30,
status: "scheduled",
contactId: "",
attendees: []
}
};
Reference
const startAt = payload?.startTimeUtc ?? payload?.startTime ?? null;
const durationMinutes = Number(payload?.durationMinutes ?? 0);
const endAt = startAt ? moment.utc(startAt).add(durationMinutes, 'minutes').toISOString() : null;
const toAttendee = (id) => {
const n = typeof id === 'number' ? id : Number(id);
if (!Number.isFinite(n)) return null;
return { id: n, type: 'Contact' };
};
const attendees = (() => {
if (Array.isArray(payload?.contacts) && payload.contacts.length) {
return payload.contacts
.map(c => (c && typeof c === 'object' ? toAttendee(c.id) : toAttendee(c)))
.filter(Boolean);
}
return [];
})();
const data = {
calendar_owner: { id: calendarId },
summary: payload?.title ?? payload?.summary ?? 'Appointment',
description: payload?.summary ?? '',
start_at: startAt,
end_at: endAt,
send_email_notification: false,
...(attendees.length ? { attendees } : {})
};
const body = { data };
const createRes = await axios.post(
`https://${user.hostname}/api/v4/calendar_entries.json`,
body,
{ headers: { 'Authorization': authHeader }, params: { fields: 'id,summary,description,start_at,end_at,attendees,external_properties,calendar_owner_id' } }
);
const calendarEntry = createRes?.data?.data ?? null;
const appointment = normalizeCalendarEntryToAppointment(calendarEntry);
return { appointmentId: appointment.id, appointment };
}
async function updateAppointment({ user, authHeader, appointmentId, patchBody }) {
const hasPatchField = (field) => Object.prototype.hasOwnProperty.call(patchBody ?? {}, field);
const hasSupportedMutation = ['title', 'summary', 'startTimeUtc', 'startTime', 'contacts']
.some(hasPatchField);
if (hasPatchField('status') && !hasSupportedMutation) {
return {
successful: false,
returnMessage: {
message: 'Clio does not support appointment status changes.',
messageType: 'warning',
ttl: 5000
}
};
}
const existing = await getCalendarEntryById({ user, authHeader, appointmentId });
if (!existing) {
return {
successful: false,
returnMessage: {
message: 'Appointment not found in Clio.',
messageType: 'warning',
ttl: 5000
}
};
}
const existingAttendees = existing?.attendees ?? [];
const hasStartUpdate = hasPatchField('startTimeUtc') || hasPatchField('startTime');
const startAt = hasStartUpdate ? patchBody?.startTimeUtc ?? patchBody?.startTime ?? null : null;
const durationMinutes = Number(patchBody?.durationMinutes ?? 0);
const endAt = hasStartUpdate && startAt
? moment.utc(startAt).add(durationMinutes, 'minutes').toISOString()
: null;
const toAttendee = (id) => {
const n = typeof id === 'number' ? id : Number(id);
if (!Number.isFinite(n)) return null;
return { id: n, type: 'Contact' };
};
const hasAttendeeUpdate = hasPatchField('contacts') && Array.isArray(patchBody?.contacts);