Skip to navigation

Google Meet Bots

How MeetStream bots join, wait, record and leave Google Meet calls
View as Markdown

Send a bot into any Google Meet call with one API request. Guest bots need no app, no OAuth and no admin setup.

curl -X POST "https://api.meetstream.ai/api/v1/bots/create_bot" \
-H "Authorization: Token <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"meeting_link": "https://meet.google.com/abc-defg-hij",
"bot_name": "Notetaker",
"video_required": false
}'

Need a meeting to test against? Open meet.new while signed in to Google. You are the host of that meeting, so you can admit your own bot.

Google Meet at a glance

TopicOn Google Meet
SetupNone for guest bots. Signed-in bots need a one-time Google Workspace SSO setup.
Link formathttps://meet.google.com/abc-defg-hij (details)
Join modesGuest (default) or signed in to a Google Workspace account
AdmissionDecided by the meeting’s access settings. Guest bots usually have to ask to join.
waiting_room_timeout60 to 600 seconds, default 600
Recording startAs soon as the bot is in the meeting. There is no host permission prompt on Meet.
Mixed audioAlways recorded
Per-participant audioUp to 16 speakers
Per-participant videoUp to 16 streams, screen shares included
Recording layoutgrid_view (default) or speaker_view, composited after the call
ChatRead and send
Native captionsmeeting_captions provider, English
Live transcription5 streaming providers plus native captions
Pause and resumeSupported
Platform value in the APIGMeet (for example GET /api/v1/bots?platform=GMeet)

Send the standard meeting-code link. MeetStream checks the host when you create the bot, and the bot checks the link again before it joins.

Link you sendWhat happens
https://meet.google.com/abc-defg-hijSupported. This is the format to use.
https://meet.google.com/abc-defg-hij?authuser=1 (any query string)Accepted. The bot drops everything after the meeting code and joins https://meet.google.com/abc-defg-hij.
http://meet.google.com/abc-defg-hijAccepted by the API, but the bot then stops with status ERROR and the message Error: Invalid Google Meet URL. Always send https://.
https://meet.google.com/lookup/<name>Use the meeting-code link. MeetStream opens /lookup/ links as given and does not resolve them.
https://g.co/meet/... short linksRejected with HTTP 400: the host must be meet.google.com. Expand the short link first.
https://meet.google.com/ or a Google page such as /signin or /aboutRejected with HTTP 400: meeting_link looks like the GMeet site root or a marketing page, not a meeting URL.
Dial-in numbers and PINsSend the https://meet.google.com/... link instead. The bot joins with the meeting link.

How the bot joins

no (default) yes sign-in fails signed in a page that blocks joining Join now or Ask to join admitted, or no approval needed host denies waiting_room_timeout passes POST /create_bot google_meet.login_required? Open the link as a guest andenter bot_name Sign in to a Google Workspaceaccount from your domain Failed: GoogleSignInFailed (noguest fallback) Open the link as that Google account What does Meet show? Failed: InvalidMeetingLink,MeetingRestricted,SignInRequired, ... Bot clicks join: bot.in_waiting_room bot.inmeeting, then bot.recording Denied: HostDenied NotAllowed: WaitingRoomTimeout

Guest or signed in?

Guest bot (default)Signed-in bot
RequestNothing extragoogle_meet.login_required: true plus google_login_domain
SetupNoneDedicated Google Workspace, SSO profile pointing at MeetStream, logins added in the dashboard
Name shown in Meetbot_nameThe Google account’s name. bot_name is not used.
Profile pictureMeet’s default avatarThe Google account’s photo
AdmissionMust ask to join unless the meeting is OpenJoins directly when its email is on the calendar invite (Trusted or Restricted meetings), unless the Waiting room is on
Meetings that require a Google accountEnds with SignInRequired. Send a signed-in botCan join
If something goes wrongJoin errors belowSame, plus GoogleSignInFailed. It never falls back to joining as a guest.

Set up signed-in bots with the Google Signed-In Bots guide. On the MeetStream side, you register your bot domain under Integrations > Signed Bots, then add each bot account and its SSO key pair.

MeetStream Add domain dialog for Google Meet signed bots, filled in with the domain example.com and the name Example Bots
Registering a bot domain for signed-in Google Meet bots: domain (1), name (2), login mode (3), then Add domain (4).

