# OAuth quickstart

> Connect your own BloomText admin account with OAuth, read the last week of your conversations chat by chat, and reply in a team chat.

Source: https://www.bloomtext.com/developers/api/oauth-quickstart/

Connect your own BloomText account to a registered app with OAuth, read the last week of your conversations chat by chat, and reply in a team chat.

> **Note:** For now, only org admins can connect apps. If you're not one, ask an org admin to try this, or use the [Patient API quickstart](https://www.bloomtext.com/developers/api/patient-api-quickstart/) with an API key.

### Get your app's credentials

Apps are registered for organizations with a signed BAA. [Request API access](https://calendly.com/tyler-bloom/bloomtext-homepage-demo-request?utm_campaign=api-access) if you haven't registered yours. For this guide, ask us to add `http://localhost:8765/callback` as a redirect URI. An org admin in your organization also needs to approve the app in BloomText.

Put the credentials in environment variables. Never commit them or ship them to a browser.

```bash filename="Terminal"
export BLOOMTEXT_CLIENT_ID="bt_client_7Hq2mX9aLk"
export BLOOMTEXT_CLIENT_SECRET="bt_cs_…"
```

### Connect your account

Create a PKCE verifier and challenge, then open the authorize URL in your browser:

```bash filename="Terminal"
export VERIFIER=$(openssl rand -base64 48 | tr -d '=+/\n' | cut -c1-64)
export CHALLENGE=$(printf %s "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=\n')

open "https://app.bloomtext.com/oauth/authorize?response_type=code&client_id=$BLOOMTEXT_CLIENT_ID&redirect_uri=http://localhost:8765/callback&scope=messages.read%20messages.write&state=quickstart&code_challenge=$CHALLENGE&code_challenge_method=S256"
```

Sign in if asked, then approve the app. Your browser goes to `http://localhost:8765/callback?code=…&state=quickstart`. Nothing is listening there, so the page won't load; copy the `code` from the address bar.

### Exchange the code for a token

```bash filename="Terminal"
curl https://app.bloomtext.com/oauth/token \
  -u "$BLOOMTEXT_CLIENT_ID:$BLOOMTEXT_CLIENT_SECRET" \
  -d grant_type=authorization_code \
  -d code=PASTE_THE_CODE_HERE \
  -d redirect_uri=http://localhost:8765/callback \
  -d code_verifier=$VERIFIER
```

```json filename="Response · 200 OK"
{
  "access_token": "bt_at_Vq8yG2mN0cT4…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "messages.read messages.write"
}
```

The code expires after 10 minutes, so exchange it right away. The access token lasts an hour; keep it for the next steps.

```bash filename="Terminal"
export BLOOMTEXT_ACCESS_TOKEN="bt_at_Vq8yG2mN0cT4…"
```

A real app also requests `offline_access` to get a refresh token. See [Tokens and how long they last](https://www.bloomtext.com/developers/api/oauth/#tokens-and-how-long-they-last).

### Read your last week, chat by chat

[List messages](https://www.bloomtext.com/developers/api/reference/list-messages/) (`GET /v1/me/messages`) returns everything in your conversations in a time range, with patients and with colleagues. `group_by=conversation` returns each chat's messages together, most recently active chat first.

```bash filename="Request"
curl -G https://api.bloomtext.com/v1/me/messages \
  -H "Authorization: Bearer $BLOOMTEXT_ACCESS_TOKEN" \
  --data-urlencode 'after=2026-09-21' \
  --data-urlencode 'group_by=conversation'
```

```js filename="read.mjs"
const url = new URL('https://api.bloomtext.com/v1/me/messages')
url.searchParams.set('after', '2026-09-21')
url.searchParams.set('group_by', 'conversation')

const response = await fetch(url, {
  headers: { Authorization: `Bearer ${process.env.BLOOMTEXT_ACCESS_TOKEN}` },
})
const { data } = await response.json()
for (const message of data) console.log(`[${message.conversation.title}] ${message.sender.name}: ${message.body}`)
```

```python filename="read.py"
import os

import requests

response = requests.get(
    "https://api.bloomtext.com/v1/me/messages",
    headers={"Authorization": f"Bearer {os.environ['BLOOMTEXT_ACCESS_TOKEN']}"},
    params={"after": "2026-09-21", "group_by": "conversation"},
)
response.raise_for_status()
for message in response.json()["data"]:
    print(f"[{message['conversation']['title']}] {message['sender']['name']}: {message['body']}")
```

```json filename="Response · 200 OK"
{
  "data": [
    {
      "id": "7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
      "conversation": { "id": "e5c3b7b8-8f08-4d5a-9af1-0d11b0f4b7a0", "title": "Front desk" },
      "sender": { "id": "8b9c2d2f-6b1a-44f4-a7b1-0d6d3f2d6f55", "name": "Alex Example", "kind": "staff" },
      "created_at": "2026-09-27T16:02:00Z",
      "body": "Room 2 is open again if anyone needs it.",
      "unread": true,
      "...": "..."
    }
  ],
  "pagination": { "next_cursor": "eyJpZCI6IjdjMWQyZTNmIn0", "has_more": true }
}
```

Follow `next_cursor` for more. Reading doesn't mark anything as read, so your unread badges stay as they were. See [Read messages](https://www.bloomtext.com/developers/api/read-messages/) for ranges, grouping, and keeping up.

### Reply in a team chat

Copy a team chat's conversation `id` and [send a message](https://www.bloomtext.com/developers/api/reference/create-message/) with `POST /v1/me/conversations/{id}/messages`. It appears under your name, and staff see a "via" label naming your app.

```bash filename="Request"
curl -X POST https://api.bloomtext.com/v1/me/conversations/e5c3b7b8-8f08-4d5a-9af1-0d11b0f4b7a0/messages \
  -H "Authorization: Bearer $BLOOMTEXT_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"body": "Thanks, I will take room 2 at 3:00."}'
```

Sending marks the chat as read for you, as replying in BloomText does.

## Next steps

  - [Connect with OAuth in your app](https://www.bloomtext.com/developers/api/oauth/)
  - [Read messages](https://www.bloomtext.com/developers/api/read-messages/)
  - [Search messages](https://www.bloomtext.com/developers/api/search/)
  - [Build an AI agent](https://www.bloomtext.com/developers/api/ai-agents/)

Texting patients from a server instead? Try the [Patient API quickstart](https://www.bloomtext.com/developers/api/patient-api-quickstart/).
