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

# Slack integration

> How PRFlow connects to Slack, which channels it can post to, the four bot scopes it requests, what data reaches your workspace, and how disconnecting or uninstalling works.

## Overview

PRFlow delivers GitLab merge request and GitHub pull request notifications to
Slack. For each MR/PR it posts **one Slack message that updates in place** as
the work progresses — CI status, approvals, and merge state all appear on the
original card instead of new messages piling up — and review comments are
synced into a Slack thread under it, so the channel stays readable.

Slack is the **destination** side of PRFlow. Notifications originate from a
source provider — [GitLab](/gitlab-integration) or
[GitHub](/github-integration) — so a workspace needs a source connected
before the Slack connection has anything to deliver. Each PRFlow workspace
connects to one Slack workspace.

## Setup

You connect Slack from inside PRFlow, via OAuth:

1. Sign in at [app.prflow.dev](https://app.prflow.dev) and connect a source
   provider first — [GitLab](/gitlab-integration) or
   [GitHub](/github-integration).
2. From **Home** or **Settings → Connections**, click **Connect Slack** and
   authorize the app in the Slack consent screen. PRFlow requests the four
   bot scopes listed below — enough to list channels and post/update its own
   messages, nothing more.
3. Map repositories to Slack channels from the dashboard. From then on, every
   qualifying MR/PR posts its card to the mapped channel.

<Note>
  Starting from Slack instead — an **Add to Slack** link or Slack's app
  directory — also works: the install lands on a guided sign-in page that
  explains the order of operations (connect a repository first, then add
  Slack from within PRFlow). No partial or dangling Slack connection is
  created along the way; you simply create an account or sign in and continue
  setup from the right starting point.
</Note>

## How it works

### Which channels PRFlow can post to

<Frame caption="The channel picker lists public channels, plus private ones the bot has been invited to.">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/prflow/images/channel-routing-select-channel.png" alt="PRFlow channel picker listing public Slack channels and one private channel" />
</Frame>

* **Public channels** — PRFlow can post to any public channel without a
  manual invite (that is what the `chat:write.public` scope is for), and
  every public channel appears in the channel picker.
* **Private channels** — PRFlow can only see and post to a private channel
  after someone runs `/invite @PRFlow` in it. Once the bot is a member, the
  channel shows up in the channel picker like any other.

PRFlow never reads channel messages: it requests no history scopes and no
user scopes, so it cannot see what anyone writes in your channels or DMs. It
only posts and updates its own messages.

### Posting model

* **One card per MR per channel.** The first qualifying event posts the
  message; every later event updates that same message (Slack `chat.update`)
  instead of posting a new one. If a repository is mapped to multiple
  channels, each channel gets at most one message per MR, and updates stay in
  the channel where the message was originally posted.
* **Comments as threaded replies.** Each review comment becomes a reply in
  the card's thread, quoting the comment text (truncated to 2,000 characters)
  with the commenter's username. Comment edits update the existing reply;
  comment deletions remove it.

## Permissions & security

PRFlow requests exactly four **bot** scopes — no user scopes, no message
history:

| Scope               | Why PRFlow needs it                                                                |
| ------------------- | ---------------------------------------------------------------------------------- |
| `chat:write`        | Post the MR message, update it in place, and manage threaded comment replies.      |
| `chat:write.public` | Post to public channels without requiring a manual bot invite to each one.         |
| `channels:read`     | List public channels in the channel picker when you map a project.                 |
| `groups:read`       | List private channels the bot has been added to, so they appear in the picker too. |

The Slack bot token is encrypted at rest with AES-256-GCM and is never
written to logs, and all Slack API traffic runs over HTTPS.

### Data sent to Slack

Notifications in your Slack channels contain:

* MR/PR number, title, and a link back to GitLab or GitHub,
* author display name and username, target branch, and project name,
* CI status, approval/review indicators, and merge-status labels,
* comment text excerpts (up to 2,000 characters) and commenter usernames in
  thread replies.

**Comment text is retained** for the comments PRFlow syncs, alongside the
comment ID and the Slack message reference: delivery is durable, so a reply
is recorded before it is posted and retried if Slack is unavailable, and an
edit at the source updates the existing reply without re-fetching it. For
the full picture of what PRFlow receives from the source provider and what
it stores, see the GitLab page's
[data handling section](/gitlab-integration#data-handling), which applies
equally to GitHub.

## Disconnecting

Either side works:

* **From PRFlow** — the Slack card on **Settings → Connections** has a
  **Disconnect** button (admin-only, with a confirmation step). Your
  repository and channel-mapping setup is kept, and notifications resume when
  you reconnect. Disconnecting also revokes the bot token at Slack, so it
  does not linger — unless another of your PRFlow organizations shares the
  same Slack workspace, in which case revocation is safely skipped and only
  your connection is removed.
* **From Slack** — uninstalling the PRFlow app from the workspace (or
  revoking its tokens on Slack's side) disconnects **every** PRFlow
  organization linked to that workspace immediately, deleting the stored
  access tokens and stopping further posting attempts.

If Slack ever rejects a notification because a connection has gone bad,
PRFlow marks that connection unhealthy and stops trying to post through it
instead of failing on every event; reconnecting from the Connections page
restores it.

## Support

Questions about the integration, a channel that isn't showing up in the
picker, or a notification that didn't arrive? Email
[hello@prflow.dev](mailto:hello@prflow.dev) and we'll get you sorted.
