Observe meeting events with Python and the Google Meet REST API

This tutorial shows how to use the Google Meet REST API along with theGoogle Workspace Events API and Google Cloud Pub/Sub to observe and react to eventsin a Meet meeting space. The sample application records whenconferences start and end, when participants join or leave, and when anygenerated meeting artifacts are available.

Instead of subscribing to a specific meeting space, you can instead subscribe toa Meet user to receive events for any meeting space that theuser owns or organizes. For details, seeSubscribe to Google Meet eventsin the Google Workspace Events API documentation.

Prerequisites

If you need any of these prerequisites turned on for your organization, askyour Google Workspace administrator to turn them on:

Prepare your environment

This section shows how to create and configure your local environment and theGoogle Cloud project for this tutorial.

Create a working directory and Python virtual environment

To create and activate a newvirtualenvironment, run the followingcommands in your terminal.

Linux/macOS

mkdirmeet-tutorialcdmeet-tutorialpython3-mvenvenvsourceenv/bin/activate

Windows (command prompt)

mkdirmeet-tutorialcdmeet-tutorialpython3-mvenvenvenv/bin/activate.bat

Windows (PowerShell)

mkdirmeet-tutorialcdmeet-tutorialpython3-mvenvenvenv/bin/activate.ps1

Create a Google Cloud project

Google Cloud console

  1. In the Google Cloud console, go to Menu>IAM & Admin>Create a Project.

    Go to Create a Project

  2. In theProject Name field, enter a descriptive name for your project.

    Optional: To edit theProject ID, clickEdit. The project ID can't be changed after the project is created, so choose an ID that meets your needs for the lifetime of the project.

  3. In theLocation field, clickBrowse to display potential locations for your project. Then, clickSelect.
  4. ClickCreate. The Google Cloud console navigates to the Dashboard page and your project is created within a few minutes.

gcloud CLI

In one of the following development environments, access the Google Cloud CLI (gcloud):

  • Cloud Shell: To use an online terminal with the gcloud CLI already set up, activate Cloud Shell.
    Activate Cloud Shell
  • Local Shell: To use a local development environment,install andinitialize the gcloud CLI.
    To create a Cloud project, use thegcloud projects create command:
    gcloud projects createPROJECT_ID
    ReplacePROJECT_ID by setting the ID for the project you want to create.

Enable billing for the Google Cloud project

If you're unable to link a billing account, you don't have thepermissions needed to make this change. For more information, seePermissions required to enable billing.

Google Cloud console

  1. In the Google Cloud console, go toBilling. ClickMenu>Billing>My Projects.

    Go to Billing for My Projects

  2. InSelect an organization, choose the organization associated with your Google Cloud project.
  3. In the project row, open theActions menu (), clickChange billing, and choose the Cloud Billing account.
  4. ClickSet account.

gcloud CLI

  1. To list available billing accounts, run:
    gcloud billing accounts list
  2. Link a billing account with a Google Cloud project:
    gcloud billing projects linkPROJECT_ID --billing-account=BILLING_ACCOUNT_ID

    Replace the following:

    • PROJECT_ID is theProject ID for the Cloud project for which you want to enable billing.
    • BILLING_ACCOUNT_ID is thebilling account ID to link with the Google Cloud project.

Set up authentication and authorization

Authentication and authorization lets the app access Meet REST APIresources. User authorization is required to call the Meet REST API.This section hows you how to configure user credentials and requestauthorization.

Configure the OAuth consent screen and choose scopes

