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

# OAuth install

> How a company connects your App, and how tokens work

One Workchats company connects to one instance of your App through a
standard OAuth 2.0 authorization-code flow. The resulting token belongs to
the company (acting as your App's bot user), not to the admin who clicked
Connect, so it keeps working after that admin leaves.

## 1. Send the admin to the consent screen

```
https://app.workchats.com/oauth/authorize
  ?client_id=<your client_id>
  &redirect_uri=<your registered redirect_uri, exactly>
  &scope=users:read users:read.email conversations:read messages:write
  &state=<opaque, single-use, generated by you>
```

Only company admins can approve. The consent screen names your App, lists
the scopes, and lets the admin pick which groups and named channels your bot
may join — including "switch company" if they admin more than one.

* **On approve:** redirects to `redirect_uri?code=<code>&state=<state>`.
* **On deny:** redirects to `redirect_uri?error=access_denied&state=<state>`.

`redirect_uri` must match what you registered with Octogle exactly. A code
is single-use, expires in 10 minutes, and is bound to your `client_id` — a
second redemption attempt gets `invalid_grant` and doesn't revoke the token
already issued, so retrying a timed-out exchange is safe.

## 2. Exchange the code for a token

```http theme={null}
POST https://public-api.workchats.com/oauth/token
Content-Type: application/json

{
  "grant_type": "authorization_code",
  "code": "…",
  "redirect_uri": "…",
  "client_id": "…",
  "client_secret": "…"
}
```

Send `client_id` / `client_secret` in the body or as HTTP Basic credentials.
`grant_type` must be `authorization_code` — Workchats tokens don't expire, so
there is no `refresh_token` grant; using one returns
`400 unsupported_grant_type`.

```json 200 theme={null}
{
  "access_token": "wc_bot_live_…",
  "token_type": "Bearer",
  "scope": "users:read users:read.email conversations:read messages:write",
  "workspace": { "id": "cmp_…", "name": "Corpwise" },
  "bot_user_id": "usr_…"
}
```

There's no `expires_in`. Store `access_token` now — it's shown once.

## 3. Send it as a bearer token

```
Authorization: Bearer wc_bot_live_…
```

Only the `Authorization` header is accepted. A token in a query parameter
(`?token=` or `?access_token=`) gets `400 token_in_query` — see
[Security](/guides/security).

## Disconnecting

```http theme={null}
POST https://public-api.workchats.com/oauth/revoke
Content-Type: application/json

{ "token": "…" }
```

Always returns `200 {"ok": true}`, including for an unknown or already
revoked token. This **disconnects**: every token on the installation stops
working immediately, but the bot stays in its groups and channels, so
reconnecting later reuses the same bot and the same memberships. Nothing
else removes the bot — only a company admin uninstalling your App in
Workchats Settings, or Octogle disabling it, does that.

No callback is sent for a revoke today. Until Phase 1b ships
`app.uninstalled`, treat a `401 token_revoked` response on any call as
"disconnected" — see
[Callbacks & signature verification](/guides/callbacks-and-signature-verification).

## Who your bot can message

Your bot can DM active or onboarding people whose email is visible to it
(subject to `users:read.email`'s release rule — see
[Concepts](/getting-started/concepts#tokens-and-scopes)). DMs to guests ship
in a later phase. Sending to a group or channel requires your bot to be an
active member of it — the admin's picks at install time, or later additions
in Workchats Settings → Apps.

| Target | Result |
| - | - |
| Active or onboarding person | Sent |
| Deactivated or removed person | `409 user_deactivated` |
| Guest | `403 cannot_dm_user` |
| Someone who blocked your bot | `403 cannot_dm_user` |
| A group or channel your bot isn't a member of, but never was | `404 conversation_not_found` |
| A group or channel your bot was removed from | `403 not_in_conversation` |
| An archived group | `409 conversation_archived` |
| An announcement channel | `403 not_allowed_in_conversation` |

Bot DMs are read-only for people: they see "this bot sends notifications
here, replies aren't delivered" instead of a composer. That's enforced on
the server, not just hidden in the client.

## Managing the install later

In Workchats Settings → Apps, a company admin can add or remove your bot
from groups and channels, toggle whether conversation posts push to phones,
or uninstall your App entirely. None of this needs a call from you.
