> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vexa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Get a Microsoft Teams transcript via API

> Microsoft Teams live transcription API: send a bot to the meeting with one POST, then read the transcript over REST or WebSocket.

Send a bot to the meeting with **one POST**, then read the transcript **while the call is still
running**. The bot joins Microsoft Teams like any participant — no plugins, no host configuration
— and streams back a speaker-attributed transcript you either poll over REST or subscribe to over
WebSocket.

<Tip>
  **Hosted, no install:** [connect your agent](https://vexa.ai/connect?utm_source=docs\&utm_medium=tip\&utm_campaign=how-to-microsoft-teams-transcript-api) (Claude Code, Codex, Cursor) or [get an API key](https://vexa.ai/start?utm_source=docs\&utm_medium=tip\&utm_campaign=how-to-microsoft-teams-transcript-api) (free credit, no card required). Self-hosting: [Deployment](/deployment).
</Tip>

## 1. Send the bot

```bash theme={null}
# the meeting ID and its passcode, as Teams shows them in the invite
curl -X POST "$API_BASE/bots" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{"platform":"teams","native_meeting_id":"397421056486982","passcode":"X8hcQVTnGNpGelJLSv","bot_name":"Vexa"}'
```

Teams meetings come addressed two ways, and both are valid `native_meeting_id`s:

* the **numeric meeting ID** (10–15 digits) Teams prints next to a **passcode** — pass the passcode
  in `passcode`, never glued onto the id;
* the **thread id** out of a classic `…/l/meetup-join/19:meeting_…@thread.v2` link, which carries
  its own credential and takes no separate passcode.

Sending the full `meeting_url` instead settles both the host and the passcode on its own.
`$API_BASE` is `https://api.cloud.vexa.ai` hosted, or `http://localhost:18056` self-hosted.

## 2. Read the transcript live

Segments stream in as the meeting runs. Poll:

```bash theme={null}
curl -H "X-API-Key: $API_KEY" \
  "$API_BASE/transcripts/teams/397421056486982"
```

```json theme={null}
{
  "segments": [
    { "speaker": "Jane Liu", "text": "Let's lock the renewal pricing by July 1.",
      "start": 12.4, "end": 15.1, "language": "en", "completed": true, "confidence": 0.93 }
  ]
}
```

Live drafts arrive as `completed: false` and are replaced by `completed: true` confirmations. For
per-segment push instead of polling, subscribe on the gateway's `/ws`:

```json theme={null}
{ "action": "subscribe",
  "meetings": [ { "platform": "teams", "native_id": "397421056486982" } ] }
```

## Microsoft Teams specifics

* **Admission.** The bot may wait in the lobby until a host admits it — admit it like any guest. A
  run that ended there reports
  [`awaiting_admission_timeout` or `awaiting_admission_rejected`](/troubleshooting/completion-reasons);
  `automatic_leave.max_wait_for_admission` sets how long it waits.
* **Non-default clouds.** On `teams.live.com` for personal meetings, or `gov.` / `dod.`
  `teams.microsoft.us` for GCC-High and DoD, add `teams_base_host` — otherwise the bot builds its
  URL on the world-wide host and joins a different Teams. Hosts outside the Teams web clients are
  rejected with `422`.
* **Passcodes.** Only `passcode` is read. `password`, `meeting_password` and similar aliases are
  rejected with a `422` naming the right field. The passcode is kept off the stored
  `constructed_meeting_url` and out of the logs.
* **Language auto-detection.** Teams rides the mixed-audio lane, where a low-confidence detection
  discards the window rather than guessing; those windows carry `language: null`. Pin `language` on
  the spawn to avoid it.

## Stop the bot

```bash theme={null}
curl -X DELETE "$API_BASE/bots/teams/397421056486982" -H "X-API-Key: $API_KEY"
```

## See also

* [Send a bot and get a transcript](/how-to/send-a-bot) — the full walkthrough, all platforms
* [Meetings API](/api/meetings) — every parameter, status, and response shape
* [Troubleshooting](/troubleshooting) — the bot joined but there is no transcript