Display name, camera and microphone

  • Name. A guest bot shows bot_name (default MeetStream). A signed-in bot shows its Google account name instead.
  • Camera. The bot’s camera tile shows your bot_image_url. Change it during the call with Send Image.
  • Microphone. The bot’s microphone only carries audio that you or your agent send (for example initial_audio or an agent’s voice). It is silent otherwise.
  • Hiding the bot. Tile layout is chosen by each viewer in Meet, so no API can hide the bot from everyone. A clear bot_name and a bot_message that explains why the bot is there work best.

Google’s transcription and Gemini notices

When a meeting already has Google’s own transcription or “Gemini is taking notes” turned on, Meet shows a notice before joining. The bot accepts that notice and continues to join, just as a person clicking Join now would.

Admission and the lobby

The meeting’s access settings, the organizer’s Google Workspace policies and the people in the call decide who Google Meet lets in. MeetStream controls how long the bot waits and how it reports each outcome.

How Meet decides

Meeting access is set by the host in Host controls > Meeting access (in the call) or in the Calendar event under Video call options > Host controls. Google defines three access types (Google’s description):

Meeting settingGuest botSigned-in bot on the calendar inviteSigned-in bot not on the invite
Open: anyone with the link can joinJoins directlyJoins directlyJoins directly
Trusted: the organization and calendar invitees join directly, everyone else knocksAsks to joinJoins directlyAsks to join
Restricted: only calendar invitees and people added by a host join directly, everyone else knocksAsks to joinJoins directlyAsks to join
”Anyone with the meeting link can ask to join” turned off (Trusted or Restricted)Turned away without the host seeing a requestJoins directlyTurned away
Waiting room turned on in the Calendar eventWaits until a host brings it inWaits until a host brings it inWaits until a host brings it in

Two more things can stop a bot before any of this applies:

  • The organizer’s Workspace admin can limit who joins the organization’s meetings, for example to signed-in Google accounts only, or to people in the organization. A guest bot then ends with SignInRequired, MeetingRestricted or CantJoinCall. A signed-in bot helps only if the policy allows its account.
  • Someone must be there to admit. A bot that asks to join can only be let in once the host (or, depending on settings, another eligible participant) is in the call.

Google states that anonymous users and third-party note takers that use “Ask to join” are automatically denied when the “Anyone with the meeting link can ask to join” option is off. In that case no admission prompt ever reaches the host.

Who can admit the bot

  • With Host management on, only the host and co-hosts can admit people. Other attendees may never see the bot’s request, which is why a bot can look like it “never arrived” while MeetStream reports it waiting.
  • With Host management off, people from the organizer’s organization who are in the call can usually respond to join requests too.
  • With the Waiting room on, the host uses Bring in or Bring everyone in, or turns on Bring in automatically so waiting participants join when the host does (Google’s Waiting room help).

Get on the calendar invite

For Trusted and Restricted meetings, the reliable way to skip the lobby is a signed-in bot whose Google account email is a guest on the Calendar event. Pin the bot to that account with sign_in_email (and keep strict_email: true) so MeetStream never picks a different login. A Waiting room still holds every participant, invited or not.

What MeetStream reports while waiting

  • bot.in_waiting_room fires as soon as the bot clicks Ask to join or Join now. When no approval is needed it is followed within seconds by bot.inmeeting.
  • The bot waits up to automatic_leave.waiting_room_timeout seconds: 60 to 600 on Google Meet, default 600. A higher value returns HTTP 400 waiting_room_timeout for GMeet must not exceed 600 seconds.
  • For a scheduled bot, the wait is measured from the scheduled start time, so arriving a few seconds early does not shorten it.
MeetStream bot status timeline for a Google Meet bot: Joining, In Waiting Room, In Meeting, Recording, Leaving, Stopped, Processing Audio, Processing Video, Uploading and Done
A bot that was admitted: In Waiting Room (1), In Meeting (2) and Recording (3) seconds apart, then post-call processing to Done (4).

Nobody admits the bot

When waiting_room_timeout passes, the bot clicks Leave, which withdraws its request so the host is not left with a stale prompt. Then:

FieldValue
StatusLeaving, then NotAllowed
MessageFailed: Not admitted to meeting
ErrorReason (Get Bot Details)WaitingRoomTimeout
Webhooksbot.leaving, then event: bot.stopped with bot_event: bot.notallowed, bot_status: NotAllowed, status_code: 500
DashboardTimeline shows In Waiting Room, Leaving, Not Admitted. The status badge reads Not Allowed.

If the meeting link or code changes while the bot waits, the bot reports the same WaitingRoomTimeout outcome.

MeetStream bot detail page for a Google Meet bot with the timeline Joining, In Waiting Room, Leaving and Not Admitted, and final status NotAllowed
A Google Meet bot that timed out in the lobby: it waited (1) for about ten minutes, was not admitted (2) and finished as NotAllowed (3).

