updateAppointment
Update an appointment by id.
Update an appointment by id (listAppointments): title, times, location, description, outcome; addUserIds/removeUserIds, addContactIds/removeContactIds; switch or clear the reminder with appointmentReminderWorkflowGroupId (omit = unchanged, null = clear). Only passed fields change. It must belong to your organization. Before moving startDate/endDate, run checkAvailability over the NEW window with the RESULTING participants (the FULL existing participants from listAppointments, minus any removeUserIds plus any addUserIds, never just the additions) plus the key owner (getMyProfile), ALWAYS on an update, with no single-teammate exception here: update-time sync runs as the key owner, and a missing event created with createCalendarEvent: true lands on THEIR calendar. Set excludeAppointmentId to this appointment and show conflicts. If the windows overlap and the key owner organizes without being a participant, the appointment's own mirror can appear as a conflict at the OLD time: treat it as AMBIGUOUS (merged busy ranges can hide a real event), tell the user, and let them confirm against their calendar. The edit is pushed to the external event when there is one. With none, createCalendarEvent: true creates it (how an appointment whose sync never landed reaches a calendar), on the key owner's calendar with them as organizer; it is opt-in, since a missing event may mean it was deliberately kept in Goliath, so only ask for it when that is the right host. Read calendarSync as on createAppointment: only SYNCED means the calendar matches; a reschedule that comes back SKIPPED_NO_ACCESS or FAILED left guests' calendars at the OLD time: say so instead of reporting it moved.
curl https://server.goliathdata.com/api/v1/call \
-H "Authorization: Bearer $GOLIATH_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"operationId": "updateAppointment",
"variables": {
"appointmentId": "<appointmentId>"
}
}'import { GoliathClient } from '@goliath-data/sdk'
const goliath = new GoliathClient({
apiKey: process.env.GOLIATH_API_KEY!,
baseUrl: 'https://server.goliathdata.com',
})
const result = await goliath.appointments.updateAppointment(
{
appointmentId: '<appointmentId>'
},
{ idempotencyKey: crypto.randomUUID() },
)const res = await fetch('https://server.goliathdata.com/api/v1/call', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GOLIATH_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
operationId: 'updateAppointment',
variables: {
appointmentId: '<appointmentId>'
}
}),
})
const { data, errors } = await res.json()Variables
The example sends only what the schema requires. Some operations also need one of several optional variables (one filter or another, say); the description above says which.
AZ: Arizona: MST all year, no DST.
Response
What comes back under data: a list shows as one entry, and a value as its type.
{
"data": {
"tasksMutation": {
"updateAppointment": {
"id": "<ID>",
"title": "…",
"startDate": "2026-01-01T00:00:00.000Z",
"endDate": "2026-01-01T00:00:00.000Z",
"timezone": "IDLW",
"location": "…",
"description": "…",
"outcome": "…",
"appointmentReminderWorkflowGroupId": "<ID>",
"calendarSync": {
"status": "SYNCED",
"provider": "GOOGLE"
},
"participants": [
{
"id": "<ID>",
"firstName": "…",
"lastName": "…"
}
],
"contacts": [
{
"id": "<ID>",
"name": "…"
}
]
}
}
}
}Errors
unknown_variableA variable the operation does not declare. A typo is refused rather than silently dropped.
unauthorizedNo bearer header, or the key is invalid or revoked.
insufficient_scopeThe key lacks the scope the operation requires.
forbiddenA referenced record does not exist, was deleted, or is outside your organization. The gateway cannot tell those apart.
idempotency_conflictA request with this Idempotency-Key is still in flight.
Idempotency
Send an Idempotency-Key of 1 to 255 characters. A finished request retried with the same key replays its stored response, marked Idempotency-Replayed: true; one still in flight returns 409 idempotency_conflict. Keys expire after 24 hours. Write without fear →