The following steps suggest placeholder information to configuretheOAuth consent screen foryour app. Before publishing the app externally, update this information.

  1. In the Google Cloud console, go to Menu>Google Auth platform>Branding.

    Go to Branding

  2. If you have already configured the Google Auth platform, you can configure the following OAuth Consent Screen settings inBranding,Audience, andData Access. If you see a message that saysGoogle Auth platform not configured yet, clickGet Started:
    1. UnderApp Information, inApp name, enterMeet REST API Tutorial.
    2. InUser support email, choose a support email address where users can contact you if they have questions about their consent.
    3. ClickNext.
    4. UnderAudience, selectInternal. If unable to create an internal app, selectExternal.
    5. ClickNext.
    6. UnderContact Information, enter anEmail address where you can be notified about any changes to your project.
    7. ClickNext.
    8. UnderFinish, review theGoogle API Services User Data Policy and if you agree, selectI agree to the Google API Services: User Data Policy.
    9. ClickContinue.
    10. ClickCreate.
    11. If you selectedExternal for user type, add test users:
      1. ClickAudience.
      2. UnderTest users, clickAdd users.
      3. Enter your email address and any other authorized test users, then clickSave.
  3. ClickData Access>Add or Remove Scopes. A panel appears with a list of scopes for each API that you've enabled in your Google Cloud project.
  4. UnderManually add scopes, paste the following scopes:
    • https://www.googleapis.com/auth/meetings.space.created
  5. ClickAdd to Table.
  6. ClickUpdate.
  7. After selecting the scopes required by your app, clickSave.

For more information about configuring OAuth consent, seeGet started with the Google Auth platform.

Create a client ID

The client ID acts as credentials for your application during the OAuth 2.0flows. Since the app runs locally, create a desktop client ID.

  1. In the Google Cloud console, go to Menu>Google Auth platform>Clients.

    Go to Clients

  2. ClickCreate Client.
  3. ClickApplication type>Desktop app.
  4. In theName field, type a name for the credential. This name is only shown in the Google Cloud console.
  5. ClickCreate.

    The newly created credential appears under "OAuth 2.0 Client IDs."

Install the Google auth libraries

Install the Google auth libraries:

pipinstallgoogle-authgoogle-auth-oauthlib

Execute authorization

The Meet REST API requires user credentials in the form of an OAuth 2.0access token. In this section, you implement the OAuth 2.0 flow to request anaccess token and a refresh token for the user.

  1. In your working directory, create the filemain.py and add the followingcontents:

    importosimportjsonfromgoogle.auth.transportimportrequestsfromgoogle.oauth2.credentialsimportCredentialsfromgoogle_auth_oauthlib.flowimportInstalledAppFlowdefauthorize()->Credentials:"""Ensure valid credentials for calling the Meet REST API."""CLIENT_SECRET_FILE="./client_secret.json"credentials=Noneifos.path.exists('token.json'):credentials=Credentials.from_authorized_user_file('token.json')ifcredentialsisNone:flow=InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE,scopes=['https://www.googleapis.com/auth/meetings.space.created',])flow.run_local_server(port=0)credentials=flow.credentialsifcredentialsandcredentials.expired:credentials.refresh(requests.Request())ifcredentialsisnotNone:withopen("token.json","w")asf:f.write(credentials.to_json())returncredentialsUSER_CREDENTIALS=authorize()
  2. To run the code, both the client ID and the secret created earlier arerequired. Copy the downloaded client secret file to the project workingdirectory and rename it asclient_secret.json.

  3. If you'd like to test how authorization works, run the following command.The app prompts for authorization and creates atoken.json file in theproject working directory after the request is approved.

    python3main.py

Add the Meet REST API

Now that the authorization code is complete, it's time to enable and call theMeet REST API.

Enable the APIs

While this section is focused on the Meet REST API, this tutorial also usesGoogle Cloud Pub/Sub and Google Workspace Events API.

Google Cloud console

  1. In the Google Cloud console, enable the Google Meet REST API, theGoogle Workspace Events API, and Google Cloud Pub/Sub.

    Enable theAPIs

  2. Confirm that you're enabling the APIs in the correctCloud project, then clickNext.

  3. Confirm that you're enabling the correct APIs, then clickEnable.

gcloud CLI

  1. If necessary, set the current Cloud project to the one youcreated with thegcloud config set project command:

    gcloudconfigsetprojectPROJECT_ID

    ReplacePROJECT_ID with theProject ID of theCloud project you created.

  2. Enable the Google Meet REST API, the Google Workspace Events API, andGoogle Cloud Pub/Sub with thegcloud services enable command:

    gcloudservicesenablemeet.googleapis.comworkspaceevents.googleapis.compubsub.googleapis.com

