# updateAppointment

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.

- Call: `POST https://server.goliathdata.com/api/v1/call` with `{ "operationId": "updateAppointment", "variables": {...} }`
- Scope: `WRITE`
- Type: mutation
- Idempotency: honors `Idempotency-Key` (24 h)
- Rate-limited: no

## Variables

- `appointmentId`: `ID!` (required)
- `title`: `String`
- `timezone`: `Timezone` (one of `IDLW`, `SST`, `HST`, `AKST`, `PST`, `MST`, `AZ`, `CST`, `EST`, `AST`, `BRT`, `FNT`, `AZOT`, `UTC`, `CET`, `EET`, `MSK`, `GST`, `PKT`, `BST`, `ICT`, `JST`, `AEST`, `NCT`, `NZST`). AZ: Arizona: MST all year, no DST.
- `startDate`: `DateTime`
- `endDate`: `DateTime`
- `location`: `String`
- `description`: `String`
- `outcome`: `String`
- `addUserIds`: `[String!]`
- `removeUserIds`: `[String!]`
- `addContactIds`: `[ID!]`
- `removeContactIds`: `[ID!]`
- `createCalendarEvent`: `Boolean`
- `appointmentReminderWorkflowGroupId`: `ID`

## Response (data, an example)

```json
{
  "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": "…"
        }
      ]
    }
  }
}
```

## Example

```bash
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>"
    }
  }'
```
