# How to transcribe a Google Meet

Source: https://developer.nylas.com/docs/cookbook/notetaker/transcribe-google-meet/

Google Meet links look like `meet.google.com/abc-defg-hij`, and most of them come straight off a Workspace calendar event. If you're building meeting intelligence on top of those events, you don't want to ask hosts to flip on Google's own transcription or stay on a paid Workspace tier. You point a Nylas Notetaker bot at the same `meet.google.com` link, and it joins, records, and transcribes the call for you.

This recipe covers the two API calls you need: one to send the bot into the meeting, and one to fetch the finished transcript and recording afterward.

## Send a Notetaker bot to a Google Meet

To record a Google Meet, you `POST` the meeting's `meet.google.com` URL to the [invite Notetaker endpoint](/docs/reference/api/notetaker/invite-notetaker/). The `meeting_link` is the only required field, and Notetaker supports all three major platforms, so the same request shape works whether the link is Meet, Teams, or Zoom. Omit `join_time` and the bot joins right away.

The request below turns on transcription and a video recording, and sets `expected_languages` so a bilingual call doesn't get mis-detected. Each `POST` creates a new bot, since Nylas doesn't de-duplicate Notetakers, so send the request once per meeting you want recorded.

```bash
curl --request POST \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/notetakers" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "join_time": 1732657774,
    "meeting_link": "https://meet.google.com/xyz-abcd-ijk",
    "meeting_settings": {
      "action_items": true,
      "action_items_settings": {
        "custom_instructions": "Only return the 5 most important action items."
      },
      "audio_recording": true,
      "leave_after_silence_seconds": 360,
      "summary": true,
      "summary_settings": {
        "custom_instructions": "Return this summary in the MEDPIC sales methodology."
      },
      "transcription": true,
      "transcription_settings": {
        "expected_languages": ["en", "es"],
        "fallback_language": "en"
      },
      "video_recording": true
    },
    "name": "Nylas Notetaker"
  }'

```

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

{
  "request_id": "5fa64c92-e840-4357-86b9-2aa364d35b88",
  "data": {
    "id": "<NOTETAKER_ID>",
    "name": "Nyla's Notetaker",
    "join_time": 1732657774,
    "meeting_link": "<MEETING_URL>",
    "meeting_provider": "Google Meet",
    "state": "scheduled",
    "meeting_settings": {
      "action_items": true,
      "action_items_settings": {
        "custom_instructions": "Only return the 5 most important action items."
      },
      "audio_recording": true,
      "summary": true,
      "summary_settings": {
        "custom_instructions": "Return this summary in the MEDPIC sales methodology."
      },
      "transcription": true,
      "transcription_settings": {
        "expected_languages": ["en", "es"],
        "fallback_language": "en"
      },
      "video_recording": true
    }
  }
}


```

```js [inviteMeet-Node.js SDK]

import Nylas from "nylas";

const nylas = new Nylas({
  apiKey: "<NYLAS_API_KEY>",
  apiUri: "<NYLAS_API_URI>",
});

async function inviteNotetaker() {
  try {
    const notetaker = await nylas.notetakers.create({
      identifier: "<NYLAS_GRANT_ID>",
      requestBody: {
        meetingLink: "https://meet.google.com/abc-defg-hij",
        name: "Nylas Notetaker",
        meetingSettings: {
          videoRecording: true,
          audioRecording: true,
          transcription: true,
        },
      },
    });

    console.log("Notetaker:", notetaker);
  } catch (error) {
    console.error("Error inviting notetaker:", error);
  }
}

inviteNotetaker();


```

```python [inviteMeet-Python SDK]

from nylas import Client

nylas = Client(
    "<NYLAS_API_KEY>",
    "<NYLAS_API_URI>",
)

notetaker = nylas.notetakers.invite(
    request_body={
        "meeting_link": "https://meet.google.com/abc-defg-hij",
        "name": "Nylas Notetaker",
        "meeting_settings": {
            "video_recording": True,
            "audio_recording": True,
            "transcription": True,
        },
    },
    identifier="<NYLAS_GRANT_ID>",
)

print("Invited notetaker:", notetaker)


