> ## 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 Scheduling Pages

> List, inspect, toggle, and issue single-use links for Zeeg scheduling pages programmatically. Provision pages at sign-up, sync from a master config, or generate per-customer booking links.

This guide covers the lifecycle of a scheduling page from the API side — listing what you have, inspecting a single page's configuration, activating or deactivating it, and issuing single-use links to share with specific customers.

If you want to **use** a scheduling page (fetch availability and create a booking), see the [Booking Flow](/guides/booking-flow) guide. This guide is its complement: it covers how you **manage** the pages themselves.

## When to use these endpoints

Typical reasons to manage scheduling pages programmatically:

* **Provisioning at sign-up** — list a newly invited user's pages to confirm they exist before pointing the user at them.
* **Syncing from a master config** — keep an internal source of truth in step with what's published on Zeeg by toggling pages active/inactive as your data changes.
* **Per-customer booking links** — issue a unique, one-time-use link to a specific customer (for example, after a paid signup) so they can only book once.
* **Operational hygiene** — deactivate an employee's scheduling page when they leave; reactivate when they return.

## Prerequisites

* An API token from your [Zeeg dashboard](https://app.zeeg.me/account/settings/api-access). All endpoints in this guide require a Bearer token.
* The `userSlug` filter on listing requires an **organization admin or owner** token.

<Info>
  **Naming.** Zeeg's dashboard calls these "scheduling pages." The API path is `/event-types` for historical reasons. The two terms refer to the same object — this guide uses "scheduling page" in prose and shows the actual `/event-types` path in code samples.
</Info>

## Listing scheduling pages

Retrieve a paginated list of scheduling pages with `GET /event-types`. By default, the response contains pages on which the authenticated user is a host.

### Query parameters

| Parameter  | Type    | Description                                                                               |
| ---------- | ------- | ----------------------------------------------------------------------------------------- |
| `userSlug` | string  | Filter to a specific user's scheduling pages. Requires an organization admin/owner token. |
| `count`    | integer | Items per page. Default `20`, max `100`. See [Pagination](/pagination).                   |
| `page`     | integer | Page number (1-indexed).                                                                  |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.zeeg.me/v2/event-types?count=20&page=1" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json"
  ```

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

  response = requests.get(
      "https://api.zeeg.me/v2/event-types",
      params={"count": 20, "page": 1},
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Accept": "application/json",
      },
  )

  data = response.json()
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.zeeg.me/v2/event-types?" +
      new URLSearchParams({ count: "20", page: "1" }),
    {
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        Accept: "application/json",
      },
    }
  );

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

### Example response

```json theme={null}
{
  "collection": [
    {
      "uri": "https://api.zeeg.me/v2/event-types/80f46bf5-eb01-4c07-960e-a9a3e18aae5e",
      "uuid": "80f46bf5-eb01-4c07-960e-a9a3e18aae5e",
      "title": "30-Minute Discovery Call",
      "type": "ONE_ON_ONE",
      "slug": "30min-discovery-call",
      "schedulingUrl": "https://zeeg.me/lena-meier/30min-discovery-call",
      "isActive": true,
      "duration": 30,
      "profile": {
        "type": "User",
        "firstName": "Lena",
        "lastName": "Meier",
        "slug": "lena-meier",
        "email": "lena.meier@horizondigital.de"
      },
      "color": "2196f3",
      "maxActiveInvitees": 1,
      "inviteeNameFormat": "FULL_NAME",
      "inviteePhoneNumber": false
    }
  ],
  "pagination": {
    "total": 1,
    "count": 1,
    "totalPages": 1,
    "previousPage": null,
    "currentPage": 1,
    "nextPage": null
  }
}
```

The response uses Zeeg's standard pagination envelope. Walk through `pagination.nextPage` until it returns `null` — see [Pagination](/pagination) for the full pattern.

<Tip>
  To audit pages owned by another user in your organization (for example, when offboarding), call `GET /event-types?userSlug=<slug>` with an admin token.
</Tip>

## Getting a single page's details

Fetch a specific scheduling page by UUID with `GET /event-types/{uuid}`. The detail response is richer than the list response — it includes notification settings, the assigned hosts (or Flexi host collections), and the full `inviteeQuestions` array.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.zeeg.me/v2/event-types/80f46bf5-eb01-4c07-960e-a9a3e18aae5e" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json"
  ```

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

  uuid = "80f46bf5-eb01-4c07-960e-a9a3e18aae5e"

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

  page = response.json()["resource"]
  ```

  ```javascript JavaScript theme={null}
  const uuid = "80f46bf5-eb01-4c07-960e-a9a3e18aae5e";

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

  const { resource: page } = await response.json();
  ```
</CodeGroup>

### Fields most integrations care about

| Field                         | Why it matters                                                                                               |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `slug`                        | Used as `eventTypeSlug` when [creating a booking](/guides/booking-flow).                                     |
| `profile.slug`                | Used as `ownerSlug` when creating a booking.                                                                 |
| `isActive`                    | `false` means the page is hidden from public scheduling; bookings will be rejected.                          |
| `duration` / `eventDurations` | Default duration plus any alternative durations the invitee can pick.                                        |
| `inviteePhoneNumber`          | When `true`, bookings against this page must include a `phone` field.                                        |
| `inviteeQuestions`            | Custom questions with their numeric `id`s. Pass answers via `question_answers` when booking.                 |
| `type`                        | `ONE_ON_ONE`, `GROUP`, `ROUND_ROBIN`, `COLLECTIVE`, or `FLEXI`. Shared types use `shared` as the owner slug. |
| `hosts` / `flexiCollections`  | Assigned hosts. `hosts` is populated for everything except FLEXI pages.                                      |
| `notifications`               | Per-page email and calendar invite behaviour.                                                                |

For the complete schema, see the [Get a scheduling page](/api/scheduling-pages/get-a-scheduling-page) API reference.

## Toggling active/inactive

Send `PUT /event-types/{uuid}/status` to flip a page's active state. The endpoint takes no body — it toggles whatever the current state is. Active pages accept bookings; inactive pages do not appear at the public URL and reject API bookings.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT "https://api.zeeg.me/v2/event-types/80f46bf5-eb01-4c07-960e-a9a3e18aae5e/status" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json"
  ```

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

  uuid = "80f46bf5-eb01-4c07-960e-a9a3e18aae5e"

  response = requests.put(
      f"https://api.zeeg.me/v2/event-types/{uuid}/status",
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Accept": "application/json",
      },
  )
  ```

  ```javascript JavaScript theme={null}
  const uuid = "80f46bf5-eb01-4c07-960e-a9a3e18aae5e";

  await fetch(`https://api.zeeg.me/v2/event-types/${uuid}/status`, {
    method: "PUT",
    headers: {
      Authorization: "Bearer YOUR_TOKEN",
      Accept: "application/json",
    },
  });
  ```
</CodeGroup>

### Example response

```json theme={null}
{
  "success": true,
  "message": "Success"
}
```

<Warning>
  This endpoint **toggles** — it does not let you set an explicit target state. If you need to ensure a page ends up active (or inactive) regardless of its current state, fetch the page first, check `isActive`, and only call the toggle endpoint when the current state differs from your target.
</Warning>

```python Python theme={null}
def ensure_active(uuid: str, target: bool) -> None:
    page = requests.get(
        f"https://api.zeeg.me/v2/event-types/{uuid}",
        headers={"Authorization": "Bearer YOUR_TOKEN"},
    ).json()["resource"]

    if page["isActive"] != target:
        requests.put(
            f"https://api.zeeg.me/v2/event-types/{uuid}/status",
            headers={"Authorization": "Bearer YOUR_TOKEN"},
        )