The host denies the bot

When someone clicks Deny entry, Meet shows “You’ve been denied entry to this meeting” or “Someone in the call denied your request to join”. The bot reports:

FieldValue
StatusLeaving, then Denied
MessageFailed: Host denied join
ErrorReasonHostDenied
Webhooksbot.leaving, then event: bot.stopped with bot_event: bot.denied, bot_status: Denied, status_code: 500
DashboardTimeline step Rejected

For step-by-step fixes, see Google Meet Lobby & Admission Troubleshooting.

Join errors

Pages that block joining

When Meet shows one of these pages instead of the join screen, the bot stops right away with status Failed. The terminal webhook has event: bot.stopped, bot_event: bot.failed, bot_status: Failed and a lowercase failure_reason.

What Meet showsfailure_reasonErrorReasonMessageWhat to do
”You can’t join this video call” (or “…this meeting”, “…this call”)cant_join_callCantJoinCallFailed: You can't join this video callRetried automatically first (see below). Check that people outside the organization, and people who aren’t signed in, may ask to join. Otherwise use a signed-in bot on the invite.
”Check your meeting code”, “Invalid video call name”, “The meeting code that you entered doesn’t work”, “Meeting not found”, “The video call wasn’t found”invalid_meeting_linkInvalidMeetingLinkFailed: Invalid meeting linkCheck the link for typos and send a fresh https://meet.google.com/abc-defg-hij link.
”This meeting has not started”meeting_not_startedMeetingNotStartedFailed: Meeting has not startedStart the meeting first, or check whether the organizer requires the host to join before anyone else.
”This meeting has ended”, “Your meeting code has expired”meeting_endedMeetingEndedFailed: Meeting has endedUse the link for a current meeting.
”Access to this meeting is restricted”, “You don’t have permission to join”, “Meeting access denied”, “Only people invited by the organizer”meeting_restrictedMeetingRestrictedFailed: Meeting access is restrictedInvite a signed-in bot’s email to the event, or relax the meeting access setting.
A Google sign-in page instead of the meetingsign_in_requiredSignInRequiredFailed: Sign in requiredThe organization only admits signed-in Google accounts. Use a signed-in bot.
(Signed-in bots) Google sign-in did not completegoogle_sign_in_failedGoogleSignInFailedFailed: Configured Google sign-in failedCheck the SSO setup and the login. See troubleshooting.

ErrorReason is returned by Get Bot Details. The full list of statuses and reasons across platforms is in the Bot status and error code reference.

Automatic retries

You don’t need to create a new bot for these; the same bot retries.

  • “You can’t join this video call”. This page is sometimes temporary, so the bot retries the join up to three more times before it stops with CantJoinCall.
  • Temporary Meet or network errors. “Something went wrong”, “There was a problem connecting to the meeting”, “Can’t connect to the meeting”, “You lost your network connection” and similar messages get up to 3 attempts in total. If all fail, the bot stops with status Failed, ErrorReason MeetTransientError or NetworkError, and a message such as Failed: Google Meet reported a temporary error (after 3 attempts).

Other join failures

SituationStatusErrorReason
http:// linkERROR (message Error: Invalid Google Meet URL)none
Meet’s join button never appearedFAILEDClickJoinFailed
The bot made no progress toward the lobby for about 5 minutesNotAllowedJoinHang
The bot was still Joining after 60 minutesNotAllowedJoinTimeout

Leaving the meeting

Why a bot left mid-call

What happenedErrorReasonStatusMessage
Meet lost the connection (“You lost your network connection”, “Trying to reconnect”)ConnectionLostStoppedBot lost network connection to Google Meet
A participant removed the bot (“You’ve been removed from the meeting”)KickedByHostKicked (webhook: bot_event: bot.kicked, bot_status: Stopped)Bot was removed from the meeting by a participant
Meet says the bot left (“You left the meeting”)LeftVoluntarilyStoppedBot left the meeting
The meeting ended (“This meeting has ended”)MeetingEndedByHostStoppedMeeting ended
Meeting audio stopped reaching the botMediaConnectionsLostStoppedBot lost media connections to Google Meet
The bot’s page was no longer on Google MeetMeetOffDomainStoppedBot is no longer on a Google Meet URL
Meet showed only its generic post-call screen (“Return to home screen”, “Call ended”)MeetingExitUnknownStoppedBot left the meeting (post-call screen)

