Skip to main content

Prerequisites

Before you can send bots to meetings, you’ll need:
1

Attendee API Key

Create an account at app.attendee.dev, sign in, and navigate to the ‘API Keys’ section in the sidebar to generate your key.
2

Zoom OAuth Credentials

Required for joining Zoom meetings. These are the Zoom app client ID and secret that uniquely identify your bot.
  • Navigate to Zoom Marketplace and register/log into your developer account
  • Click “Develop” → “Build App” → choose “General App”
  • Copy the Client ID and Client Secret from the ‘App Credentials’ section
  • Go to the Embed tab under Features, then enable the Meeting SDK toggle
For detailed instructions, see this guide or watch this video.
3

Deepgram API Key

Required for transcribing Zoom meetings. Sign up at console.deepgram.com - no credit card required, includes 400 hours of free transcription.
Enter your Zoom OAuth credentials and Deepgram API key in the Attendee UI under the ‘Settings’ section in the sidebar.

Your First Bot

Let’s send a bot to join a meeting and get a transcript in three simple steps.
1

Create a bot and join a meeting

Make a POST request to create a bot. The bot will immediately attempt to join the meeting:
curl -X POST https://app.attendee.dev/api/v1/bots \
  -H 'Authorization: Token <YOUR_API_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "meeting_url": "https://us05web.zoom.us/j/84315220467?pwd=9M1SQg2Pu2l0cB078uz6AHeWelSK19.1",
    "bot_name": "My Bot"
  }'
Response:
{
  "id": "bot_3hfP0PXEsNinIZmh",
  "meeting_url": "https://us05web.zoom.us/j/84315220467?pwd=9M1SQg2Pu2l0cB078uz6AHeWelSK19.1",
  "state": "joining",
  "transcription_state": "not_started",
  "recording_state": "not_started"
}
The bot ID (bot_3hfP0PXEsNinIZmh) is returned in the response. Save this - you’ll need it to check the bot’s status and retrieve the transcript.
2

Monitor the bot's state

Poll the bot to check its status. The bot will transition through states like joiningjoined_recordingleavingended:
curl -X GET https://app.attendee.dev/api/v1/bots/bot_3hfP0PXEsNinIZmh \
  -H 'Authorization: Token <YOUR_API_KEY>' \
  -H 'Content-Type: application/json'
Response when meeting ends:
{
  "id": "bot_3hfP0PXEsNinIZmh",
  "meeting_url": "https://us05web.zoom.us/j/84315220467?pwd=9M1SQg2Pu2l0cB078uz6AHeWelSK19.1",
  "state": "ended",
  "transcription_state": "complete",
  "recording_state": "complete"
}
Wait for both state: "ended" and transcription_state: "complete" before requesting the transcript.
3

Retrieve the transcript

Once transcription is complete, fetch the full transcript:
curl -X GET https://app.attendee.dev/api/v1/bots/bot_3hfP0PXEsNinIZmh/transcript \
  -H 'Authorization: Token <YOUR_API_KEY>' \
  -H 'Content-Type: application/json'
Response:
[
  {
    "speaker_name": "Noah Duncan",
    "speaker_uuid": "16778240",
    "speaker_user_uuid": "AAB6E21A-6B36-EA95-58EC-5AF42CD48AF8",
    "timestamp_ms": 1079,
    "duration_ms": 7710,
    "transcription": "You can totally record this, buddy. You can totally record this. Go for it, man."
  },
  {
    "speaker_name": "Jane Smith",
    "speaker_uuid": "16778241",
    "speaker_user_uuid": "BBB6E21A-6B36-EA95-58EC-5AF42CD48AF9",
    "timestamp_ms": 9320,
    "duration_ms": 4200,
    "transcription": "Thanks for joining! Let's get started with today's agenda."
  }
]
You can also query this endpoint during the meeting to get partial transcripts in real-time.

Understanding Bot States

Bots go through several states during their lifecycle:
StateDescription
readyInitial state when bot is created
joiningBot is attempting to join the meeting
joined_not_recordingBot has joined but isn’t recording yet
joined_recordingBot is actively recording the meeting
waiting_roomBot is in the meeting’s waiting room
leavingBot is leaving the meeting
post_processingBot is processing recordings and transcripts
endedMeeting ended, all data is available
fatal_errorBot encountered an unrecoverable error

Code Examples

import requests
import time

API_KEY = 'your_api_key_here'
BASE_URL = 'https://app.attendee.dev/api/v1'

headers = {
    'Authorization': f'Token {API_KEY}',
    'Content-Type': 'application/json'
}

# Create a bot
response = requests.post(
    f'{BASE_URL}/bots',
    headers=headers,
    json={
        'meeting_url': 'https://zoom.us/j/123456789',
        'bot_name': 'My Bot'
    }
)

bot = response.json()
bot_id = bot['id']
print(f'Bot created: {bot_id}')

# Poll until meeting ends
while True:
    response = requests.get(
        f'{BASE_URL}/bots/{bot_id}',
        headers=headers
    )
    bot = response.json()
    
    if bot['state'] == 'ended' and bot['transcription_state'] == 'complete':
        break
    
    print(f"Bot state: {bot['state']}, Transcription: {bot['transcription_state']}")
    time.sleep(5)

# Get transcript
response = requests.get(
    f'{BASE_URL}/bots/{bot_id}/transcript',
    headers=headers
)

transcript = response.json()
for utterance in transcript:
    print(f"{utterance['speaker_name']}: {utterance['transcription']}")

Next Steps

Authentication

Learn about API key management and security

Bot Lifecycle

Deep dive into bot states and lifecycle management

Webhooks

Set up webhooks for real-time bot state notifications

API Reference

Explore the complete API reference

Troubleshooting

The bot needs to be admitted to the meeting by a host. Either:
  • Have a meeting host manually admit the bot
  • Disable the waiting room in your meeting settings
  • Configure automatic leave settings to exit after a timeout
Verify that:
  • Your API key is correct and active
  • You’ve entered valid Zoom OAuth credentials in Settings
  • Your Deepgram API key is valid
Check that:
  • The meeting had actual speech (silence won’t produce transcripts)
  • The transcription_state is complete before requesting the transcript
  • Your Deepgram API key has sufficient credits

Build docs developers (and LLMs) love