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

# Managing Events

> List, filter, inspect, cancel, and hand over scheduled events with the Zeeg API. Includes filtering by host, team, status, and date range.

The Zeeg API gives you full control over scheduled events in your workspace. You can list events with powerful filters, retrieve detailed event information, cancel events or individual invitees, and hand over Round Robin events to a different host.

## Listing events

Retrieve a paginated list of scheduled events with `GET /scheduled-events`. Use query parameters to filter and sort the results.

### Available filters

| Parameter | Type | Description |
| - | - | - |
| `status` | string | Filter by event status: `confirmed` or `cancelled` |
| `minStartTime` | ISO 8601 | Only return events starting at or after this time |
| `maxStartTime` | ISO 8601 | Only return events starting at or before this time |
| `userSlug` | string | Filter by the host's user slug |
| `hostEmail` | string | Filter by the host's email address |
| `inviteeEmail` | string | Filter by an invitee's email address |
| `teamSlug` | string | Filter by team slug |
| `keyword` | string | Search invitee names, invitee emails, booking question answers, and custom query parameter values |
| `sort` | string | Sort by start time: `asc` (default) or `desc` |
| `scope` | string | Set to `all` to list events across the entire organization (requires an admin or owner token with `admin:full` scope) |

### Example: filter by date range and status

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.zeeg.me/v2/scheduled-events?status=confirmed&minStartTime=2026-04-01T00:00:00Z&maxStartTime=2026-04-30T23:59:59Z&sort=asc" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json"
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://api.zeeg.me/v2/scheduled-events",
      params={
          "status": "confirmed",
          "minStartTime": "2026-04-01T00:00:00Z",
          "maxStartTime": "2026-04-30T23:59:59Z",
          "sort": "asc",
      },
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Accept": "application/json",
      },
  )

  data = response.json()
  ```

  ```javascript JavaScript theme={null}
  const params = new URLSearchParams({
    status: "confirmed",
    minStartTime: "2026-04-01T00:00:00Z",
    maxStartTime: "2026-04-30T23:59:59Z",
    sort: "asc",
  });

  const response = await fetch(
    `https://api.zeeg.me/v2/scheduled-events?${params}`,
    {
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        Accept: "application/json",
      },
    }
  );

  const data = await response.json();
  ```
</CodeGroup>

To list events across your entire organization, add `scope=all`. This requires a token with the `admin:full` scope.

```bash theme={null}
curl -X GET "https://api.zeeg.me/v2/scheduled-events?scope=all" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Accept: application/json"
```

## Getting event details

Retrieve full details for a single event with `GET /scheduled-events/{uuid}`. Event UUIDs follow the format `zg-XXX` (for example, `zg-O69bac566950c6`).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.zeeg.me/v2/scheduled-events/zg-O69bac566950c6" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json"
  ```

  ```python Python theme={null}
  import requests

  event_uuid = "zg-O69bac566950c6"

  response = requests.get(
      f"https://api.zeeg.me/v2/scheduled-events/{event_uuid}",
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Accept": "application/json",
      },
  )

  event = response.json()
  ```

  ```javascript JavaScript theme={null}
  const eventUuid = "zg-O69bac566950c6";

  const response = await fetch(
    `https://api.zeeg.me/v2/scheduled-events/${eventUuid}`,
    {
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        Accept: "application/json",
      },
    }
  );

  const event = await response.json();
  ```
</CodeGroup>

### Example response

```json theme={null}
{
  "resource": {
    "uri": "https://api.zeeg.me/v2/scheduled-events/zg-O69bac566950c6",
    "uuid": "zg-O69bac566950c6",
    "title": "30-Minute Discovery Call",
    "type": "ONE_ON_ONE",
    "startTime": "2026-04-15T09:00:00.000000Z",
    "endTime": "2026-04-15T09:30:00.000000Z",
    "duration": 30,
    "status": "confirmed",
    "eventTypeUri": "https://api.zeeg.me/v2/event-types/80f46bf5-eb01-4c07-960e-a9a3e18aae5e",
    "maxActiveInvitees": 1,
    "activeInviteesCount": 1,
    "location": {
      "type": "Google Meet",
      "joinUrl": "https://meet.google.com/abc-defg-hij"
    },
    "invitees": [
      {
        "uuid": "zg-O69bad4047abf0",
        "salutation": "Ms.",
        "fullName": "Sophie Laurent",
        "email": "sophie.laurent@northwind.io",
        "guests": ["alex.chen@northwind.io"],
        "timeZone": "Europe/Paris",
        "questions": [
          {
            "answer": "Product demo and pricing options",
            "answer_type": "STRING",
            "question": "What would you like to discuss?"
          }
        ],
        "scheduledAt": "2026-04-10T08:30:00.000000Z",
        "utm": {
          "utm_campaign": "spring_launch",
          "utm_source": "linkedin",
          "utm_medium": "social",
          "utm_content": null,
          "utm_term": null
        },
        "customQueryParams": {
          "c__ref": "nl-2026-04"
        }
      }
    ],
    "hosts": [
      {
        "firstName": "Lena",
        "lastName": "Meier",
        "email": "lena.meier@horizondigital.de",
        "slug": "lena-meier",
        "url": "https://zeeg.me/lena-meier",
        "avatarUrl": null
      }
    ],
    "teamName": "Sales",
    "createdAt": "2026-04-10T08:30:00.000000Z",
    "updatedAt": "2026-04-10T08:30:02.000000Z"
  }
}
```

<Note>
  `customQueryParams`, `utm`, `guests`, and `teamName` each keep one JSON shape on every response from every scheduled-event endpoint. `customQueryParams` is always an object. If the booking captured no custom parameters, the object is empty (`{}`). `utm` is always an object with all five keys (`utm_campaign`, `utm_source`, `utm_medium`, `utm_term`, `utm_content`). If the booking did not carry a value for a key, that key holds `null`. `guests` is always an array. If the invitee added no guests, the array is empty (`[]`). `teamName` is always present. If the booking was made on a personal scheduling page, it holds `null`. It carries the same value the `invitee.scheduled` webhook sends for that booking, so you can recover the team after a missed delivery. Check for the empty value directly (`{}`, `[]`, or a `null` key) instead of testing the type.
</Note>

## Cancelling events

Cancel a scheduled event with `PUT /scheduled-events/{uuid}/cancel`. You can optionally include a `cancellationReason` (maximum 512 characters) that will be shared with participants.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT "https://api.zeeg.me/v2/scheduled-events/zg-O69bac566950c6/cancel" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -d '{"cancellationReason": "Scheduling conflict — will rebook next week."}'
  ```

  ```python Python theme={null}
  import requests

  event_uuid = "zg-O69bac566950c6"

  response = requests.put(
      f"https://api.zeeg.me/v2/scheduled-events/{event_uuid}/cancel",
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Accept": "application/json",
          "Content-Type": "application/json",
      },
      json={
          "cancellationReason": "Scheduling conflict — will rebook next week."
      },
  )
  ```

  ```javascript JavaScript theme={null}
  const eventUuid = "zg-O69bac566950c6";

  const response = await fetch(
    `https://api.zeeg.me/v2/scheduled-events/${eventUuid}/cancel`,
    {
      method: "PUT",
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        cancellationReason: "Scheduling conflict — will rebook next week.",
      }),
    }
  );
  ```
</CodeGroup>

A successful cancellation returns a `200` response confirming the operation.

```json theme={null}
{
  "success": true,
  "message": "Event cancelled successfully.",
  "status": 200
}
```

<Warning>
  Attempting to cancel an event that is already cancelled will return a `400 Bad Request` error. Check the event's `status` field before making the request if you need to handle this case gracefully.
</Warning>

## Cancelling individual invitees

For group events where you need to remove a single attendee without cancelling the entire event, use `PUT /scheduled-invitees/{uuid}/cancel`. The invitee UUID can be found in the event details response.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT "https://api.zeeg.me/v2/scheduled-invitees/zg-O69bad4047abf0/cancel" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -d '{"cancellationReason": "Attendee can no longer make it."}'
  ```

  ```python Python theme={null}
  import requests

  invitee_uuid = "zg-O69bad4047abf0"

  response = requests.put(
      f"https://api.zeeg.me/v2/scheduled-invitees/{invitee_uuid}/cancel",
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Accept": "application/json",
          "Content-Type": "application/json",
      },
      json={
          "cancellationReason": "Attendee can no longer make it."
      },
  )
  ```

  ```javascript JavaScript theme={null}
  const inviteeUuid = "zg-O69bad4047abf0";

  const response = await fetch(
    `https://api.zeeg.me/v2/scheduled-invitees/${inviteeUuid}/cancel`,
    {
      method: "PUT",
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        cancellationReason: "Attendee can no longer make it.",
      }),
    }
  );
  ```
</CodeGroup>

## Marking no-shows

When an invitee doesn't turn up, mark them as a no-show with `POST /scheduled-invitees/{uuid}/no-show`. It has the same effect as marking them in the dashboard: workflows triggered by a no-show run, the CRM records the missed meeting, and webhooks subscribed to `invitee.no_show` receive the invitee. The response is the invitee, with `noShow: true` and the `noShowAt` timestamp.

<CodeGroup>
  ```bash Mark theme={null}
  curl -X POST "https://api.zeeg.me/v2/scheduled-invitees/zg-O69bad4047abf0/no-show" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json"
  ```

  ```bash Undo theme={null}
  curl -X DELETE "https://api.zeeg.me/v2/scheduled-invitees/zg-O69bad4047abf0/no-show" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json"
  ```
</CodeGroup>

* The booking must have started. Marking earlier, or marking an invitee whose seat is cancelled, rescheduled or unconfirmed, returns `422`.
* Both calls are safe to repeat: marking a marked invitee, or undoing an unmarked one, returns the invitee unchanged.
* Undoing a marking cancels no-show workflow steps that haven't run yet. It sends no webhook, and it doesn't restore workflow steps the marking cancelled.

## Handing over events

Transfer a Round Robin event to a different host with `PUT /scheduled-events/{uuid}/handover`. You can specify the new host explicitly or let the system auto-assign one based on the Round Robin rules.

### Options

| Parameter | Type | Default | Description |
| - | - | - | - |
| `newHostEmail` | string | — | Email of the new host. If omitted, the system auto-assigns using Round Robin logic. |
| `requireHostAvailability` | boolean | `true` | When `true`, the handover only succeeds if the new host is free at the event time. |
| `fallbackToReschedule` | boolean | `false` | When `true` and the booking cannot move in place (it sits in a calendar other than Microsoft, or its location is Zoom, Webex or Demodesk), reschedules it to the new host at the same time instead of failing. It does not help when the new host is busy. |

A booking that moves in place emails the new host, with the booking details and who it came from, and tells the previous host it is no longer theirs. The invitee receives no email, and nothing is sent when the event type turns host emails off. A booking rescheduled through `fallbackToReschedule` sends the usual reschedule emails to the invitee and the hosts instead.

<Warning>
  `fallbackToReschedule: true` goes through a reschedule, so the booking gets a new event `uuid` and a new invitee `uuid`. Keep the default `false` if your integration stores the identifiers it already holds.
</Warning>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT "https://api.zeeg.me/v2/scheduled-events/zg-O69bac566950c6/handover" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json" \
    -H "Content-Type: application/json" \
    -d '{
      "newHostEmail": "marco.rossi@horizondigital.de",
      "requireHostAvailability": true,
      "fallbackToReschedule": true
    }'
  ```

  ```python Python theme={null}
  import requests

  event_uuid = "zg-O69bac566950c6"

  response = requests.put(
      f"https://api.zeeg.me/v2/scheduled-events/{event_uuid}/handover",
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Accept": "application/json",
          "Content-Type": "application/json",
      },
      json={
          "newHostEmail": "marco.rossi@horizondigital.de",
          "requireHostAvailability": True,
          "fallbackToReschedule": True,
      },
  )
  ```

  ```javascript JavaScript theme={null}
  const eventUuid = "zg-O69bac566950c6";

  const response = await fetch(
    `https://api.zeeg.me/v2/scheduled-events/${eventUuid}/handover`,
    {
      method: "PUT",
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        newHostEmail: "marco.rossi@horizondigital.de",
        requireHostAvailability: true,
        fallbackToReschedule: true,
      }),
    }
  );
  ```
</CodeGroup>

<Warning>
  **Handover limitations.** The handover endpoint currently has the following constraints:

  * **Round Robin only** — handover is only supported for events booked through a Round Robin scheduling page. Other event types will return an error.
  * **Calendar provider** — the host must use a Microsoft calendar or have no calendar connected. Google Calendar is not yet supported for handovers.
  * **No Zoom, Webex or Demodesk locations** — events with a Zoom, Webex or Demodesk meeting location cannot be handed over in place. The meeting link is tied to the original host and cannot be transferred automatically.
</Warning>

## Adding notes to events

You can attach internal notes to scheduled events that are visible only to hosts and workspace members. Notes are useful for adding context before or after a meeting.

See the [Notes API reference](/api/notes/create-a-note) for the full list of endpoints.

## Real-time updates

<Tip>
  Instead of polling `GET /scheduled-events` to detect changes, set up [webhook subscriptions](/guides/webhooks-guide) to receive real-time notifications when events are created, cancelled, rescheduled, or handed over. This is more efficient and gives you near-instant updates.
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.