Planned leaves (your API call or an automatic-leave rule) end with status Stopped and no ErrorReason: Bot stopped via API request (Remove Bot), Bot exited the call: No one joined the meeting, Bot exited the call: Everyone left the meeting, and Bot exited the call: <reason> for other automatic-leave rules. In every case post-call processing runs as usual.

Automatic leave on Google Meet

All fields go in automatic_leave. Full behavior, including bot detection, is in Automatic Leave Configurations.

FieldRange (seconds)Default on MeetBehavior on Meet
waiting_room_timeout60 to 600600Lobby wait, see above
no_one_joined_timeout60 to 1800600Starts once the bot is in the meeting (or at the scheduled start, if later) and nobody else is there
everyone_left_timeout60 to 1800600Starts after at least one other participant was seen and then everyone else left
voice_inactivity_timeout60 to 1800600, applied even if you don’t set itStarts after admission and ignores the first 30 seconds. The bot leaves after this long without detected speech.
in_call_recording_timeout600 to 1800014400Accepted. On Google Meet, set the maximum length with everyone_left_timeout, voice_inactivity_timeout or a remove_bot call.
bot_detectionsee guideoffSupported. Leaves when every other participant’s name matches your matches list.

recording_permission_denied_timeout is Zoom only and has no effect on Meet.

Webhooks on Google Meet

A bot that joins and records normally sends:

bot.joining → bot.in_waiting_room → bot.inmeeting → bot.recording → bot.leaving → bot.stopped → post-call events → bot.done

Scheduled bots send bot.scheduled first. Every terminal webhook uses event: bot.stopped; the cause is in bot_event (bot.stopped, bot.kicked, bot.denied, bot.notallowed or bot.failed). Branch on bot_event.

{
"bot_id": "7b61cc61-0000-4000-8000-000000000000",
"event": "bot.stopped",
"bot_event": "bot.failed",
"bot_status": "Failed",
"message": "Failed: Invalid meeting link",
"failure_reason": "invalid_meeting_link",
"timestamp": "2026-09-23T16:48:31.000Z"
}
Terminal statusbot_event
Stoppedbot.stopped
Kicked (sent as bot_status: Stopped)bot.kicked
Failed (a meeting page blocked the join, with failure_reason)bot.failed
Deniedbot.denied
NotAllowedbot.notallowed
ERROR, FAILEDbot.failed

Signed-in bots also include profile_image_url (the Google account’s photo) when available. Payloads are signed with X-MeetStream-Signature; see Webhooks and Events and Verifying Webhook Signatures.

Media on Google Meet

CapabilityHow to use itGoogle Meet details
Mixed audioAlways recordedAlso streamed live with live_audio_required.websocket_url; each frame carries the active speaker’s ID and name. See Real-time Audio Streaming.
Per-participant audioaudio_separate_streams: trueUp to 16 speakers. On only when you set audio_separate_streams: true, or when you record video with video_layout: speaker_view. Audio goes to a speaker’s file only when Meet identifies the speaker. Other audio stays in the mixed recording. Guide
Per-participant videovideo_separate_streams: true with video_required: trueUp to 16 streams, screen shares included. Guide
Recording layoutrecording_config.video_layoutgrid_view (default when video_required is true) or speaker_view. Both are composited after the call from the per-participant streams.
Screen shareAutomatic with videoEach share is its own stream, and screenshare_on / screenshare_off appear in participant events.
Read chatAutomaticGet Bot Chats, or live participant_events.chat_message through recording_config.realtime_endpoints
Send chatSend Message, bot_messageMessages are posted one at a time. bot_message is posted a few seconds after the bot is in the call. Guide
Send imageSend ImageReplaces the bot’s camera image, animated GIFs included
Initial audioinitial_audio: {"url": "https://...", "wait_seconds": 0}Plays once after admission. url must be HTTPS; wait_seconds 0 to 60. Google Meet and Teams only.
Participants and speakersParticipants & Speaker TimelineJoin, leave, speech, webcam and screen-share events. The speaker timeline comes from Meet’s audio levels. Use deviceId as the stable participant ID.
Pause and resumePause / ResumeSee below

Live transcription on Meet

Set a streaming provider in recording_config.transcript.provider and a live_transcription_required.webhook_url; the webhook is required for every _streaming provider. Google Meet supports:

Provider keyNotes
deepgram_streamingDeepgram Streaming
assemblyai_streamingAssemblyAI Streaming
sarvam_streamingSarvam, for Indian languages
jigsawstack_streamingJigsawStack
meetstream_streamingMeetStream Engine, no provider key needed
meeting_captionsMeet’s own captions, see below