Install the Meet REST API client library

Follow these steps to install the Meet REST API client library:

  1. Run the command:

    pipinstallgoogle-apps-meet
  2. Edit themain.py file to import the client:

    fromgoogle.appsimportmeet_v2asmeet

Create a space

Now that the Meet REST API is available, define a function to create ameeting space that can be subscribed to.

Editmain.py and add:

defcreate_space()->meet.Space:"""Create a meeting space."""client=meet.SpacesServiceClient(credentials=USER_CREDENTIALS)request=meet.CreateSpaceRequest()returnclient.create_space(request=request)

Subscribe to events

To receive events about a meeting space, you create a subscription using theGoogle Workspace Events API. You must also create and subscribe to aGoogle Cloud Pub/Sub topic which serves as the notification endpoint where yourapp receives the events.

Configure Google Cloud Pub/Sub

To create and subscribe to a Pub/Sub topic:

Google Cloud console

  1. In the Google Cloud console, go to Menu>Pub/Sub.

    Go to Pub/Sub

    Make sure that the Cloud project for your app is selected.

  2. ClickCreate topic and do the following:
    1. Enterworkspace-events as the topic name.
    2. LeaveAdd a default subscription selected.
    3. ClickCreate. Your full topic name is formatted asprojects/{project}/topics/{topic}. Make a note of this name for use in later steps.
  3. Grant access to publish Pub/Sub messages to your topic:
    1. On the side panel, open thePermissions tab.
    2. ClickAdd Principal.
    3. InNew principals, entermeet-api-event-push@system.gserviceaccount.com.
    4. InAssign roles, selectPub/Sub Publisher.
    5. ClickSave.

    It can take a few minutes to update the permissions for your topic.

gcloud CLI

  1. In your Cloud project, create a topic by running the following:
    gcloud pubsub topics create workspace-events

    The output displays the full topic name, formatted asprojects/{project}/topics/{topic}. Make a note of this name for use in later steps.

  2. Grant access to publish messages to your topic:
    gcloud pubsub topics add-iam-policy-binding workspace-events --member='serviceAccount:meet-api-event-push@system.gserviceaccount.com' --role='roles/pubsub.publisher'

    It can take a few minutes to update the permissions for your topic.

  3. Create a Pub/Sub subscription for the topic:
    gcloud pubsub subscriptions create workspace-events-sub --topic=TOPIC_NAME

    Replace the following:

    • TOPIC_NAME: The name of your topic that you created in the previous step.

Make note of the topic name and make sure the value for{project} is theCloud project ID for your app. You'll use the topic name to create theGoogle Workspace subscription later.

Create a service account

Google Cloud console

  1. In the Google Cloud console, go to Menu>IAM & Admin>Service Accounts.

    Go to Service Accounts

  2. ClickCreate service account.
  3. Fill in the service account details, then clickCreate and continue.Note: By default, Google creates a unique service account ID. If you would like to change the ID, modify the ID in the service account ID field.
  4. In theGrant this service account access to project section, add the following roles:
    • roles/pubsub.subscriber
  5. ClickContinue.
  6. Optional: Enter users or groups that can manage and perform actions with this service account. For more details, refer toManaging service account impersonation.
  7. ClickDone. Make a note of the email address for the service account.

gcloud CLI

  1. Create the service account:
    gcloud iam service-accounts create meet-event-listener \  --display-name="meet-event-listener"
  2. Grant the necessary roles to the service account:
    gcloud projects add-iam-policy-bindingPROJECT_ID \  --member="serviceAccount:meet-event-listener@PROJECT_ID.iam.gserviceaccount.com" \  --role="roles/pubsub.subscriber"

    ReplacePROJECT_ID with your Google Cloud project ID.

Use the service account

After creating the service account, grant yourself access to impersonate theservice account.

