cd /news/developer-tools/record-and-transcribe-meetings-with-… · home topics developer-tools article
[ARTICLE · art-35903] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

Record and transcribe meetings with the Nylas Notetaker API

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.

read7 min views3 publishedJun 21, 2026

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.

The 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, which mirrors the whole lifecycle for terminal use and quick testing.

I work on the CLI, so the terminal commands below are exactly what I run when I'm testing a notetaker against a live meeting.

Before any code, there's one architectural choice worth understanding, because it changes the endpoint you call.

A grant-scoped notetaker is tied to a connected account and lives under /v3/grants/{grant_id}/notetakers

. 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.

A standalone notetaker has no grant at all and lives under /v3/notetakers

. 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.

Same request body, same lifecycle, same media output; the only difference is whether there's a grant_id

in the path. See the Notetaker overview for how both models fit together.

You 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:

nylas init        # create an account, generate an API key
nylas auth login  # only needed for grant-scoped notetakers

The supported meeting providers are Zoom, Google Meet, and Microsoft Teams. Any meeting link from those three works as the target.

Creating 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:

nylas notetaker create --meeting-link "https://zoom.us/j/123456789"

nylas notetaker create \
  --meeting-link "https://meet.google.com/abc-defg-hij" \
  --join-time "2026-06-23 14:00" \
  --bot-name "Acme Notetaker"

The --bot-name

flag 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

flag accepts an absolute time, a relative offset like 30m

, or natural phrasing like tomorrow 9am

.

Over HTTP, the request body fields are meeting_link

(required), join_time

, name

, and meeting_settings

:

curl --request POST \
  --url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/notetakers" \
  --header "Authorization: Bearer <NYLAS_API_KEY>" \
  --header "Content-Type: application/json" \
  --data '{
    "meeting_link": "https://meet.google.com/abc-defg-hij",
    "name": "Acme Notetaker",
    "meeting_settings": {
      "video_recording": true,
      "audio_recording": true,
      "transcription": true
    }
  }'

For a standalone notetaker, drop the grant from the path and POST the same body to /v3/notetakers

. The meeting_settings

object controls what gets captured — video_recording

, audio_recording

, and transcription

toggles. They aren't fully independent, though: if transcription

is true

, both video_recording

and audio_recording

must also be true

, 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.

There's also a transcription_settings

object with an expected_languages

array. 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 reference, and the CLI flags are at notetaker create.

A notetaker moves through states, and your app usually waits for it to finish before pulling media. The CLI's --state

filter accepts friendly names — scheduled

(created, waiting to join), connecting

, attending

(in the meeting, recording), complete

(done, media ready), cancelled

, and failed

. The raw API state

field is more granular: a notetaker object surfaces values like waiting_for_entry

, processing

, and available

(the API's equivalent of the CLI's "complete"). The list endpoint's state

query filter uses its own enum (for example media_available

), so don't assume the filter value and the object's state

string are spelled identically. List notetakers and filter by state to find the ones worth acting on:

nylas notetaker list

nylas notetaker list --state complete

The --state

filter is how you build a polling loop: ask for complete

notetakers, process their media, move on. The CLI returns 20 by default and the notetaker list command documents the rest. To inspect a single notetaker's current state and metadata, use

nylas notetaker show <notetaker-id>

. In production, rather than polling, you'd subscribe to notetaker webhooks so Nylas tells you when a session reaches complete

.Once a notetaker is complete

, 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.

nylas notetaker media <notetaker-id>

Over HTTP, it's a GET

against the notetaker's media path:

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

The 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 reference and the notetaker media command cover the details.

This is the distinction that catches people, because the three sound interchangeable and aren't:

cancel

and rm

are aliases of delete

.From the CLI:

nylas notetaker leave <notetaker-id>

nylas notetaker delete <notetaker-id>

Reaching for delete

when you meant leave

permanently throws away the recording you just made, so it's worth getting right. The notetaker delete command and the API's separate leave and cancel endpoints keep these operations distinct on purpose.

Dimension Value Notes
Providers Zoom, Google Meet, Microsoft Teams Any meeting link from these three
Models Grant-scoped and standalone
/v3/grants/{id}/notetakers vs /v3/notetakers
Capture toggles video, audio, transcription
meeting_settings flags; transcription requires both recordings on
Media URLs Expiring Download promptly; store your own copy
Lifecycle scheduled → connecting → attending → complete Simplified CLI states; the API exposes more granular values

The 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.

The 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

, 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.

Where to go next:

nylas notetaker

subcommandWritten by Qasim Muhammad and Pouya Sanooei.

── more in #developer-tools 4 stories · sorted by recency
── more on @nylas 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/record-and-transcrib…] indexed:0 read:7min 2026-06-21 ·