# Bots

> Sending the notetaker into a call, and the three rules that govern it.

Most recordings happen because a calendar meeting matched a rule. This is the other way round: a call is happening now, and you want the notetaker in it.

```bash
curl -X POST https://api-notetaker.nabrah.ai/ext/v1/bots \
  -H "Authorization: Bearer $NABRAH_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7f3c1e90-2f1a-4c0e-9a3b-9d2e5f6a7b8c" \
  -d '{"joinUrl":"https://meet.google.com/abc-defg-hij","title":"Vendor call"}'
```

## Three rules, and each fails differently

### One bot per account, at a time
A second `POST /bots` while one is still live returns `409`. This is not transient and retrying will not clear it — either wait for the first to finish, or stop it with `POST /bots/{runId}/stop`.

It is enforced by a uniqueness constraint in the database rather than a check in code, so two simultaneous requests cannot both win.

### Recordings are capped per calendar month
At the cap, `409` with a message saying so. It resets at the start of the next month. `GET /organization` shows the month's usage against the allowance if you want to see it coming.

### The link must be a platform we can join
Google Meet, Webex and Microsoft Teams. Anything else — including Zoom — is refused with `422` at the schema, before anything is created. The check is an allowlist of hosts, so a link that merely looks like one will not pass.

## Watching it happen

`POST /bots` answers as soon as the bot is dispatched, not when it has joined. Poll `GET /bots/{runId}` to follow it, or take the webhooks and do not poll at all.

| State | Means |
| --- | --- |
| `pending` · `dispatched` | On its way |
| `live` | In the meeting, recording |
| `ended` | Left the meeting; analysis has not finished |
| `processing` | Transcribing and summarising |
| `ready` | Notes exist — `GET /recordings/{runId}` |
| `failed` | Could not join, or nothing was recorded |

**Tip: Prefer webhooks**

`meeting.started`, `meeting.ended` and `meeting.ready` tell you each transition as it happens. A bot can sit in an hour-long call; polling costs you a request a minute and tells you nothing new for most of them.

## Always send an Idempotency-Key

A timeout does not tell you whether the bot was dispatched. Retrying blind is how one call ends up with two — except the second is refused by the one-bot rule, so what you actually get is a confusing `409` instead of the answer you missed.

With an `Idempotency-Key`, the retry returns the **original response**, byte for byte, with `Idempotency-Replayed: true`.

## Stopping early

```bash
curl -X POST https://api-notetaker.nabrah.ai/ext/v1/bots/$RUN_ID/stop \
  -H "Authorization: Bearer $NABRAH_API_KEY"
```

Whatever was captured up to that point is still processed into notes — stopping is not discarding. A run that has already finished answers `404`, because there is nothing left to stop.