Google Cloud console

  1. In theActions column for the newly created service account, click>Manage permissions.
  2. ClickAdd key>Grant access.
  3. Enter your email address underAdd principals.
  4. SelectService accounts>Service Account Token Creator as the role.
  5. ClickSave.
  6. Return to your terminal and sign in withgcloud to set the application default credentials to the service account. When prompted for authorization, sign in using the same account used in the previous steps.
    gcloud auth application-default login --impersonate-service-account=SERVICE_ACCOUNT_EMAIL

gcloud CLI

  1. To add the permission, rungcloud iam service-accounts add-iam-policy-binding using the email address of the service account and the user.
    gcloud iam service-accounts add-iam-policy-binding \SERVICE_ACCOUNT_EMAIL \  --member="user:YOUR_EMAIL" \  --role="roles/iam.serviceAccountTokenCreator"
  2. Sign in to set the application default credentials to the service account. When prompted for authorization, sign in using the same account used in the previous steps.
    gcloud auth application-default login --impersonate-service-account=SERVICE_ACCOUNT_EMAIL

Install the Pub/Sub client library

  1. Usepip to install the client library for Pub/Sub:

    pipinstallgoogle-cloud-pubsub
  2. Then editmain.py to import the client:

    fromgoogle.cloudimportpubsub_v1

Create the Google Workspace subscription

Add the following code tomain.py to define a method for subscribing toMeet events. This code subscribes to all events for a meetingspace. When subscribed, events are posted to the Pub/Sub topic.

defsubscribe_to_space(space_name:str=None,topic_name:str=None):"""Subscribe to events for a meeting space."""session=requests.AuthorizedSession(USER_CREDENTIALS)body={'targetResource':f"//meet.googleapis.com/{space_name}","eventTypes":["google.workspace.meet.conference.v2.started","google.workspace.meet.conference.v2.ended","google.workspace.meet.participant.v2.joined","google.workspace.meet.participant.v2.left","google.workspace.meet.recording.v2.fileGenerated","google.workspace.meet.transcript.v2.fileGenerated",],"payloadOptions":{"includeResource":False,},"notificationEndpoint":{"pubsubTopic":topic_name},"ttl":"86400s",}response=session.post("https://workspaceevents.googleapis.com/v1/subscriptions",json=body)returnresponse

Next, add the corresponding code to pull and process the events.

Listen for and handle events

Continue to editmain.py and add the following sample code. This codeimplements the receiving side and uses the Google Cloud Pub/Sub API to pullevents as they're made available. The various handler methods print informationabout the corresponding events.