Speaker names in live transcripts come from Meet’s active speaker. Live transcript and caption POSTs do not include the X-MeetStream-Signature header. Put a secret token in the webhook URL and check it on each request. More in Live Transcription.

Native captions

With recording_config.transcript.provider.meeting_captions, the bot turns on Meet’s captions after it is admitted and records them. Meet captions are recorded in English. For other languages, use sarvam_streaming or a post-call provider. If captions do not switch on at first, the bot tries again every 15 seconds and stays in the meeting.

  • With a live_transcription_required.webhook_url, each caption is POSTed as {"type": "caption", "bot_id": "...", "caption": {"text", "speakerName", "speakerDisplayName", "deviceId", ...}}.
  • After the call, Get Bot Details returns caption_file.available and a caption_file.download_url (valid for 1 hour) when a caption file was saved.

See Meeting Captions.

Pause and resume

POST /api/v1/bots/{bot_id}/pause_recording and /resume_recording work on Google Meet (guide). While paused, the recording keeps its real duration but contains black video and silence, per-participant audio included. A second pause (or resume) changes nothing and returns HTTP 409 with "status": "no_op".

Native captions, chat capture and participant events continue during a pause. Remove the bot to keep captions, chat and participant events out of a paused stretch.

Find Meet bots in the dashboard

All Bots lists every bot with its platform and status. Filter by Google Meet to see only Meet bots; open a bot to see its status timeline.

MeetStream All Bots table filtered to Google Meet bots, with Platform and Status columns highlighted
Filter by platform (1), check the Platform column (2) and the Status badge (3). A lobby timeout shows as Not Allowed.

Good to know

  • Send https://meet.google.com/<code> links.
  • waiting_room_timeout is 60 to 600 seconds on Meet.
  • Meetings that admit only signed-in accounts need a signed-in bot that the meeting’s policy allows.
  • Set the maximum length with remove_bot or the timers above.
  • voice_inactivity_timeout is 600 seconds when you do not set it.
  • Meet captions are recorded in English.
  • Remove the bot to keep captions, chat and participant events out of a paused stretch.
  • Per-participant audio and video record up to 16 streams each.
  • The bot stays in the main room.
  • A signed-in bot always joins with its Google account. If sign-in fails, the bot ends with GoogleSignInFailed.

Calendar auto-join

Connect a Google or Outlook calendar and MeetStream can schedule a bot for every event with a Meet link. See Scheduling Bots and Google Calendar OAuth Setup.

FAQ

Someone who can admit has to let it in. With Host management on, only the host and co-hosts see the request; other attendees don’t, so to them it looks like the bot never arrived while MeetStream reports bot.in_waiting_room. Make sure the organizer or a co-host is in the call, or use a signed-in bot on the calendar invite. Troubleshooting steps: Lobby & Admission.

Nobody admitted it within waiting_room_timeout (default 600 seconds, the Google Meet maximum). ErrorReason is WaitingRoomTimeout. The bot withdraws its request when it leaves. Lower the timeout for ad-hoc calls, or remove the need for admission with a signed-in, invited bot.

Meet showed “You can’t join this video call” on every attempt (the bot retries up to three more times first). This usually means the meeting doesn’t let people from outside the organization, or people who aren’t signed in, ask to join. Ask the organizer to check Host controls > Meeting access, or use a signed-in bot whose email is on the invite.

The organizer’s Google Workspace only admits signed-in Google accounts, so a guest bot is sent to Google’s sign-in page. Use a signed-in bot.

The meeting is Open, or the bot is a signed-in account on the calendar invite of a Trusted or Restricted meeting. You still get bot.in_waiting_room, followed within seconds by bot.inmeeting.

The Calendar event has the Waiting room turned on, which holds everyone until a host brings them in. Also check that the invited email is exactly the login the bot used: set sign_in_email with strict_email: true to pin it.

It is a signed-in bot. Meet shows the Google account’s name and photo, and bot_name is not used. Rename the account in Google Admin to change it.

On Google Meet, voice_inactivity_timeout defaults to 600 seconds even if you don’t set it. Set a higher value (up to 1800) for meetings with long silences.

On Google Meet, set the maximum length with everyone_left_timeout, voice_inactivity_timeout or a Remove Bot call from your backend.

The link started with http://. The bot joins https://meet.google.com/... links. Send the https:// version.

Meet captions are recorded in English. For other languages, use sarvam_streaming or a post-call provider.

The bot leaves with status Stopped (usually ErrorReason MeetingEndedByHost), and post-call processing and webhooks run as normal.