```

The response returns the Notetaker's `id`. Hold onto it, because you'll use it to fetch media later and to match incoming webhook notifications to this specific meeting.

## Get the transcript and recording

Once the bot leaves the meeting, Nylas processes the audio and produces the files you enabled. Call the [Get Notetaker Media endpoint](/docs/reference/api/notetaker/get-notetaker-media/) with the `notetaker_id` to retrieve them. A typical Meet recording comes back as a `video/mp4` file alongside a `transcript` as `application/json`, plus `summary`, `action_items`, and `thumbnail` if you turned those on.

Every download URL in the response carries a `ttl` of 3600, meaning each link expires 3,600 seconds (60 minutes) after it's generated. Download the files to your own storage promptly. If a link expires, just call this endpoint again to mint fresh URLs.

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

```

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

{
  "request_id": "5fa64c92-e840-4357-86b9-2aa364d35b88",
  "data": {
    "action_items": {
      "created_at": 1703088000,
      "expires_at": 1704297600,
      "name": "meeting_action_items.json",
      "size": 289,
      "ttl": 3600,
      "type": "application/json",
      "url": "https://storage.googleapis.com/nylas-notetaker-uc1-prod-notetaker/..."
    },
    "recording": {
      "created_at": 1703088000,
      "duration": 1800,
      "expires_at": 1704297600,
      "name": "meeting_recording.mp4",
      "size": 52428800,
      "ttl": 3600,
      "type": "video/mp4",
      "url": "https://storage.googleapis.com/nylas-notetaker-uc1-prod-notetaker/..."
    },
    "summary": {
      "created_at": 1703088000,
      "expires_at": 1704297600,
      "name": "meeting_summary.json",
      "size": 437,
      "ttl": 3600,
      "type": "application/json",
      "url": "https://storage.googleapis.com/nylas-notetaker-uc1-prod-notetaker/..."
    },
    "thumbnail": {
      "created_at": 1703088000,
      "expires_at": 1704297600,
      "name": "thumbnail.png",
      "size": 437,
      "ttl": 3600,
      "type": "image/png",
      "url": "https://storage.googleapis.com/nylas-notetaker-uc1-prod-notetaker/..."
    },
    "transcript": {
      "created_at": 1703088000,
      "expires_at": 1704297600,
      "name": "transcript.json",
      "size": 10240,
      "ttl": 3600,
      "type": "application/json",
      "url": "https://storage.googleapis.com/nylas-notetaker-uc1-prod-notetaker/..."
    }
  }
}


```

For details on URL expiration, retention windows, and the transcript format, see [Handling Notetaker media files](/docs/v3/notetaker/media-handling/).

## Transcribe automatically with webhooks

Polling the media endpoint wastes requests, since processing takes a few minutes and finishes at an unpredictable time. Instead, subscribe to the `notetaker.media` webhook, which fires once per file when the media is ready. Your handler then downloads each file inside the 60-minute URL window without any guesswork about timing.

For a full webhook setup, see the [Notetaker webhooks recipe](/docs/cookbook/notetaker/notetaker-webhooks/).

## Things to know about Google Meet

Meet links follow the `meet.google.com/xxx-xxxx-xxx` format, a 10-character code split into three groups. That code is what you pass as `meeting_link`. When a meeting is scheduled through a Workspace calendar event, the same link sits in the event's conferencing details, so you can pull it straight from a synced calendar instead of asking users to paste it.

The bot always joins as an external, non-signed-in guest, and that's where most Google Meet join failures come from. A few specifics to plan for:

- **Host admission.** If the meeting's host is on Google Workspace and the call is set to admit guests manually, a host has to click **Admit** when the bot knocks. Notetaker waits up to 10 minutes, then reports `failed_entry`.
- **Quick access.** Workspace hosts can turn on quick access so trusted participants skip the lobby. With it off, every external joiner, including the bot, lands in the waiting room.
- **Org guest policies.** Some Workspace admins restrict or block external participants entirely at the organization level. If that policy is active, the bot can't enter no matter what your code does, so confirm the meeting allows guests before scheduling a recording.

The practical takeaway: for internal-only Meet calls, make sure a human is present to admit the bot, or ask the host to enable quick access ahead of time. For Google's own breakdown of these controls, see [Google Meet Help](https://support.google.com/meet/).

## What's next

- Learn the full lifecycle in the [Notetaker API guide](/docs/cookbook/notetaker/notetaker-api-guide/).
- Record other platforms with the [Microsoft Teams recipe](/docs/cookbook/notetaker/transcribe-teams-meeting/).
- Download finished files with [Get the transcript and recording](/docs/cookbook/notetaker/get-transcript-and-recording/).
- Review settings and webhooks in the [Notetaker reference docs](/docs/v3/notetaker/).