defformat_participant(participant:meet.Participant)->str:"""Formats a participant for display on the console."""ifparticipant.anonymous_user:returnf"{participant.anonymous_user.display_name} (Anonymous)"ifparticipant.signedin_user:returnf"{participant.signedin_user.display_name} (ID:{participant.signedin_user.user})"ifparticipant.phone_user:returnf"{participant.phone_user.display_name} (Phone)"return"Unknown participant"deffetch_participant_from_session(session_name:str)->meet.Participant:"""Fetches the participant for a session."""client=meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)# Use the parent path of the session to fetch the participant detailsparsed_session_path=client.parse_participant_session_path(session_name)participant_resource_name=client.participant_path(parsed_session_path["conference_record"],parsed_session_path["participant"])returnclient.get_participant(name=participant_resource_name)defon_conference_started(message:pubsub_v1.subscriber.message.Message):"""Display information about a conference when started."""payload=json.loads(message.data)resource_name=payload.get("conferenceRecord").get("name")client=meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)conference=client.get_conference_record(name=resource_name)print(f"Conference (ID{conference.name}) started at{conference.start_time.rfc3339()}")defon_conference_ended(message:pubsub_v1.subscriber.message.Message):"""Display information about a conference when ended."""payload=json.loads(message.data)resource_name=payload.get("conferenceRecord").get("name")client=meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)conference=client.get_conference_record(name=resource_name)print(f"Conference (ID{conference.name}) ended at{conference.end_time.rfc3339()}")defon_participant_joined(message:pubsub_v1.subscriber.message.Message):"""Display information about a participant when they join a meeting."""payload=json.loads(message.data)resource_name=payload.get("participantSession").get("name")client=meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)session=client.get_participant_session(name=resource_name)participant=fetch_participant_from_session(resource_name)display_name=format_participant(participant)print(f"{display_name} joined at{session.start_time.rfc3339()}")defon_participant_left(message:pubsub_v1.subscriber.message.Message):"""Display information about a participant when they leave a meeting."""payload=json.loads(message.data)resource_name=payload.get("participantSession").get("name")client=meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)session=client.get_participant_session(name=resource_name)participant=fetch_participant_from_session(resource_name)display_name=format_participant(participant)print(f"{display_name} left at{session.end_time.rfc3339()}")defon_recording_ready(message:pubsub_v1.subscriber.message.Message):"""Display information about a recorded meeting when artifact is ready."""payload=json.loads(message.data)resource_name=payload.get("recording").get("name")client=meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)recording=client.get_recording(name=resource_name)print(f"Recording available at{recording.drive_destination.export_uri}")defon_transcript_ready(message:pubsub_v1.subscriber.message.Message):"""Display information about a meeting transcript when artifact is ready."""payload=json.loads(message.data)resource_name=payload.get("transcript").get("name")client=meet.ConferenceRecordsServiceClient(credentials=USER_CREDENTIALS)transcript=client.get_transcript(name=resource_name)print(f"Transcript available at{transcript.docs_destination.export_uri}")defon_message(message:pubsub_v1.subscriber.message.Message)->None:"""Handles an incoming event from the Google Cloud Pub/Sub API."""event_type=message.attributes.get("ce-type")handler={"google.workspace.meet.conference.v2.started":on_conference_started,"google.workspace.meet.conference.v2.ended":on_conference_ended,"google.workspace.meet.participant.v2.joined":on_participant_joined,"google.workspace.meet.participant.v2.left":on_participant_left,"google.workspace.meet.recording.v2.fileGenerated":on_recording_ready,"google.workspace.meet.transcript.v2.fileGenerated":on_transcript_ready,}.get(event_type)try:ifhandlerisnotNone:handler(message)message.ack()exceptExceptionaserror:print("Unable to process event")print(error)deflisten_for_events(subscription_name:str=None):"""Subscribe to events on the subscription."""subscriber=pubsub_v1.SubscriberClient()withsubscriber:future=subscriber.subscribe(subscription_name,callback=on_message)print("Listening for events")try:future.result()exceptKeyboardInterrupt:future.cancel()print("Done")

Finalize the code

Add the following code tomain.py to call the methods to create the space,subscribe to events, and listen. Update theTOPIC_NAMEandSUBSCRIPTION_NAME constants with your owntopicand subscription names that you previouslycreated.

  1. Add the code tomain.py:

    space=create_space()print(f"Join the meeting at{space.meeting_uri}")TOPIC_NAME="projects/PROJECT_ID/topics/TOPIC_ID"SUBSCRIPTION_NAME="projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID"subscription=subscribe_to_space(topic_name=TOPIC_NAME,space_name=space.name)if(subscription.status_code)==200:listen_for_events(subscription_name=SUBSCRIPTION_NAME)else:print(f"Subscription to Meet events failed, response data:{subscription.content}")

    Replace the following:

    • PROJECT_ID: The unique Cloud project ID foryour app, such asmy-sample-project-191923.

    • TOPIC_ID: The name of the Pub/Sub topic that youcreated in your Cloud project.

    • SUBSCRIPTION_ID: The name of your subscription, suchasworkspace-events-sub.

  2. Run the program:

    python3main.py

If you haven't previously run the program, it prompts for authorization thefirst time. Grant access to the application to call the Meet REST API.After the program successfully runs, you should see output similar to:

Join the meeting at https://meet.google.com/abc-mnop-xyz

Join the conference

To generate events for the application, join the conference using the URLdisplayed by the application. After you join, you can try these actions totrigger events:

  • Leave and rejoin the meeting.
  • Invite others or dial in with your phone.
  • Enable recordings and transcripts.

Each of these activities generates an event that the application receives andlogs to the Google Cloud console.

Note: Recordings and transcripts can take several minutesafter the meetingends to generate. Keep the program running after leaving the meeting and wait.

