{"slug": "record-and-transcribe-meetings-with-the-nylas-notetaker-api", "title": "Record and transcribe meetings with the Nylas Notetaker API", "summary": "Nylas has launched a Notetaker API that allows developers to programmatically join, record, and transcribe meetings from Zoom, Google Meet, and Microsoft Teams. The API supports both grant-scoped notetakers tied to a connected account and standalone notetakers that only require a meeting link. Developers can create notetakers via HTTP or the Nylas CLI, with options for custom bot names, scheduled join times, and toggles for video, audio, and transcription.", "body_md": "Meeting notes are the feature everyone wants and nobody wants to build. The hard part isn't the summary — an LLM handles that. The hard part is getting into the meeting: a bot that joins Zoom, Google Meet, and Microsoft Teams, survives each platform's waiting room and admission flow, records cleanly, and produces a transcript you can feed downstream. Each provider has its own join mechanics, and none of them ships a tidy \"record this meeting\" API.\n\nThe Nylas Notetaker API is that bot as a service. You point it at a meeting link, it joins on schedule, records, and generates a transcript, and you fetch the recording and transcript through one endpoint. This post walks the Notetaker surface from the HTTP API and the [Nylas CLI](https://cli.nylas.com/docs/commands), which mirrors the whole lifecycle for terminal use and quick testing.\n\nI work on the CLI, so the terminal commands below are exactly what I run when I'm testing a notetaker against a live meeting.\n\nBefore any code, there's one architectural choice worth understanding, because it changes the endpoint you call.\n\nA **grant-scoped** notetaker is tied to a connected account and lives under `/v3/grants/{grant_id}/notetakers`\n\n. Use it when the bot acts on behalf of a specific user — it can read that user's calendar and join their meetings as them.\n\nA **standalone** notetaker has no grant at all and lives under `/v3/notetakers`\n\n. You hand it a raw meeting link and it joins, no connected account required. This is the one to reach for when you just have a URL and want a recording — a public webinar, a meeting on an account you haven't connected, or a system that deals in links rather than users.\n\nSame request body, same lifecycle, same media output; the only difference is whether there's a `grant_id`\n\nin the path. See the [Notetaker overview](https://developer.nylas.com/docs/v3/notetaker/) for how both models fit together.\n\nYou need a Nylas API key. If you're using a grant-scoped notetaker you also need a connected account; for standalone, the API key alone is enough. The CLI gets you started:\n\n```\nnylas init        # create an account, generate an API key\nnylas auth login  # only needed for grant-scoped notetakers\n```\n\nThe supported meeting providers are Zoom, Google Meet, and Microsoft Teams. Any meeting link from those three works as the target.\n\nCreating a notetaker is one call. The only required field is the meeting link; everything else has a sensible default. The CLI joins immediately if you don't pass a time:\n\n```\n# Join right now\nnylas notetaker create --meeting-link \"https://zoom.us/j/123456789\"\n\n# Join at a specific time, with a custom display name\nnylas notetaker create \\\n  --meeting-link \"https://meet.google.com/abc-defg-hij\" \\\n  --join-time \"2026-06-23 14:00\" \\\n  --bot-name \"Acme Notetaker\"\n```\n\nThe `--bot-name`\n\nflag sets what the other participants see in the attendee list, which matters more than it sounds — a bot labeled \"Acme Notetaker\" reads as intentional, while a generic name makes people wonder who joined. The `--join-time`\n\nflag accepts an absolute time, a relative offset like `30m`\n\n, or natural phrasing like `tomorrow 9am`\n\n.\n\nOver HTTP, the request body fields are `meeting_link`\n\n(required), `join_time`\n\n, `name`\n\n, and `meeting_settings`\n\n:\n\n```\ncurl --request POST \\\n  --url \"https://api.us.nylas.com/v3/grants/<GRANT_ID>/notetakers\" \\\n  --header \"Authorization: Bearer <NYLAS_API_KEY>\" \\\n  --header \"Content-Type: application/json\" \\\n  --data '{\n    \"meeting_link\": \"https://meet.google.com/abc-defg-hij\",\n    \"name\": \"Acme Notetaker\",\n    \"meeting_settings\": {\n      \"video_recording\": true,\n      \"audio_recording\": true,\n      \"transcription\": true\n    }\n  }'\n```\n\nFor a standalone notetaker, drop the grant from the path and POST the same body to `/v3/notetakers`\n\n. The `meeting_settings`\n\nobject controls what gets captured — `video_recording`\n\n, `audio_recording`\n\n, and `transcription`\n\ntoggles. They aren't fully independent, though: if `transcription`\n\nis `true`\n\n, both `video_recording`\n\nand `audio_recording`\n\nmust also be `true`\n\n, because the transcript is generated from the recording. So \"transcript only, no recording\" isn't a valid combination — you can record audio-only, but a transcript always implies a recording exists.\n\nThere's also a `transcription_settings`\n\nobject with an `expected_languages`\n\narray. It's a language *declaration*, not translation: the hints help the speech recognizer pick between the languages you expect in the meeting, and Notetaker never translates the transcript or forces it into one language. The full request body is in the [invite notetaker](https://developer.nylas.com/docs/reference/api/notetaker/invite-notetaker/) reference, and the CLI flags are at [ notetaker create](https://cli.nylas.com/docs/commands/notetaker-create).\n\nA notetaker moves through states, and your app usually waits for it to finish before pulling media. The CLI's `--state`\n\nfilter accepts friendly names — `scheduled`\n\n(created, waiting to join), `connecting`\n\n, `attending`\n\n(in the meeting, recording), `complete`\n\n(done, media ready), `cancelled`\n\n, and `failed`\n\n. The raw API `state`\n\nfield is more granular: a notetaker object surfaces values like `waiting_for_entry`\n\n, `processing`\n\n, and `available`\n\n(the API's equivalent of the CLI's \"complete\"). The list endpoint's `state`\n\nquery filter uses its own enum (for example `media_available`\n\n), so don't assume the filter value and the object's `state`\n\nstring are spelled identically. List notetakers and filter by state to find the ones worth acting on:\n\n```\n# All notetakers (20 by default)\nnylas notetaker list\n\n# Only the finished ones, ready for media\nnylas notetaker list --state complete\n```\n\nThe `--state`\n\nfilter is how you build a polling loop: ask for `complete`\n\nnotetakers, process their media, move on. The CLI returns 20 by default and the [ notetaker list](https://cli.nylas.com/docs/commands/notetaker-list) command documents the rest. To inspect a single notetaker's current state and metadata, use\n\n`nylas notetaker show <notetaker-id>`\n\n. In production, rather than polling, you'd subscribe to notetaker webhooks so Nylas tells you when a session reaches `complete`\n\n.Once a notetaker is `complete`\n\n, its media is ready. The media endpoint returns URLs for the recording (the video or audio file) and the transcript (the text). One thing to watch: these URLs expire, so download promptly rather than storing the URL and fetching it days later.\n\n```\nnylas notetaker media <notetaker-id>\n```\n\nOver HTTP, it's a `GET`\n\nagainst the notetaker's media path:\n\n```\ncurl --request GET \\\n  --url \"https://api.us.nylas.com/v3/grants/<GRANT_ID>/notetakers/<NOTETAKER_ID>/media\" \\\n  --header \"Authorization: Bearer <NYLAS_API_KEY>\"\n```\n\nThe response gives you the download links; pull the bytes to your own storage immediately if you need them long-term. From there the transcript is plain text you can hand to an LLM for a summary, action items, or a searchable index. The [get notetaker media](https://developer.nylas.com/docs/reference/api/notetaker/) reference and the [ notetaker media](https://cli.nylas.com/docs/commands/notetaker-media) command cover the details.\n\nThis is the distinction that catches people, because the three sound interchangeable and aren't:\n\n`cancel`\n\nand `rm`\n\nare aliases of `delete`\n\n.From the CLI:\n\n```\n# End a live recording but keep the media\nnylas notetaker leave <notetaker-id>\n\n# Remove a notetaker and its media\nnylas notetaker delete <notetaker-id>\n```\n\nReaching for `delete`\n\nwhen you meant `leave`\n\npermanently throws away the recording you just made, so it's worth getting right. The [ notetaker delete](https://cli.nylas.com/docs/commands/notetaker-delete) command and the API's separate leave and cancel endpoints keep these operations distinct on purpose.\n\n| Dimension | Value | Notes |\n|---|---|---|\n| Providers | Zoom, Google Meet, Microsoft Teams | Any meeting link from these three |\n| Models | Grant-scoped and standalone |\n`/v3/grants/{id}/notetakers` vs `/v3/notetakers`\n|\n| Capture toggles | video, audio, transcription |\n`meeting_settings` flags; transcription requires both recordings on |\n| Media URLs | Expiring | Download promptly; store your own copy |\n| Lifecycle | scheduled → connecting → attending → complete | Simplified CLI states; the API exposes more granular values |\n\nThe standalone model is the feature I'd point a new integration at first. Not needing a connected account to record a meeting removes the entire OAuth step for the common case where you already have a link, and you can always move to grant-scoped notetakers later when the bot needs to act as a specific user.\n\nThe value here is that the genuinely hard part — a bot that reliably joins three different meeting platforms and comes back with clean media — is the part you don't write. You make one call with a meeting link, wait for `complete`\n\n, and pull a recording and transcript. The summary layer on top is a solved problem; getting a trustworthy transcript out of a live meeting was the bottleneck, and that's what the API removes. The CLI mirrors the full lifecycle, so you can record a real meeting and inspect the transcript from your terminal before committing any of it to code.\n\nWhere to go next:\n\n`nylas notetaker`\n\nsubcommand*Written by Qasim Muhammad and Pouya Sanooei.*", "url": "https://wpnews.pro/news/record-and-transcribe-meetings-with-the-nylas-notetaker-api", "canonical_source": "https://dev.to/mqasimca/record-and-transcribe-meetings-with-the-nylas-notetaker-api-2emk", "published_at": "2026-06-21 21:27:02+00:00", "updated_at": "2026-06-21 21:55:17.941006+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "natural-language-processing"], "entities": ["Nylas", "Zoom", "Google Meet", "Microsoft Teams", "Nylas CLI"], "alternates": {"html": "https://wpnews.pro/news/record-and-transcribe-meetings-with-the-nylas-notetaker-api", "markdown": "https://wpnews.pro/news/record-and-transcribe-meetings-with-the-nylas-notetaker-api.md", "text": "https://wpnews.pro/news/record-and-transcribe-meetings-with-the-nylas-notetaker-api.txt", "jsonld": "https://wpnews.pro/news/record-and-transcribe-meetings-with-the-nylas-notetaker-api.jsonld"}}