```

## Issuing single-use links

A single-use link lets you give a specific customer a unique URL that can be redeemed exactly once. After the booking is confirmed, the link can no longer be used. This is the most powerful programmatic feature exposed on scheduling pages — use it any time you want to bind a single booking to a specific recipient (post-purchase scheduling, support escalations, gated demo invites, etc.).

Generate one with `GET /event-types/{uuid}/single-use-link`.

### Query parameters

| Parameter | Type   | Description                                                                                                                                                                                                                    |
| --------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `price`   | number | Optional. For paid scheduling pages, override the default price for this single-use link. Useful for issuing discounted or free bookings to specific recipients. The override applies to all configured durations on the page. |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.zeeg.me/v2/event-types/80f46bf5-eb01-4c07-960e-a9a3e18aae5e/single-use-link" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Accept: application/json"
  ```

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

  uuid = "80f46bf5-eb01-4c07-960e-a9a3e18aae5e"

  response = requests.get(
      f"https://api.zeeg.me/v2/event-types/{uuid}/single-use-link",
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Accept": "application/json",
      },
  )

  link = response.json()["link"]
  ```

  ```javascript JavaScript theme={null}
  const uuid = "80f46bf5-eb01-4c07-960e-a9a3e18aae5e";

  const response = await fetch(
    `https://api.zeeg.me/v2/event-types/${uuid}/single-use-link`,
    {
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        Accept: "application/json",
      },
    }
  );

  const { link } = await response.json();
  ```
</CodeGroup>

### Example response

```json theme={null}
{
  "success": true,
  "link": "https://zeeg.me/S/axo3kbv54/30min-discovery-call",
  "eventTypeUri": "https://api.zeeg.me/v2/event-types/80f46bf5-eb01-4c07-960e-a9a3e18aae5e"
}
```

The `link` field contains the URL to share with the recipient. Once they complete a booking through it, the link is consumed and any subsequent attempts to use it will fail.

<Tip>
  Each call to `GET /event-types/{uuid}/single-use-link` returns a **new** link. Generate one link per recipient — never reuse the same single-use link for two different people.
</Tip>

### Worked example: issue a link on customer signup

A common pattern is to mint a single-use link the moment a customer completes a paid signup, then email it to them so they can book a kickoff call exactly once.

<CodeGroup>
  ```python Python theme={null}
  import requests

  ZEEG_TOKEN = "YOUR_TOKEN"
  KICKOFF_PAGE_UUID = "80f46bf5-eb01-4c07-960e-a9a3e18aae5e"


  def issue_kickoff_link(customer_email: str) -> str:
      """Issue a single-use kickoff link for a newly signed-up customer."""
      response = requests.get(
          f"https://api.zeeg.me/v2/event-types/{KICKOFF_PAGE_UUID}/single-use-link",
          headers={
              "Authorization": f"Bearer {ZEEG_TOKEN}",
              "Accept": "application/json",
          },
          timeout=10,
      )
      response.raise_for_status()
      link = response.json()["link"]

      send_email(
          to=customer_email,
          subject="Book your kickoff call",
          body=f"Welcome aboard! Pick a time that works for you: {link}",
      )

      return link


  # In your signup webhook handler:
  # issue_kickoff_link(customer.email)
  ```

  ```javascript JavaScript theme={null}
  const ZEEG_TOKEN = "YOUR_TOKEN";
  const KICKOFF_PAGE_UUID = "80f46bf5-eb01-4c07-960e-a9a3e18aae5e";

  async function issueKickoffLink(customerEmail) {
    const response = await fetch(
      `https://api.zeeg.me/v2/event-types/${KICKOFF_PAGE_UUID}/single-use-link`,
      {
        headers: {
          Authorization: `Bearer ${ZEEG_TOKEN}`,
          Accept: "application/json",
        },
      }
    );

    if (!response.ok) {
      throw new Error(`Failed to mint single-use link: ${response.status}`);
    }

    const { link } = await response.json();

    await sendEmail({
      to: customerEmail,
      subject: "Book your kickoff call",
      body: `Welcome aboard! Pick a time that works for you: ${link}`,
    });

    return link;
  }
  ```
</CodeGroup>

<Tip>
  Don't mint single-use links until you actually need them. Generating one for every record in a CRM list "just in case" creates URLs that may sit unused — and you'll have no easy way to map them back to recipients later. Mint on demand, log the recipient alongside the link, and let the [`invitee.scheduled`](/guides/webhooks-guide) webhook tell you when each link has been consumed.
</Tip>

## Composing with the booking flow

Once you have a scheduling page (or a single-use link), the next step is fetching availability and creating the booking. That's covered end-to-end in:

<Card title="Booking Flow" icon="calendar-check" href="/guides/booking-flow">
  Fetch a scheduling page's available slots and create a booking via the API.
</Card>

## Rate limits and error handling

* All endpoints in this guide return standard Zeeg error codes — see [Errors](/errors) for the full list and recommended client behaviour.
* API requests are subject to per-token limits — see [Rate Limits](/rate-limits) before bulk-issuing single-use links or syncing many pages.
* A `404` from the toggle or single-use-link endpoints means the UUID does not match a scheduling page accessible by your token. Double-check the UUID and the token's owner.
