# Add a scheduling page with automatic notetaking

Source: https://developer.nylas.com/docs/cookbook/use-cases/build/scheduling-with-notetaking/

Every scheduled meeting needs notes, but nobody wants to take them. Combine Scheduler with Notetaker and the recording happens by itself: a guest books a slot on your scheduling page, the event is created with a conferencing link, Notetaker joins on time, and a webhook delivers the transcript, summary, and action items after the call ends. No per-meeting setup. No forgotten recordings.

This is the building-block recipe for the [interview scheduling pipeline](/docs/cookbook/use-cases/build/interview-scheduling-pipeline/) and any other one-on-one meeting flow where you want recordings without thinking about them.

## The pipeline

```
guest visits scheduling page ─▶ books a slot
                                     │
                                     ▼
            Scheduler creates calendar event with conferencing link + Notetaker settings
                                     │
                                     ▼
                       Notetaker joins the meeting at start time
                                     │
                                     ▼
                            meeting happens, bot records
                                     │
                  notetaker.media webhook ─▶ download recording, transcript, summary, action items
```

By the end you'll have a Scheduler Configuration with Notetaker enabled, a scheduling page (hosted or embedded), and webhook handlers that deliver the media artifacts after each call.

## Before you begin


Make sure you have the following before starting this tutorial:

