Meetings are pretty old school.
It didn’t matter if you were in the agora of ancient Greece, sitting in the first town hall meetings of the 16th century, or fumbling with a mute button in front of your computer screen. The format and goal of a meeting hasn’t changed much.
We bring up an agenda, discuss it, and ideally, come to a conclusion. But more often than not, we spend too much time discussing and leave our meetings bloated with information instead of action items.
This is a problem that persists even more so with the convenience of meeting platforms.
Five years ago, developers were doubling down on tools to improve the meeting experience. But today, we’re seeing a shift in value toward using AI to capture and elevate what happens after those meetings.
How can we keep up with streams of information as they come? How can we capture and remember what matters?
If you’re building a product to help people collaborate during and after meetings, then you’ll want to know how to capture audio and video data from popular platforms like Zoom, Microsoft Teams, and Google Meet. This guide breaks down what developers need to know when selecting and implementing APIs for cross-platform recordings.
Hundreds of millions of users hold virtual meetings on platforms like Zoom, Teams, and Meet daily. Zoom data reports that the platform hosts 3.3 billion minutes of meetings annually.
A product that records meetings on these popular platforms will help teams capture, preserve shared context, extract meaning, and make asynchronous collaboration long after any meeting is done.
Shifting your strategy toward meeting recordings and automation unlocks new ways SaaS platforms can deliver value across industries.. For example:
Each meeting platform has its own APIs and requirements for retrieving meeting recordings and meeting transcriptions.
Take Zoom, for example.
Developers trying to build AI agents that join meetings, transcribe conversations, and respond in real time quickly hit a wall. Zoom doesn’t give you direct access to live audio through its API, and recording requires strict consent flows that are easy to misconfigure. Even triggering a simple recording bot means navigating OAuth scopes and host presence rules.
And Zoom isn’t the only challenge. Developers building cross-platform recording features run into platform-specific limitations like:
People have their own preferences for meeting platforms, influenced by factors like the devices they use, the teams they work with, and the software stack they operate. You want your product to be able to deliver a quality meeting assistance experience that meets users where they are.
Using a unified third-party API means:
Before you start building bots specifically for recording Zoom, Teams, and Google Meet meetings, here are a few things to keep in mind for each platform.
Recording requirements |
Developers must configure flows that get explicit participant consent.
Bots must either:
|
---|---|
API support |
|
Challenges |
|
Developer tips |
For bots that need to join Zoom meetings and access raw audio/video,
use the Zoom Meeting SDK. The Linux version works well in Docker.
You’ll get direct media access, but you’ll need to manage encoding and scaling on your own. |
Recording requirements | Meeting recording and transcription features are gated by organizational policies. Consent flows must align with regulations. |
---|---|
API support |
|
Challenges |
|
Developer tips | Build bots using the Microsoft Real-time Media Platform for access to live streams. |
Recording requirements |
|
---|---|
API support | No dedicated API for recording or retrieving media. |
Challenges |
|
Developer tips |
|
Let’s look at the APIs that are simplifying the complexities of cross-platform recording. These solutions provide developer-friendly tools to help you build on meeting data without having to worry about developing your own meeting bot infrastructure.
Recall.ai is an API that connects to prebuilt meeting bots for Zoom, Microsoft Teams, and Google Meet. It handles the heavy lifting of joining meetings, capturing audio and video, and piping that data back to your app in real time or post-call. The platform also supports additional platforms like Slack Huddle and Cisco Webex.
Features
Best for: Collaboration tools, internal analytics platforms, and AI assistants that need to passively capture and process meetings across platforms. Use cases include coaching, training, and customer support QA.
What’s in the docs?
Fireflies.ai API gives developers access to Fireflies’ transcription engine and meeting intelligence tools. Rather than using the API to orchestrate bots, developers upload audio files directly and use the API to generate transcripts, extract insights, and manage user-level data. This makes it more suited for post-meeting processing than live bot interactions.The API works with any audio source, but speaker labeling support is strongest with Zoom and Google Meet.
Features
Best for: Apps focused on building searchable meeting archives or generating structured insights for coaching, analytics, or CRM enrichment.
What’s in the docs?
Nylas Notetaker goes beyond meeting recordings and transcripts. It’s the only meeting recording API in this list that already has integrations with calendar providers, making it ideal for developers that need reliable calendar synchronization in their products — like CRMs, ATSs, sales tools, or scheduling platforms. The Notetaker API has native support for Zoom, Teams, and Google Meet. By being a unified API with native integrations for meetings and calendars, developers can work fewer edge cases and better scheduling logic.
Features
Best for: Platforms where calendar, meeting, and communication data all intersect. If you’re building tools that depend on context-rich communication — like customer relationship management, lead enrichment, hiring coordination, or customer follow-up — Nylas gives you the most integrated, flexible foundation.
What’s in the docs?
This tutorial will walk you through how to integrate with the Nylas Notetaker so your app can record meetings across Zoom, Microsoft Teams, and Google Meet. You’ll need:
In your development environment, set an environment variable for your Nylas API key (you can get this from the Nylas dashboard).
Replace <YOUR_NYLAS_API_KEY> with the actual key from your Nylas dashboard. You’ll also reference your grantId (the connected account’s grant ID) in API calls.
# Set environment variables for reuse
export NYLAS_API_KEY="<YOUR_NYLAS_API_KEY>"
Before you can schedule or manage a Notetaker, you’ll need a grantId
. This represents a connected user account and is required for making authenticated API calls on their behalf.
If you’re building an app where users connect their own Google or Microsoft accounts, use the OAuth 2.0 flow to generate this grant. You can check out our docs and use the Nylas SDKs for this.
There are a few ways to get a Nylas Notetaker to join meetings:
If you’re not setting up a calendar sync, you’ll invite the Notetaker by creating a Notetaker instance for a given meeting. To invite the bot, make a POST request with the meeting information. You’ll need to provide the meeting’s meeting_link. Here’s an example:
Join and record a meeting
const Nylas = require("nylas");
const nylas = new Nylas({
apiKey: "{NYLAS_API_KEY}",
});
async function createNotetaker() {
const response = await nylas.notetakers.create({
identifier: "{EMAIL}",
requestBody: {
meetingLink: "{MEETING_LINK}",
name: "My Notetaker",
},
});
console.log("Notetaker created:", response);
}
createNotetaker();
require 'nylas'
nylas = Nylas::Client.new(api_key: '{NYLAS_API_KEY}')
response = nylas.notetakers.create(
identifier: '{EMAIL}',
request_body: {
meeting_link: '{MEETING_LINK}',
name: 'My Notetaker'
}
)
puts "Notetaker created: #{response.inspect}"
from nylas import Client
nylas = Client(
api_key="{NYLAS_API_KEY}",
)
response = nylas.notetakers.create(
identifier="{EMAIL}",
request_body={
"meeting_link": "{MEETING_LINK}",
"name": "My Notetaker"
}
)
print(f"Notetaker created: {response}")
import com.nylas.NylasClient;
import com.nylas.models.*;
public class CreateNotetaker {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("{NYLAS_API_KEY}").build();
CreateNotetakerRequest request = new CreateNotetakerRequest.Builder()
.meetingLink("{MEETING_LINK}")
.name("My Notetaker")
.build();
Response<Notetaker> response = nylas.notetakers().create("{EMAIL}", request);
System.out.println("Notetaker created: " + response.getData());
}
}
curl --request POST "https://api.nylas.com/v3/grants/<GRANT_ID>/notetakers" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
--header "Content-Type: application/json" \
--data '{
"meeting_link": "<MEETING_URL>",
"join_time": "1732657774",
"notetaker_name": "Nylas Notetaker",
"meeting_settings": {
"video_recording": true,
"audo_recording": true,
"transcription": true,
}
}'
import com.nylas.NylasClient
import com.nylas.models.CreateNotetakerRequest
fun main() {
val nylas = NylasClient(apiKey = "{NYLAS_API_KEY}")
val request = CreateNotetakerRequest(
meetingLink = "{MEETING_LINK}",
name = "My Notetaker"
)
val response = nylas.notetakers().create("{EMAIL}", request)
println("Notetaker created: ${response.data}")
}
{
"request_id":"<REQUEST_ID>",
"data":{"id":"<NOTETAKER_ID>",
"grant_id":"<GRANT_ID>",
"name":"Nylas Notetaker",
"state":"connecting",
"meeting_link":"<MEETING_LINK>",
"meeting_provider":"Google Meet",
"meeting_settings":{
"video_recording":true,
"audio_recording":true,
"transcription":true,
}
"join_time":1741210298
}
To set up a calendar sync with the Nylas Notetaker, make a PUT request to update a specific calendar’s settings using the /v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID> endpoint.
In the request body, you define the notetaker configuration, including rules like event_selection (e.g., “internal,” “external” meetings) and participant_filter (e.g., minimum/maximum number of attendees).
Syncing with calendar events
const Nylas = require("nylas");
const nylas = new Nylas({
apiKey: "{NYLAS_API_KEY}",
});
async function createNotetaker() {
const response = await nylas.notetakers.create({
identifier: "{GRANT_ID}",
requestBody: {
meetingLink: "{MEETING_LINK}",
name: "My Notetaker",
},
});
console.log("Notetaker created:", response);
}
createNotetaker();
require 'nylas'
nylas = Nylas::Client.new(api_key: '{NYLAS_API_KEY}')
response = nylas.notetakers.create(
identifier: '{GRANT_ID}',
request_body: {
meeting_link: '{MEETING_LINK}',
name: 'My Notetaker'
}
)
puts "Notetaker created: #{response.inspect}"
from nylas import Client
nylas = Client(
api_key="{NYLAS_API_KEY}",
)
response = nylas.notetakers.create(
identifier="{GRANT_ID}",
request_body={
"meeting_link": "{MEETING_LINK}",
"name": "My Notetaker"
}
)
print(f"Notetaker created: {response}")
import com.nylas.NylasClient;
import com.nylas.models.*;
public class CreateNotetaker {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("{NYLAS_API_KEY}").build();
CreateNotetakerRequest request = new CreateNotetakerRequest.Builder()
.meetingLink("{MEETING_LINK}")
.name("My Notetaker")
.build();
Response<Notetaker> response = nylas.notetakers().create("{GRANT_ID}", request);
System.out.println("Notetaker created: " + response.getData());
}
}
curl --request POST "https://api.nylas.com/v3/grants/<GRANT_ID>/notetakers" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
--header "Content-Type: application/json" \
--data '{
"meeting_link": "<MEETING_URL>",
"join_time": "1732657774",
"notetaker_name": "Nylas Notetaker",
"meeting_settings": {
"video_recording": true,
"audo_recording": true,
"transcription": true,
}
}'
import com.nylas.NylasClient
import com.nylas.models.CreateNotetakerRequest
fun main() {
val nylas = NylasClient(apiKey = "{NYLAS_API_KEY}")
val request = CreateNotetakerRequest(
meetingLink = "{MEETING_LINK}",
name = "My Notetaker"
)
val response = nylas.notetakers().create("{GRANT_ID}", request)
println("Notetaker created: ${response.data}")
}
Once your meeting is done, the Notetaker will leave and start processing your recording to generate a transcription. You can get these files…
1. In real-time via webhook notifications: In the Nylas dashboard or via API, you need to register a webhook URL (an endpoint on your server) and specify the events you would like to receive (Notetaker supports a few events). If you’ve subscribed to the notetaker.media webhook event, Nylas will send a notification to your webhook URL when the transcription and recording are ready. The webhook payload will include temporary URLs for the video recording and the transcription file.
2. On-demand via API request: Access the recording and transcript by making a GET request to the Notetaker media endpoint. This request will return JSON containing URLs for the recording and transcript.
Get meeting recordings and transcriptions
const Nylas = require("nylas");
const nylas = new Nylas({
apiKey: "{NYLAS_API_KEY}",
});
async function listNotetakers() {
const response = await nylas.notetakers.list({
identifier: "{GRANT_ID}",
});
console.log("Notetakers:", response.data);
}
listNotetakers();
require 'nylas'
nylas = Nylas::Client.new(api_key: '{NYLAS_API_KEY}')
response = nylas.notetakers.list(
identifier: '{GRANT_ID}'
)
puts "Notetakers:"
response.data.each do |notetaker|
puts "- #{notetaker[:id]}: #{notetaker[:name]} (Status: #{notetaker[:status]})"
end
from nylas import Client
nylas = Client(
api_key="{NYLAS_API_KEY}",
)
response = nylas.notetakers.list(
identifier="{GRANT_ID}"
)
print(f"Notetakers: {response.data}")
import com.nylas.NylasClient;
import com.nylas.models.*;
public class ListNotetakers {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("{NYLAS_API_KEY}").build();
ListResponse<Notetaker> response = nylas.notetakers().list("{GRANT_ID}");
System.out.println("Notetakers:");
for (Notetaker notetaker : response.getData()) {
System.out.println("- " + notetaker.getId() + ": " + notetaker.getName() +
" (Status: " + notetaker.getStatus() + ")");
}
}
}
curl --request GET "https://api.nylas.com/v3/grants/<GRANT_ID>/notetakers/<NOTETAKER_ID>/media" \
--header "Authorization: Bearer <NYLAS_API_KEY>
import com.nylas.NylasClient
fun main() {
val nylas = NylasClient(apiKey = "{NYLAS_API_KEY}")
val response = nylas.notetakers().list("{GRANT_ID}")
println("Notetakers:")
response.data.forEach { notetaker ->
println("- ${notetaker.id}: ${notetaker.name} (Status: ${notetaker.status})")
}
}
{
"request_id":"<REQUEST_ID>",
"data":{
"recording":{"url":"<URL>","size":0, ...more details...},
"transcript":{"url":"<URL>","size":0, ...more details...}
}
}
If you’re competing in a saturated market, rushing through the build of a feature isn’t an option. User-friendly meeting intelligence isn’t just about starting a recording. Recordings need to be handled in a secure environment and they need to be timely, easy to work with, and feasible at scale (because meetings are not a rare occasion). Most product teams hit their first set of roadblocks after building a meeting bot because…
Keep these top of mind before going live with a cross-platform meeting bot:
Zoom, Teams, and Google Meet each enforce unique policies around recording, consent, and organization-level approvals. Bots must trigger native consent dialogs or validate permissions ahead of time to avoid legal and security risks.
Meeting recordings often contain PII, customer information, and sensitive internal conversations. You need to store media files using encrypted, access-controlled services like AWS S3. But beyond that, you need secure key management, access controls, token protection, OAuth handling, and audit logs to avoid client-side vulnerabilities.
Running full integration tests on live meetings can trigger API rate limits, cloud storage fees, and recording usage charges. You can simulate joins with dummy meeting URLs to catch integration errors and edge cases with each platform before production.
Each platform has API rate limits that are easy to hit when bots are joining meetings in bulk or syncing with calendars. You’ll want to make sure your app implements appropriate retry logic to stay within these thresholds without disrupting the end-user experience.
Use your UX to inform customers and make them feel secure. Display clear indicators when a bot joins and starts recording, provide status updates, and include confirmation prompts in your app so users are always in control of the recording process.
Having strong integrations is critical for delivering value in any SaaS platform built on communications data. But it also takes time to get these foundations right. That’s why many teams rely on API providers to standardize and offload the work around these structural components
The Nylas Notetaker helps SaaS applications look beyond basic meeting recording. Developers can build tightly integrated communication platforms with a secure and reliable environment for email, calendar, and cross-platform meeting data.
Contact our team to learn how you can use our meeting recorder API to build your app’s next meeting feature.