> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.meetstream.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.meetstream.ai/_mcp/server.

# MeetStream Guide: Raise & Lower Hand

Make a bot raise or lower its hand in a live meeting. Use it when your agent wants to speak but should wait its turn instead of talking over people: raise the hand, wait for the host or the conversation to make room, then speak and lower the hand.

---

## How it works

You send a `raise_hand` or `lower_hand` command to a bot that is in the meeting. The bot uses the meeting's own raise-hand control, exactly as a person would, so everyone in the meeting sees the hand go up or down.

The bot then checks the meeting again and tells you the result. The `hand_raised` field in the response is the hand state the bot saw **after** acting, not just an echo of what you asked for.

The commands are safe to repeat. If the hand is already in the state you asked for, the bot does nothing and returns `200` with the current state.

---

## Prerequisites

- A bot that is **in the meeting** (status `InMeeting` or `Recording`). A bot that is still joining or waiting in the lobby cannot raise its hand.
- Your MeetStream API key.
- The host has not turned off raise hand for the meeting.

### Supported platforms

| Platform | Supported |
|----------|-----------|
| Google Meet | Yes |
| Zoom | Yes |
| Microsoft Teams | Yes |
| Zoom RTMS (Meeting Direct Connect) | No. RTMS sessions are receive-only and nothing can be sent into the meeting |
| WhatsApp | No |

---

## Endpoint

```
POST https://api.meetstream.ai/api/v1/bots/{bot_id}/send_command
```

| Parameter | Location | Required | Description |
|-----------|----------|----------|-------------|
| `bot_id` | Path | Yes | The bot ID returned when you created the bot |
| `Authorization` | Header | Yes | `Token <YOUR_API_KEY>` |
| `command` | Body | Yes | `raise_hand` or `lower_hand` |

---

## Example: Raise hand

```bash
curl -X POST "https://api.meetstream.ai/api/v1/bots/{bot_id}/send_command" \
  -H "Authorization: Token <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"command": "raise_hand"}'
```

### Response (200)

```json
{
  "status": "accepted",
  "bot_id": "83acdd72-3257-4b06-a2e9-0d879dc571ff",
  "command": "raise_hand",
  "hand_raised": true
}
```

## Example: Lower hand

```bash
curl -X POST "https://api.meetstream.ai/api/v1/bots/{bot_id}/send_command" \
  -H "Authorization: Token <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"command": "lower_hand"}'
```

### Response (200)

```json
{
  "status": "accepted",
  "bot_id": "83acdd72-3257-4b06-a2e9-0d879dc571ff",
  "command": "lower_hand",
  "hand_raised": false
}
```

---

## Example: Raise, speak, lower (Python)

```python
import requests

API = "https://api.meetstream.ai/api/v1/bots"
HEADERS = {"Authorization": "Token <YOUR_API_KEY>"}


def set_hand(bot_id: str, raised: bool) -> bool:
    command = "raise_hand" if raised else "lower_hand"
    resp = requests.post(
        f"{API}/{bot_id}/send_command",
        headers=HEADERS,
        json={"command": command},
        timeout=15,
    )
    resp.raise_for_status()
    return resp.json()["hand_raised"]


set_hand(bot_id, True)    # hand goes up
# ... wait for your turn, then have the bot speak ...
set_hand(bot_id, False)   # hand goes down
```

---

## Behavior notes

- **The response reflects the meeting.** `hand_raised` is read back from the meeting after the bot acts.
- **Repeats are no-ops.** Raising a hand that is already up, or lowering one that is already down, returns `200` with the current state and changes nothing.
- **Someone else may lower the hand.** The host can lower the bot's hand. On Google Meet, the meeting also lowers a raised hand on its own once that participant speaks. Send `lower_hand` before your next `raise_hand` if you are not sure of the current state. It returns the real state without acting when the hand is already down.
- **Response time.** A command usually completes in 1 to 2 seconds. Allow up to 10 seconds before treating a request as failed.
- **One hand command at a time.** If you send several hand commands to the same bot at once, the bot runs them in order. A command that waits too long behind another one returns `503` with `hand_command_busy` without acting, so it is never applied late. Retry it.
- **Reactions are not supported.** Emoji reactions (thumbs up, clap and so on) are not available through this command.

---

## Conditions

- The bot must be **in the meeting** (`InMeeting` or `Recording` status). Requests sent while the bot is joining, waiting in the lobby, or after it has left return `409`.
- Rate limit: **30 requests per minute** per bot, shared with the other in-meeting commands you send to the same bot.
- Bots running in a region outside the US return `501` for now.

---

## Error Responses

| Status | `error` | Meaning |
|--------|---------|---------|
| `400` | `Invalid command. ...` | The command name is wrong, or raise hand is not available for this bot's platform. |
| `400` | `code: unsupported_on_zoom_rtms` / `unsupported_on_whatsapp` | The bot type cannot send anything into the meeting. |
| `401` | | Missing or invalid API key. |
| `403` | | The bot does not belong to your account. |
| `404` | | Bot not found. |
| `409` | `Bot is not currently in a meeting.` | The bot is still joining, waiting in the lobby, or has left. |
| `409` | `raise_hand_unavailable` | The meeting does not allow it. The host may have turned off raise hand. |
| `429` | `Rate limit exceeded` | More than 30 commands per minute for this bot. |
| `501` | | Not yet available for bots in this execution region. |
| `502` | `ui_control_not_found` | The bot could not find or read the meeting's raise-hand control. Retry once; if it persists, contact support. |
| `503` | `hand_command_busy` | Another hand command for this bot was still running. Retry. |
| `503` | | The bot is unreachable or is not in the meeting any more. |