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

# Slack

> Technical reference for the Rippit Slack data integration: OAuth bot scopes, channel selection, the Web API methods and events Rippit uses, what a thread becomes in Rippit, and sync behavior.

An OAuth integration that syncs messages and threads from the public Slack channels you select into Rippit, through scheduled polling and Slack events. For what applies to every integration, see [how data integrations work](https://docs.rippit.com/plg/data-integrations.md). For the security model, see [Data integration security](https://docs.rippit.com/security/data-integrations.md).

## Data integration and the Slack connector

Rippit connects to Slack in two ways, and both can read your messages. This page covers the data integration. The [Slack connector](https://docs.rippit.com/agentic-chat/connectors/slack.md) is an MCP connection that Rippit's agent uses during a chat.

| | Data integration | Slack connector (MCP) |
| - | - | - |
| How it reads | Copies every message from the public channels you select into Rippit, and keeps the copy current | Reads Slack live during a chat, one request at a time |
| Best for | Analysis across your Slack history: themes across months of threads, enrichment, Agent Apps, and comparison with your other conversation sources | Checking the latest discussion in a channel, or following a single thread |
| What it can read | The public channels on your list in Rippit | Any public channel the authorizing admin can see |
| Posts to Slack | Never | Yes, as the Rippit Slack app |
| Slack app | Rippit Data Ingestion | Rippit Slack app |

You can read Slack through either one, but ingesting is what makes analysis possible. With every message stored, the agent works across all of them at once instead of fetching recent history one channel at a time.

The connector is still worth connecting separately. It is how Rippit posts results and reports back to Slack, and it lets the agent look up a channel you have not chosen to ingest. The two are separate Slack apps with separate installs and scopes, so if you connect both, review both.

## Connection summary

| | |
| - | - |
| Authorization | OAuth 2.0 through Slack's `oauth/v2/authorize`. Installs the Rippit Data Ingestion app as a bot in one Slack workspace |
| Token type | Bot token only. No user token is requested |
| Required scopes | `channels:read`, `channels:history`, `channels:join`, `chat:write`, `app_mentions:read`, `im:history`, `im:read`, `users:read`, `users:read.email` |
| Optional scopes | `files:read`, `reactions:read`, `groups:read`, `groups:history`. Slack shows each as a checkbox the installing admin can decline |
| Channel access | Public channels selected in Rippit. Private channels are never synced |
| Direct messages | Never collected. Direct messages sent to the app are dropped without being stored |
| Writes to Slack | Rippit joins the public channels you select, and sends whoever invites the bot to a channel a private reply only that person can see. It never posts visible messages, edits, or deletes |
| Credentials shared with Rippit | The bot token. Rippit stores it and uses it for every sync |
| Credential check | `auth.test`, and the token must carry `channels:read`, `channels:history`, `users:read`, and `users:read.email` before the connection syncs |
| Connection identity | Your Slack workspace. One connection per workspace in each Rippit account. Rippit accounts that connect the same workspace share one bot |
| Required Rippit role | Workspace admin |
| API base | `https://slack.com/api` |
| Sync method | Scheduled polling, plus Slack events for new messages, replies, edits, deletions, and reactions |
| Attachments | Downloaded and stored by Rippit, with `files:read` |
| Maximum historical backfill | 90 days, per channel. The default is 30. A channel you add later imports the same window |
| Field selection limit | 150 columns |

## Before you connect

Install the app into a single Slack workspace. Rippit does not support organization-wide installs on Enterprise Grid, and rejects one with the message to select a workspace and try again.

Slack's install screen lists the optional scopes as checkboxes. Declining them narrows what Rippit collects:

* **Files** (`files:read`): without it, file attachments are not downloaded.
* **Reactions** (`reactions:read`): without it, reactions are not recorded.
* **Private channels** (`groups:read`, `groups:history`): Rippit does not sync private channels whether or not you grant these.

The direct message scopes (`im:history`, `im:read`) are required for the app's Messages tab in Slack. Rippit drops every direct message event without storing it.

### Choosing channels

Rippit syncs only the channels on your list in Rippit. The bot being in a channel is not enough.

* **Pick channels in Rippit.** Select public channels in Rippit, up to 50 at a time, and Rippit joins them.
* **Invite the bot from Slack.** Type `/invite @Rippit Data Ingestion` in a public channel. The bot replies privately to you, and the channel is added to your list. When more than one Rippit account uses the same Slack workspace, the channel is not added; an admin adds it in Rippit.
* **Private channels.** Inviting the bot to a private channel imports nothing. The bot replies privately that private channels are not synced.

To stop syncing a channel, remove it from your list in Rippit. The bot stays in the channel, because every Rippit account on the workspace shares it. To take the bot out of a channel, type `/remove @Rippit Data Ingestion` in Slack.

## Data handling

| Question | Answer |
| - | - |
| Is message content ingested, or only metadata? | Full content: message text, thread replies, file attachments, and reaction names in the channels you select, plus channel names and the name and email of every member of the Slack workspace |
| Are direct messages ingested? | No. Direct message events are dropped without being stored |
| Are private channels ingested? | No. Rippit syncs public channels only, even when the private channel scopes are granted. A public channel that is converted to private stops syncing |
| Are attachments stored? | Yes. Files are downloaded and stored rather than linked. Files hosted outside Slack, such as Google Drive shares, are skipped. Images that apps post as message blocks, such as `/giphy`, are downloaded without sending the bot token to the image host |
| Are edits and deletions reflected? | Yes. An edit updates the stored message. A deleted message is marked deleted and hidden in Rippit, except a thread's opening message that still has replies, whose text is cleared and kept so the thread stays intact |
| Can Rippit modify Slack? | No posting, editing, or deleting of messages. Rippit joins the public channels you select, and replies privately to whoever invites the bot to a channel |
| Is data used to train models? | No. Rippit does not train any AI models. Your data is used for inference only |

### What a thread becomes in Rippit

Each Slack thread becomes one conversation in Rippit. A message with no replies is a conversation of one message.

| Rippit record | Content |
| - | - |
| Conversation | The channel ID and the opening message's Slack timestamp, joined by an underscore: `C0123ABCD_1712345678.123456` |
| Subject | The thread's opening message |
| Slack Channel | The channel name, without the `#` |
| Commenters | Everyone who posted in the thread, each a workspace member or an app. First Commenter is the author of the opening message, and Last Commenter the author of the latest one. Members are synced with name and email, including deactivated members and bots, so older messages still resolve to a person |
| Comments | Every message in the thread, one comment each, in order |
| Attachments | Each file, and each app-posted image, as its own attachment comment on the thread |
| Reactions | Stored on each message's comment as the list of reaction names on it, such as `thumbsup`. Who reacted and how many times are not stored, and reactions are not a column in the table |
| Link | Links from Rippit to a conversation open the thread in Slack |

Slack's message formatting is converted to Markdown. User mentions, channel mentions, and links resolve to readable names and links.

Channel housekeeping messages are excluded: joins, leaves, renames, topic and purpose changes, pins, and archive and unarchive notices.

## API endpoints

Web API calls go to `https://slack.com/api/`, and file downloads go to each file's `url_private_download` on `files.slack.com`. Every call after the install carries the bot token as `Authorization: Bearer <token>`. The token exchange comes before there is a bot token, so it sends the authorization code with Rippit's app credentials instead.

### Authorization

| Purpose | Method | HTTP |
| - | - | - |
| Token exchange after you approve the install | `oauth.v2.access` | GET |
| Credential check | `auth.test` | POST |
| Token revocation on **Remove**, when no other Rippit account uses the workspace | `auth.revoke` | POST |

### Setup and channel selection

| Purpose | Method | HTTP |
| - | - | - |
| Channels on your list that the bot is in | `users.conversations?types=public_channel&exclude_archived=true` | POST |
| Public channels available to add | `conversations.list?types=public_channel&exclude_archived=true` | POST |
| Join a public channel you picked | `conversations.join` | POST |
| Check whether a channel the bot was invited to is private | `conversations.info` | POST |
| Private reply to whoever invited the bot | `chat.postEphemeral` | POST |

### Sync

| Object | Method | HTTP |
| - | - | - |
| Channel discovery | `users.conversations?types=public_channel&limit=200` | GET |
| Messages, per channel | `conversations.history?channel=<id>&oldest=<watermark>&limit=200` | GET |
| Existing thread replies, once per thread | `conversations.replies?channel=<id>&ts=<thread>&oldest=<thread>&limit=200` | GET |
| Single message refresh | `conversations.history?channel=<id>&latest=<ts>&inclusive=true&limit=1` | GET |
| Single channel refresh | `conversations.info?channel=<id>` | GET |
| Members | `users.list?limit=200` | GET |
| Single member refresh | `users.info?user=<id>` | GET |
| Apps that post without a user, such as incoming webhooks | `bots.info?bot=<id>` | GET |
| File content | The file's `url_private_download` | GET |

Channel discovery lists every public channel the bot is in, and Rippit reads only the ones on your list. Every list is paged with Slack's cursor.

Slack has no endpoint that lists every message in a workspace, so messages are read channel by channel. `conversations.history` returns top-level messages only, which is why `conversations.replies` appears: it reads a thread's existing replies once, when the thread is first seen. Later replies arrive as events.

### Events

Slack sends these events to Rippit, which verifies each request's Slack signature before accepting it.

| Event | Use |
| - | - |
| `message.channels` | New messages, thread replies, edits, and deletions in the channels on your list. Events from other channels are dropped |
| `reaction_added`, `reaction_removed` | Reaction changes in the channels on your list |
| `user_change`, `user_profile_changed`, `team_join` | Member name and email changes, and new members |
| `member_joined_channel` | When someone invites the bot to a public channel, adds it to your list and replies privately to that person |
| `app_uninstalled`, `tokens_revoked` | Rippit deletes the stored credentials |
| `message.groups`, `message.im`, `app_mention` | Received and dropped. Private channel messages, direct messages, and mentions of the app are not stored |

## Sync behavior

| | |
| - | - |
| Channel discovery | Every sync run, from the public channels the bot is in, limited to the channels on your list |
| Message discovery | Per channel, from a watermark on the newest message read, 200 per page |
| Watermark | Advances only after a channel is read to the end without error, so a failure partway through a channel loses nothing |
| New channels | Imports the backfill window chosen at setup the first time the channel is synced |
| Thread replies | Existing replies are read once when the thread is first seen. Later replies arrive as events |
| Edits, deletions, and reactions | Arrive as events. The polling path never sees a deletion, because Slack drops deleted messages from `conversations.history`. When the sync reads a message, it also replaces that message's reaction list with Slack's current one |
| Members | Listed every 12 hours, and updated in between from member events |
| Losing access | A channel the bot was removed from, that was archived or deleted, or that was converted to private drops out of the sync |
| Reconnecting | Removing the integration and connecting the same workspace again restores your channel list, and Rippit rejoins those channels in the background |
| Expected latency | Events are received as Slack sends them and appear in Rippit after the next sync run. The scheduled sync also picks up any top-level message an event missed |

## Rate limiting

* Slack reports most errors, including rate limiting, in a response body marked `"ok": false` rather than as an HTTP error. Rippit reads the body: rate-limited and temporary failures are retried, and a revoked token or a missing scope is not retried.
* Thread reply lookups run at most 4 at a time, and single message lookups at most 2.
* Channel joins run one at a time, up to 50 per request. A rate-limit or authorization error stops the remaining joins, and those channels are reported as not joined.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.