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

# Slack integration

Connecting Slack takes three steps: install the Slack app with OAuth, pick a channel, and
choose which notifications it receives. Every call is scoped to a brain.

## Install with OAuth

Installation is a browser redirect. Start OAuth to get a signed authorization URL, send the
user to it, then confirm with the `code` and `state` Slack returns to your redirect URL.

**`TypeScript`**

```typescript TypeScript
const { authorizationUrl, expiresAt } = await client.slack.startOauth({ brainId });
// Redirect the user to authorizationUrl before expiresAt.

// In your OAuth callback handler:
const { installationId } = await client.slack.confirmOauth({ brainId, code, state });
```

**`Python`**

```python Python
start = client.slack.start_oauth(brain_id=brain_id)
# Redirect the user to start.authorization_url before start.expires_at.

# In your OAuth callback handler:
confirmed = client.slack.confirm_oauth(brain_id=brain_id, code=code, state=state)
installation_id = confirmed.installation_id
```

> **Info**
>
> The `state` value is signed and expires at `expiresAt`. Pass it back unchanged; an expired or
> altered state is rejected.

## Check status

`status` returns every Slack workspace installed for the brain, plus its channel bindings.

**`TypeScript`**

```typescript TypeScript
const { installations, bindings } = await client.slack.status({ brainId });
```

**`Python`**

```python Python
status = client.slack.status(brain_id=brain_id)
```

## Bind a channel

List the channels the bot can see in an installation, then bind one to the brain. `isMember`
tells you whether the bot has already been added to the channel.

**`TypeScript`**

```typescript TypeScript
const channels = await client.slack.channels({ brainId, installationId });

const binding = await client.slack.bind({
  brainId,
  installationId,
  channelId: channels[0].id,
});
```

**`Python`**

```python Python
channels = client.slack.channels(brain_id=brain_id, installation_id=installation_id)

binding = client.slack.bind(
    brain_id=brain_id,
    installation_id=installation_id,
    channel_id=channels[0].id,
)
```

## Choose notifications

A binding can post daily briefs, new connections, and page changes. Fields you leave out are
unchanged.

**`TypeScript`**

```typescript TypeScript
await client.slack.updateBinding({
  brainId,
  bindingId: binding.id,
  notifyBriefs: true,
  notifyConnections: false,
  notifyChanges: true,
});
```

**`Python`**

```python Python
client.slack.update_binding(
    brain_id=brain_id,
    binding_id=binding.id,
    notify_briefs=True,
    notify_connections=False,
    notify_changes=True,
)
```

## Disconnect

`unbind` removes one channel binding. `disconnectInstallation` removes the whole Slack
workspace from the brain, along with all of its bindings.

**`TypeScript`**

```typescript TypeScript
await client.slack.unbind({ brainId, bindingId });
await client.slack.disconnectInstallation({ brainId, installationId });
```

**`Python`**

```python Python
client.slack.unbind(brain_id=brain_id, binding_id=binding_id)
client.slack.disconnect_installation(brain_id=brain_id, installation_id=installation_id)
```