# Using Nylas Scheduler

Source: https://developer.nylas.com/docs/v3/scheduler/

> **Info:** 
> **New to Scheduler?** Start with the [Scheduler quickstart](/docs/v3/getting-started/scheduler/) to embed scheduling pages in your app in under 10 minutes.

> **Success:** 
> **Looking for the Scheduler API references?** [You can find them here](/docs/reference/api/)!

Nylas Scheduler, part of [Nylas Connect](/docs/v3/getting-started/), is a flexible and secure scheduling solution that you can integrate into your project. With the Scheduler API and the [Scheduler UI components](/docs/reference/ui/), you can manage bookings, design complex scheduling flows, customize the scheduling UI, and much more. Scheduler is included with [all Nylas plans](https://www.nylas.com/pricing/), and any connected calendar grant or Agent Account can act as the organizer.

## How Scheduler works

At its core, Scheduler is made up of two parts: the Scheduler Editor and Scheduling Pages. The **Scheduler Editor** lets organizers create and manage their **Scheduling Pages**. When an organizer creates a Scheduling Page, they set the event details (the title, duration, and which calendar to check availability against).


**Diagram: How a Scheduler booking works.** Every booking surface uses the same Configuration and the same Availability and Bookings endpoints. Collective configurations need every participant free, and round-robin configurations (`max-fairness`, `max-availability`) assign one host per booking.

```mermaid
flowchart TD
  config["Create a Configuration"]
  surface_0_hosted["Hosted Scheduling Page"]
  surface_1_component["Scheduling component"]
  surface_2_api["Your own booking UI"]
  availability["Calculate open slots"]
  booking["Re-check the slot and book"]
  event["Event on organizer's calendar"]
  notify["Confirmations and webhook"]
  config -->|"Guest opens a booking page"| surface_0_hosted
  config -->|"Guest opens a booking page"| surface_1_component
  config -->|"Guest opens a booking page"| surface_2_api
  surface_0_hosted -->|"GET /v3/scheduling/availability"| availability
  surface_1_component -->|"GET /v3/scheduling/availability"| availability
  surface_2_api -->|"GET /v3/scheduling/availability"| availability
  availability -->|"POST /v3/scheduling/bookings"| booking
  booking_b0["Booking rejected"]
  booking -.->|"Slot no longer free"| booking_b0
  booking -->|"Slot still free"| event
  event_b0["Notetaker joins"]
  event -.->|"If Notetaker is enabled"| event_b0
  event --> notify
```

- Your app: **Create a Configuration**: In the Dashboard (Scheduler) or with [`POST /v3/grants/{grant_id}/scheduling/configurations`](/docs/reference/api/configurations/post-configurations/). Sets participants, open hours, and booking rules.
- One of these paths (Guest opens a booking page):
  - **Nylas-hosted page**
    - **Hosted Scheduling Page**: Nylas hosts the page. No frontend code needed.
  - **Embedded component**
    - **Scheduling component**: `<nylas-scheduling>` embedded in your app, as HTML or React.
  - **Your UI + API**
    - **Your own booking UI**: Calls the Availability and Bookings endpoints directly.
- Nylas: **Calculate open slots**: Checks participant calendars within open hours, applying buffers and minimum notice. ([`GET /v3/scheduling/availability`](/docs/reference/api/availability/get-availability/))
- Nylas: **Re-check the slot and book**: Confirms the selected slot is still free before booking. ([`POST /v3/scheduling/bookings`](/docs/reference/api/bookings/post-bookings/))
  - Slot no longer free → **Booking rejected**: Returns an error. Nothing is created.
- Provider: **Event on organizer's calendar**: Created in the organizer's `booking.calendar_id`, with conferencing if configured. (Slot still free)
  - If Notetaker is enabled → **Notetaker joins**: Joins the meeting to record and transcribe. Needs conferencing.
- Nylas: **Confirmations and webhook**: Emails attendees unless `disable_emails` is set, and sends [`booking.created`](/docs/reference/notifications/scheduler/booking-created/).


Guests use Scheduling Pages to book a time with the event organizer. When a booking is confirmed, Scheduler displays a booking confirmation message and sends a confirmation email to the organizer, the participants, the guest, and any other guests on the booking. To stop Scheduler from sending booking email, set `event_booking.disable_emails` to `true` in the Configuration.

Organizers can also customize their Scheduling Pages to include links to reschedule or cancel a booking, include extra fields in the booking form, add their company's logo to email notifications, and more.

Scheduler supports one-on-one, collective, round-robin, and group meetings. See [Meeting types](/docs/v3/scheduler/meeting-types/) for more information. Agent Accounts support all 4; see [Use Scheduler with Agent Accounts](/docs/v3/scheduler/agent-accounts/).

### User roles in Scheduler

Nylas Scheduler recognizes three types of users: organizers, participants, and guests.

> **Info:** 
> **Participants and guests are sometimes collectively called "attendees"**. This includes optional guests that users can invite to the event.

- **Organizers**: Users who can create Scheduling Pages and events. Only one organizer can exist per [Configuration object](#create-a-configuration). An organizer can be a connected OAuth grant or an [Agent Account](/docs/v3/scheduler/agent-accounts/), so an AI agent can own its own booking page.
- **Participants**: Attendees from the organizer's team or company. All participants are defined in the [Configuration object](#create-a-configuration).
- **Guests**: Guests are external users who book an event with participants.
- **Additional guests**: Other users who are invited by the guest who books the event. Their attendance is optional.

## Set up Scheduler

> **Success:** 
> **New to Scheduler?** Check out our [Quickstart guide](/docs/v3/getting-started/scheduler/) for a quick step-by-step implementation guide.


To follow along with the samples on this page, you first need to [sign up for a Nylas developer account](https://dashboard.nylas.com/register?utm_source=docs&utm_medium=devrel-surfaces&utm_campaign=&utm_content=using-apis), which gets you a free Nylas application and API key.

For a guided introduction, you can follow the [Getting started guide](/docs/v3/getting-started/) to set up a Nylas account and Sandbox application. When you have those, you can connect an account from a calendar provider (such as Google, Microsoft, or iCloud) and use your API key with the sample API calls on this page to access that account's data.


Before you start with Scheduler, Nylas recommends you choose your [implementation approach](#choose-your-implementation-approach) and [hosting preference for Scheduling Pages](#choose-a-hosting-option-for-scheduling-pages), and [decide whether to implement the Scheduler Editor](#optional-implement-scheduler-editor).

### Choose your implementation approach

You can use either [UI components](/docs/reference/ui/) or the [Scheduler API](/docs/reference/api/) to add Scheduler to your project.

- You can add **Scheduler UI components** to your project as web (HTML/Vanilla JS) or React components, then customize and extend them according to your needs. This is the simplest way to integrate Scheduler.
- If you use the **Scheduler APIs**, you can create Configurations and manage bookings using API requests. You need to build your own UI, however.

### Choose a hosting option for Scheduling Pages

Nylas offers two hosting options for your Scheduling Pages:

- **Nylas-hosted**: When you create a public Configuration with a page URL ("slug"), Nylas automatically hosts the Scheduling Page under the `book.nylas.com` subdomain.
- **Self-hosted**: You host and manage your Scheduling Pages within your own infrastructure.

### (Optional) Implement Scheduler Editor

You can use Scheduler with or without the Scheduler Editor. The Scheduler Editor lets organizers create and manage Scheduling Pages, including their customization options.

> **Warn:** 
> **If you choose to use the Scheduler Editor for your Nylas-hosted Scheduling Pages**, you're responsible for [setting up the Scheduler Editor Component](#set-up-scheduler-editor-component).

If you plan to use the Scheduler Editor, you need to decide on the authentication method you'll use for the Scheduler Editor Component.

- **Standard**: Configures `nylasSessionsConfig` in your application. Guests are required to log in every time their access token expires. Nylas recommends using this method if you don't have an auth system set up.
- **Existing Hosted Authentication**: Uses your application's existing Nylas Hosted Auth flow. Guests don't have to sign in multiple times.
- **Access token**: Uses an access token for guests who have already authenticated using the same origin. Guests don't have to sign in multiple times.

## Create a Configuration

A Configuration is a collection of settings and preferences for an event. Nylas stores Configuration objects in the Scheduler database and loads them as Scheduling Pages. A Configuration can be either public or private, depending on whether it uses a [session](#optional-create-a-session).

- A **public** Configuration doesn't require a session ID, so anyone with a link to the Scheduling Page can book an event. By default, Configurations are public.
- A **private** Configuration requires a valid session ID to authenticate requests to the [Availability](/docs/reference/api/availability/) and [Bookings](/docs/reference/api/bookings/) endpoints. When you use a private Configuration, you control who can create bookings from the Scheduling Page.

You can create a Configuration using either the [Scheduler API](#create-configuration-with-scheduler-api) or the [Scheduler Editor](#create-configuration-with-scheduler-editor).

### Create Configuration with Scheduler API

Make a [Create Configuration request](/docs/reference/api/configurations/post-configurations/) with the settings you want for your Configuration. By default, Nylas creates a public Configuration that doesn't require a session.

```bash
curl --compressed --request POST \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/scheduling/configurations" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "requires_session_auth": false,
    "participants": [{
      "name": "Nyla",
      "email": "nyla@example.com",
      "is_organizer": true,
      "availability": {
        "calendar_ids": ["primary"]
      },
      "booking": {
        "calendar_id": "primary"
      }
    }],
    "availability": {
      "duration_minutes": 30
    },
    "event_booking": {
      "title": "Testing Scheduler",
      "hide_participants": false,
      "conferencing": {
        "provider": "Zoom Meeting",
        "autocreate": {
          "conf_grant_id": "<NYLAS_GRANT_ID>",
          "conf_settings": {
            "settings": {
              "join_before_host": true,
              "waiting_room": false,
              "mute_upon_entry": false,
              "auto_recording": "none"
            }
          }
        }
      }
    }
  }'

```

```json [createConfig-Response (JSON)]

{
  "ID": "<SCHEDULER_CONFIGURATION_ID>",
  "participants": [
    {
      "name": "Nyla",
      "email": "nyla@example.com",
      "is_organizer": true,
      "availability": {
        "calendar_ids": ["primary"]
      },
      "booking": {
        "calendar_id": "primary"
      }
    }
  ],
  "availability": {
    "duration_minutes": 30
  },
  "event_booking": {
    "title": "Testing Scheduler"
  }
}


```

### Create Configuration with Scheduler Editor

> **Warn:** 
> **You need to have a working front-end UI to create Configurations with the Scheduler Editor**. Follow the [Scheduler Quickstart guide](/docs/v3/getting-started/scheduler/) to get a local development environment up and running.

When you create a Scheduling Page using the Scheduler Editor, Nylas automatically creates a Configuration.

First, you need to include the Scheduler Editor script in your project and set `nylasSessionsConfig`. The Scheduler Editor Component uses the Hosted Authentication details you provide to interact with the Nylas APIs. For more information, see [Set up Scheduler Editor Component](#set-up-scheduler-editor-component).

```html
<!-- scheduler-editor.html -->

<!doctype html>
<html class="h-full bg-white" lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Nylas Scheduler Editor Component</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap"
      rel="stylesheet"
    />
    <script src="https://cdn.tailwindcss.com"></script>

    <style type="text/css">
      body {
        font-family: "Inter", sans-serif;
      }
    </style>
  </head>
  <body class="h-full">
    <div class="grid h-full place-items-center">
      <!-- Add the Nylas Scheduler Editor component -->
      <nylas-scheduler-editor />
    </div>

    <!-- Configure the Nylas Scheduler Editor component -->
    <script type="module">
      import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduler-editor/nylas-scheduler-editor.es.js";

      defineCustomElement();

      const schedulerEditor = document.querySelector("nylas-scheduler-editor");
      schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`;
      schedulerEditor.nylasSessionsConfig = {
        clientId: "<NYLAS_CLIENT_ID>", // Replace with your Nylas client ID from the previous section.
        redirectUri: `${window.location.origin}/scheduler-editor`,
        domain: "https://api.us.nylas.com/v3",
        hosted: true,
        accessType: "offline",
      };

      schedulerEditor.defaultSchedulerConfigState = {
        selectedConfiguration: {
          // Create a public Configuration that doesn't require a session.
          requires_session_auth: false,
          scheduler: {
            rescheduling_url: `${window.location.origin}/reschedule/:booking_ref`,
            cancellation_url: `${window.location.origin}/cancel/:booking_ref`,
          },
        },
      };
    </script>
  </body>
</html>


```

```css [createConfig2-React (CSS)]

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap");

html {
  height: 100%;
}

body {
  font-family: "Inter", sans-serif;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 100%;
}


```

Next, add the Scheduling Page script to your project.

```html
<!-- index.html -->

<!doctype html>
<html class="h-full bg-white" lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Nylas Scheduling Component</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap"
      rel="stylesheet"
    />
    <script src="https://cdn.tailwindcss.com"></script>

    <style type="text/css">
      body {
        font-family: "Inter", sans-serif;
      }
    </style>
  </head>
  <body>
    <div class="grid gap-0 h-full place-items-center">
      <div class="grid gap-4">
        <!-- A button to view the Scheduler Editor -->
        <a
          href="scheduler-editor.html"
          class="w-fit border border-blue-500 hover:bg-blue-100 text-blue-500 font-bold py-2 px-4 rounded"
        >
          View Scheduler Editor
        </a>

        <!-- Add the Nylas Scheduling Component -->
        <nylas-scheduling></nylas-scheduling>
      </div>
    </div>

    <!-- Configure the Nylas Scheduling Component with a Configuration ID. -->
    <script type="module">
      import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduling/nylas-scheduling.es.js";

      defineCustomElement();

      const nylasScheduling = document.querySelector("nylas-scheduling");
      nylasScheduling.schedulerApiUrl = "https://api.us.nylas.com";

      // Get the Configuration ID from the URL (`?config_id=<NYLAS_SCHEDULER_CONFIGURATION_ID>`).
      const urlParams = new URLSearchParams(window.location.search);

      // If `config_id` doesn't exist, throw a `console.error`.
      if (!urlParams.has("config_id")) {
        console.error(
          "No Scheduler Configuration ID found in the URL. Please provide a Configuration ID.",
        );
      }

      // Set the Configuration ID.
      nylasScheduling.configurationId = urlParams.get("config_id");
    </script>
  </body>
</html>


```

```css [addPage-React (CSS)]

#root {
  display: grid;
  place-items: center;
  height: 100%;
}

#root > div {
  display: grid;
  gap: 1rem;
}

.button {
  width: fit-content;
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-weight: 700;
  color: rgb(59, 130, 246);
  text-decoration: inherit;
  border-width: 1px;
  border-radius: 0.25rem;
  border-color: rgb(59, 130, 246);
  border-style: solid;
}


```

## (Optional) Create a session

A session is a short-lived token that lets a guest view availability and book from a private Configuration. Your backend creates it with your API key, so guests can only book after your app decides they should. A session lasts 5 minutes by default, and you can set its `time_to_live` up to 30 minutes.

Use sessions when your app needs to decide who can book, or when they can book. For example:

- **Payment before booking**: Charge for a consultation, then create the session after the payment succeeds.
- **Signed-in users only**: Create sessions only for users logged in to your app, so the booking flow isn't open to anyone who finds the Configuration.
- **Qualification or intake**: Collect answers first, and offer booking only to guests who qualify.
- **Plan limits**: Count bookings per customer in your app, and stop creating sessions when a customer reaches their limit.

If anyone should be able to book, use a public Configuration instead. Public Configurations don't use sessions, and a Create Session request for one returns a `400` error. To make a Configuration private, set `requires_session_auth` to `true`.


**Diagram: Gate bookings with a session.** A private Configuration only accepts bookings that carry a session ID, and only your backend can create one. Create the session after your own step succeeds, such as a payment.

```mermaid
flowchart TD
  private["Make the Configuration private"]
  gate["Completes your step"]
  session["Create a session"]
  pass["Pass the session ID"]
  book["Show availability and book"]
  private --> gate
  gate -->|"Step succeeded"| session
  session --> pass
  pass --> book
  book_b0["Request rejected"]
  book -.->|"Session missing or expired"| book_b0
```

- Your app: **Make the Configuration private**: Set `requires_session_auth: true`.
- Guest: **Completes your step**: For example, pays, signs in, or fills out a qualification form.
- Your backend: **Create a session**: [`POST /v3/scheduling/sessions`](/docs/reference/api/sessions/post-sessions/) with your API key. `time_to_live` defaults to 5 minutes, up to 30. (Step succeeded)
- Your app: **Pass the session ID**: Set `sessionId` on `<nylas-scheduling>`, or send it as the Bearer token on Availability and Bookings requests.
- Nylas: **Show availability and book**: Accepts requests from this guest's session until it expires.
  - Session missing or expired → **Request rejected**: Create a new session to continue.


> **Success:** 
> **If you created a public Configuration in the [**previous step**](#create-a-configuration)**, you can skip this step and [set up the UI Components](#set-up-ui-components).

Make a [Create Session request](/docs/reference/api/sessions/post-sessions/) with the ID of your Configuration object. Nylas recommends you set a time-to-live (TTL) value for each session, and manually refresh sessions as they expire.

```bash
curl --compressed --request POST \
  --url "https://api.us.nylas.com/v3/scheduling/sessions" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "configuration_id": "<SCHEDULER_CONFIGURATION_ID>",
    "time_to_live": 10
  }'

```

```json [createSession-Response (JSON)]
{
  "request_id": "5fa64c92-e840-4357-86b9-2aa364d35b88",
  "data": {
    "session_id": "<SCHEDULER_SESSION_ID>"
  }
}
```

## Customize the email Scheduler sends

Scheduler sends its own booking confirmations, and you can't change their wording or branding. To replace them with your own HTML, use a workflow on the booking triggers and set `disable_emails: true` on the Configuration so guests don't receive both.

- [Customize Scheduler email for your app](/docs/cookbook/workflows/scheduler-booking-email/) uses one branded template for every user
- [Customize Scheduler email for each user](/docs/cookbook/workflows/scheduler-email-per-user/) gives each customer their own branding
- [Tell attendees a meeting is recorded](/docs/cookbook/workflows/recording-notice-scheduler/) when the Configuration enables Notetaker

## Set up meeting reminders

Nylas can send email or webhook notification reminders for upcoming events. When you set up a reminder, you can configure the reminder type, time, recipients (email only), and email subject (email only).

You can choose to send both an email and webhook reminder for the same event. When you add both types of reminders, Nylas sends them approximately five minutes apart (for example, if you set both to be sent an hour before an event at 12:00p.m., Nylas sends one reminder at 10:55a.m. and the other at 11:00a.m.).

You can set up reminders using either the [Scheduler API](#set-up-reminders-using-scheduler-api) or the [Scheduler Editor](#set-up-reminders-using-scheduler-editor).

### Set up reminders using Scheduler API

Make a [Create Configuration](/docs/reference/api/configurations/post-configurations/) or [Update Configuration](/docs/reference/api/configurations/put-configurations-id/) request that includes the `reminders` array.

> **Info:** 
> **If you want to get reminders using webhook notifications,** you also need to subscribe to the [`booking.reminder` webhook trigger](/docs/reference/notifications/scheduler/booking-reminder/).

```bash [reminders-Set email reminder]
curl --request PUT \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/scheduling/configurations/<SCHEDULER_CONFIGURATION_ID>" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "event_booking": {
      "reminders": [{
        "type": "email",
        "minutes_before_event": 30,
        "recipient": "all",
        "email_subject": "Meet Nyla in 30 minutes!"
      }]
    }
  }'
```

```bash [reminders-Set webhook reminder]
curl --request PUT \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/scheduling/configurations/<SCHEDULER_CONFIGURATION_ID>" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "event_booking": {
      "reminders": [{
        "type": "webhook",
        "minutes_before_event": 30
      }]
    }
  }'
```

### Set up reminders using Scheduler Editor

Use the `nylas-reminder-emails` component to let organizers create and manage email reminders from the Scheduler Editor UI.

By default, the Scheduler Editor includes the Communications tab, where organizers can customize their confirmation and reminder emails. To create a reminder, navigate to the **Communications** tab, click **New reminder**, and set the reminder details.