Usectrl-c to interrupt the program when you're done.

Optional: Additional steps to try

The app logs basic details about the events. To continue exploring theMeet REST API, try modifying the application to perform these additionalactions.

  • Use thePeople API to retrieve additional information aboutsigned-in participants.

    defsubscribe_to_user(user_name:str=None,topic_name:str=None)->requests_lib.Response:"""Subscribe to events for a user."""session=requests.AuthorizedSession(USER_CREDENTIALS)body={"targetResource":f"//cloudidentity.googleapis.com/users/{user_name}","eventTypes":["google.workspace.meet.conference.v2.started","google.workspace.meet.conference.v2.ended","google.workspace.meet.participant.v2.joined","google.workspace.meet.participant.v2.left","google.workspace.meet.recording.v2.fileGenerated","google.workspace.meet.transcript.v2.fileGenerated",],"payloadOptions":{"includeResource":False,},"notificationEndpoint":{"pubsubTopic":topic_name},"ttl":"86400s",}response=session.post("https://workspaceevents.googleapis.com/v1/subscriptions",json=body)returnresponseservice=build("people","v1",credentials=USER_CREDENTIALS)response=(service.people().get(resourceName="people/me",personFields="names,emailAddresses").execute())resource_name=response.get("resourceName")ifresource_name.startswith("people/"):resource_name=resource_name[len("people/"):]subscription=subscribe_to_user(topic_name=TOPIC_NAME,user_name=resource_name)

    Make sure to add "https://www.googleapis.com/auth/userinfo.profile" in theauthorize method in the credential samples above.

  • Use theGoogle Drive API to download recordingsand transcripts.

  • Instead of downloading transcripts from Google Drive, retrieve them usingthestructured transcriptmethodsin the Meet REST API.

  • get space instead of creating the space

    defget_space(meeting_code:str)->meet.Space:"""Get a meeting space."""client=meet.SpacesServiceClient(credentials=USER_CREDENTIALS)returnclient.get_space(name="spaces/"+meeting_code)

    Make sure to add "https://www.googleapis.com/auth/meetings.space.readonly" in theauthorize method in the credential samples above.

Optional: Clean up

To avoid incurring charges to your Google Cloud console account for the resourcesused in this tutorial, we recommend that you clean up any resources and projectscreated.

To delete the subscription:

Console

  1. In the Google Cloud console, go to Menu>Pub/Sub>Subscriptions

    Go to Subscriptions

  2. Select the subscription and clickMore actions.

  3. ClickDelete. TheDelete subscription window appears.

  4. ClickDelete.

gcloud CLI

  1. Delete the subscription:

    gcloudpubsubsubscriptionsdeleteSUBSCRIPTION_NAME

To delete the topic:

Console

  1. In the Google Cloud console, go to Menu>Pub/Sub>Topics

    Go to Topics

  2. Select the topic and clickMore actions.

  3. ClickDelete. TheDelete topic window appears.

  4. Enterdelete and then clickDelete.

gcloud CLI

  1. Delete the topic:

    gcloudpubsubtopicsdeleteTOPIC_NAME

To delete the project:

Console

Caution: Deleting a project has the following effects:

  • Everything in the project is deleted. If you used an existing project for this tutorial, when you delete it, you also delete any other work you've done in the project.
  • Custom project IDs are lost. When you created this project, you might have created a custom project ID that you want to use in the future. To preserve the URLs that use the project ID, such as a URL on appspot.com, delete the selected resources inside the project instead of deleting the whole project.

If you plan to explore multiple tutorials and quickstarts, reusing projects can help you avoid exceeding project quota limits.

  1. In the Google Cloud console, go to theManage resources page. ClickMenu>IAM & Admin>Manage Resources.

    Go to Resource Manager

  2. In the project list, select the project you want to delete and then clickDelete.
  3. In the dialog, type the project ID and then clickShut down to delete the project.

gcloud CLI

  1. To delete a project, use thegcloud projectsdeletecommand:

    gcloudprojectsdeletePROJECT_ID

Related topics

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-11 UTC.