# createAppointment

Create an appointment: title, timezone, startDate, endDate; optional location, description, contactIds (accessible to the key owner), participant userIds (listTeammates), appointmentReminderWorkflowGroupId (listAppointmentReminders; null = no texts to contacts, but participants' 15-minute alert still follows their notification settings; this API applies no org default, so to give it the default pass the isGlobal one's id). By default it is ALSO created on a connected Google/Microsoft calendar, which is what invites the participants and linked contacts as guests: the key owner's, EXCEPT when userIds names exactly one teammate and not the key owner, then that teammate's, as organizer. createCalendarEvent: false keeps it inside Goliath. ALWAYS read calendarSync before telling anyone it is booked: SYNCED = the event exists and guests were invited, the only state where an invite went out (else say it was recorded, not sent); NOT_REQUESTED = Goliath-only; SKIPPED_NO_ACCESS = no connected calendar could be written; SKIPPED_WRITE_BLOCKED = a provider was reachable but deliberately not written; FAILED = the provider errored and the calendar may be stale. Confirm first: title, day, time, zone, participants, contacts and, with a calendar event, whose calendar (it invites them). Double-booking is allowed and nothing here warns, so run checkAvailability FIRST over the same window with every userId plus the key owner (getMyProfile; unless userIds is exactly one teammate without the key owner: then that teammate, the organizer, alone) and show its conflicts. listAppointments is NOT a conflict check: it sees ONLY Goliath appointments. A connected calendar's event lands there only when it already maps to a Goliath appointment, is an out-of-office blocker, or has an attendee whose email matches a CRM contact; everything else (a busy event whose attendees are not contacts, a free/transparent event, any calendar never connected) is never ingested and is invisible here, and a MEMBER key sees only its own rows. So a clear listAppointments window means the GOLIATH calendar looks clear, never that the time is free; even after a clean checkAvailability, say no conflicts were found rather than that the slot is free.

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

## Variables

- `title`: `String!` (required)
- `timezone`: `Timezone!` (required, 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!` (required)
- `endDate`: `DateTime!` (required)
- `location`: `String`
- `description`: `String`
- `contactIds`: `[ID!]`
- `userIds`: `[String!]`
- `createCalendarEvent`: `Boolean`
- `appointmentReminderWorkflowGroupId`: `ID`

## Response (data, an example)

```json
{
  "tasksMutation": {
    "createAppointment": {
      "id": "<ID>",
      "title": "…",
      "startDate": "2026-01-01T00:00:00.000Z",
      "endDate": "2026-01-01T00:00:00.000Z",
      "timezone": "IDLW",
      "location": "…",
      "description": "…",
      "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": "createAppointment",
    "variables": {
      "title": "<String>",
      "timezone": "IDLW",
      "startDate": "2026-01-01T00:00:00.000Z",
      "endDate": "2026-01-01T00:00:00.000Z"
    }
  }'
```