- A [Nylas account](https://dashboard-v3.nylas.com/) with an active application
- A valid **API key** from your Nylas Dashboard
- At least one **connected grant** (an authenticated user account) for the provider you want to work with
- **Node.js 18+** or **Python 3.8+** installed (depending on which code samples you follow)

> **Info:** 
> **New to Nylas?** Start with the [quickstart guide](/docs/v3/getting-started/) to set up your app and connect a test account before continuing here.


You also need the following for this tutorial:

- A **connected grant** with calendar access for the provider you want to schedule with
- A **conferencing provider** set up on the grant (Google Meet, Microsoft Teams, or Zoom). Notetaker needs a meeting link to join, so conferencing is required. See [Adding conferencing to bookings](/docs/v3/scheduler/add-conferencing/) for setup details.
- **Notetaker** enabled on your Nylas plan

## Create a Scheduler Configuration with Notetaker

Start by creating a Configuration that defines your scheduling page, conferencing provider, and Notetaker settings. This single API request sets up the entire pipeline.

```bash
curl --request POST \
  --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/scheduling/configurations' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "requires_session_auth": false,
    "participants": [{
      "name": "Your Name",
      "email": "you@example.com",
      "is_organizer": true,
      "availability": {
        "calendar_ids": ["<CALENDAR_ID>"]
      }
    }],
    "availability": {
      "duration_minutes": 30
    },
    "event_booking": {
      "title": "Meeting with {{invitee_name}}",
      "conferencing": {
        "provider": "Google Meet",
        "autocreate": {}
      }
    },
    "scheduler": {
      "notetaker_settings": {
        "enabled": true,
        "show_ui_consent_message": true,
        "notetaker_name": "Meeting Notetaker",
        "meeting_settings": {
          "video_recording": true,
          "audio_recording": true,
          "transcription": true,
          "summary": true,
          "action_items": true
        }
      }
    }
  }'
```

A few things to note about this request:

- **`conferencing.provider`** determines which video platform Notetaker joins. Set this to `"Google Meet"`, `"Microsoft Teams"`, or `"Zoom Meeting"` depending on your grant's provider. The `autocreate` object tells Scheduler to generate a meeting link automatically for each booking.
- **`scheduler.notetaker_settings.enabled`** turns on the Notetaker integration. Without this, bookings are created normally but no recording bot joins.
- **`notetaker_name`** is the display name guests see when the bot joins the call. Keep it short and descriptive so attendees know what it is.
- **`meeting_settings`** controls what Notetaker produces. You can disable `video_recording` if you only need audio, or turn off `summary` and `action_items` if you just want the raw transcript.

> **Info:** 
> Some `meeting_settings` fields depend on others. Transcription requires `audio_recording`, and both `summary` and `action_items` require `transcription`. If you enable a feature that depends on another, Nylas enables the dependency automatically.

### Customize summary and action item output

If you want more control over the AI-generated content, pass custom instructions:

```bash
curl --request PUT \
  --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/scheduling/configurations/<CONFIGURATION_ID>' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "scheduler": {
      "notetaker_settings": {
        "enabled": true,
        "meeting_settings": {
          "video_recording": true,
          "audio_recording": true,
          "transcription": true,
          "summary": true,
          "summary_settings": {
            "custom_instructions": "Focus on key decisions, open questions, and next steps."
          },
          "action_items": true,
          "action_items_settings": {
            "custom_instructions": "List action items with the responsible person and a deadline if mentioned."
          }
        }
      }
    }
  }'
```

Custom instructions are limited to 1,500 characters each. Be specific about what you want: the more precise the instructions, the more useful the output.

## Host the scheduling page

Once your Configuration exists, you need to give guests a way to book meetings. Nylas supports two approaches.

### Option 1: Nylas-hosted scheduling page

The simplest option. Add a `slug` to your Configuration, and Nylas hosts the scheduling page for you at `book.nylas.com/<SLUG>`.

```bash
curl --request PUT \
  --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/scheduling/configurations/<CONFIGURATION_ID>' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "slug": "meet-with-your-team"
  }'
```

After this request succeeds, your scheduling page is live at `https://book.nylas.com/meet-with-your-team`. Share that URL with guests, embed it in emails, or link to it from your website. No frontend code required.

### Option 2: Embedded scheduling component

If you want the scheduling UI inside your own application, use the `<nylas-scheduling>` web component. This gives you full control over the surrounding page layout, styling, and user experience.

```html
<!DOCTYPE html>
<html>
  <head>
    <title>Book a Meeting</title>
    <script src="https://cdn.jsdelivr.net/npm/@nylas/react@latest/dist/cdn/nylas-scheduling/nylas-scheduling.es.js"></script>
  </head>
  <body>
    <nylas-scheduling configuration-id="<CONFIGURATION_ID>"> </nylas-scheduling>
  </body>
</html>
```

```tsx
function BookingPage() {
  return <NylasScheduling configurationId="<CONFIGURATION_ID>" />;
}

export default BookingPage;
```

The component handles date selection, time slot display, the booking form, and confirmation. All the Notetaker settings you configured on the backend apply automatically. Guests see a consent message if you set `show_ui_consent_message` to `true`.

For more customization options, see [Using the Scheduling component](/docs/v3/scheduler/using-scheduling-component/) and [Customize Scheduler](/docs/v3/scheduler/customize-scheduler/).

## Set up webhooks for recordings

You need webhooks to know when bookings happen and when recordings are ready. Subscribe to the `booking.created` and `notetaker.media` triggers.

```bash
curl --request POST \
  --url 'https://api.us.nylas.com/v3/webhooks' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "trigger_types": [
      "booking.created",
      "notetaker.media"
    ],
    "description": "Scheduling with notetaking",
    "webhook_url": "https://your-app.example.com/webhooks/nylas",
    "notification_email_addresses": ["you@example.com"]
  }'
```

- **`booking.created`** fires when a guest completes a booking. Use this to update your internal records, send custom notifications, or trigger other workflows.
- **`notetaker.media`** fires when Notetaker finishes processing media after a meeting ends. The payload includes download URLs for the recording, transcript, summary, and action items.

> **Warn:** 
> **Your webhook endpoint must be publicly accessible and respond with a 200 status code.** Nylas retries failed deliveries, but if your endpoint is consistently unreachable, notifications are dropped. For more details, see [Using webhooks with Nylas](/docs/v3/notifications/).

### Booking created webhook payload

When a guest books a meeting, Nylas sends a notification like this:

```json [webhookPayloads-booking.created]
{
  "specversion": "1.0",
  "type": "booking.created",
  "source": "/nylas/passthru",
  "id": "<WEBHOOK_ID>",
  "time": 1725895310,
  "data": {
    "application_id": "<NYLAS_APPLICATION_ID>",
    "grant_id": "<NYLAS_GRANT_ID>",
    "object": {
      "booking_id": "<BOOKING_ID>",
      "configuration_id": "<CONFIGURATION_ID>",
      "object": "booking",
      "booking_info": {
        "event_id": "<EVENT_ID>",
        "start_time": 1719842400,
        "end_time": 1719846000,
        "title": "Meeting with Leyah Miller",
        "location": "https://meet.google.com/abc-defg-hij"
      }
    }
  }
}
```

Notice the `location` field contains the conferencing link. That is the same link Notetaker uses to join the meeting.

## Retrieve recordings and transcripts

After the meeting ends, Notetaker processes the recording. This typically takes a few minutes. When processing completes, Nylas sends a `notetaker.media` webhook with the state set to `available` and URLs for each media file.

### The notetaker.media webhook payload

```json [mediaPayload-notetaker.media]
{
  "specversion": "1.0",
  "type": "notetaker.media",
  "source": "/nylas/notetaker",
  "id": "<WEBHOOK_ID>",
  "time": 1737500935555,
  "data": {
    "application_id": "<NYLAS_APPLICATION_ID>",
    "object": {
      "id": "<NOTETAKER_ID>",
      "object": "notetaker",
      "state": "available",
      "media": {
        "recording": "https://storage.googleapis.com/nylas-notetaker/.../recording.mp4",
        "recording_duration": "1800",
        "thumbnail": "https://storage.googleapis.com/nylas-notetaker/.../thumbnail.png",
        "transcript": "https://storage.googleapis.com/nylas-notetaker/.../transcript.json",
        "summary": "https://storage.googleapis.com/nylas-notetaker/.../summary.json",
        "action_items": "https://storage.googleapis.com/nylas-notetaker/.../action_items.json"
      }
    }
  }
}
```

Each URL in the `media` object points to a downloadable file. Download them directly from your webhook handler.

### Download media files

The URLs in the webhook payload are valid for 60 minutes. Download the files immediately when you receive the webhook. If the URLs expire, you can retrieve fresh ones using the Notetaker API:

```bash
curl --request GET \
  --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/notetakers/<NOTETAKER_ID>/media' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>'
```

```json
{
  "data": {
    "recording": "https://storage.googleapis.com/nylas-notetaker/.../recording.mp4",
    "thumbnail": "https://storage.googleapis.com/nylas-notetaker/.../thumbnail.png",
    "transcript": "https://storage.googleapis.com/nylas-notetaker/.../transcript.json",
    "summary": "https://storage.googleapis.com/nylas-notetaker/.../summary.json",
    "action_items": "https://storage.googleapis.com/nylas-notetaker/.../action_items.json"
  }
}
```

> **Warn:** 
> **Nylas stores Notetaker media files for a maximum of 14 days.** After that, the files are permanently deleted. Download and store the files in your own infrastructure as soon as they become available.

### What the media files contain

| File             | Format                          | Contents                                                       |
| ---------------- | ------------------------------- | -------------------------------------------------------------- |
| **Recording**    | MP4 (video) or MP3 (audio-only) | Full meeting recording at 1280x720 resolution, 12 FPS          |
| **Thumbnail**    | PNG                             | A screenshot captured from roughly halfway through the meeting |
| **Transcript**   | JSON                            | Speaker-labelled transcript with timestamps for each segment   |
| **Summary**      | JSON                            | AI-generated meeting summary based on the transcript           |
| **Action items** | JSON                            | AI-extracted list of action items from the conversation        |

The transcript includes speaker names and timing data, so you can build features like searchable meeting archives or highlight key moments.

## Things to know

- **Conferencing is required.** Notetaker connects through a video link. Without one, it has nothing to join. Your Configuration must include `event_booking.conferencing` with Google Meet, Microsoft Teams, or Zoom. Skip conferencing and Notetaker settings are silently ignored.
- **Processing takes a few minutes.** After the meeting ends and the bot disconnects, Nylas processes the recording, runs transcription, and generates the summary + action items. Expect a few minutes of delay before `notetaker.media` fires. Longer meetings take longer to process.
- **Notetaker times out at the lobby.** The bot joins as a non-signed-in participant. If the meeting is restricted and nobody admits it within 10 minutes, you get `failed_entry` and no recording. For Teams, configure the meeting to allow anonymous users; for Google Meet, set "Anyone with the link can join"; for Zoom, disable the waiting room.
- **Don't ship without an automated media download.** Nylas deletes media files after 14 days. Build a download pipeline that runs on `notetaker.media` and stores files in your own infrastructure. If you need 30+ day retention, this isn't optional.
- **Each booking creates a separate Notetaker instance.** Bots are not pooled or deduplicated. Two back-to-back bookings at 2:00 PM and 2:30 PM create two independent bots.
- **Recording consent is your problem.** The `show_ui_consent_message` flag and the in-meeting chat message are informational, not legal consent mechanisms. Recording laws vary by jurisdiction -- some require explicit opt-in. Get this reviewed before production.

## Next steps

- [Interview scheduling pipeline](/docs/cookbook/use-cases/build/interview-scheduling-pipeline/) -- the round-robin extension of this recipe for hiring panels
- [Automate meeting follow-ups](/docs/cookbook/use-cases/act/automate-meeting-follow-ups/) -- close the loop with a recap email after each meeting
- [Auto-log meeting notes to your CRM](/docs/cookbook/use-cases/sync/auto-log-meeting-notes-crm/) -- pipe Notetaker output into Salesforce or HubSpot
- [Scheduler and Notetaker integration](/docs/v3/scheduler/scheduler-notetaker-integration/) -- full reference for Notetaker settings inside Scheduler
- [Customize Scheduler](/docs/v3/scheduler/customize-scheduler/) -- style the page, add custom fields, control the booking flow
- [Handling Notetaker media files](/docs/v3/notetaker/media-handling/) -- media formats, download strategies, storage recommendations