Slack integration
Retrieve messages and thread replies from the Slack channels an administrator approves. Recover the discussion behind a decision, with author names, channel context, and a link back to the original message.
Approved channels define the boundary
Retrieve messages and thread replies from the Slack channels an administrator approves. Nothing is read until an administrator approves a specific channel, so the source boundary is a deliberate choice rather than the whole workspace.
Messages, threads, and shared files
Channel messages with their thread replies kept together.
Extractable text from documents shared in an approved channel.
Private channel content limited to that channel’s current members.
Private channels stay with their members
Membership is evaluated when a query runs, not when the message was imported. Someone who leaves a private channel loses access to what was already indexed from it.
Workspace readiness checklist
- A Slack workspace where an administrator can approve the intended channels.
- MemorySync added to each approved channel, which a person must do for private channels.
- A MemorySync project for the imported conversation knowledge.
Check items for your own planning. Nothing here changes a live connection.
0 of 4 planning steps complete
History window on the first import
The first import reads a bounded window of past conversation rather than the entire archive. Workspaces on a free Slack plan also hide older history at the source, so the window is the smaller of the two limits.
- 1Approve channels
An administrator selects each channel to index.
- 2Import history
MemorySync reads the approved channels within the configured history window.
- 3Track new activity
New messages, edits, and deletions arrive as they happen.
Edits and deletions follow the source
Verify retrieval from an approved channel
Query a memorable phrase from a known message in an approved channel. Confirm the result names the channel and author, and that its link opens the original message in Slack.
Troubleshooting and related sources
Why is a channel missing from the list?
Confirm it is an active channel and that MemorySync has been added to it. Private channels must be selected by a person in Slack first.
Why can a colleague not retrieve private channel content?
Private channel content is limited to that channel’s current members, and each member must be linked to a MemorySync account.
Why did a message disappear from results?
Deleting a message in Slack purges the memories derived from it.
Why did an approved channel stop syncing?
A channel that becomes private or is shared with an external organization has its approval revoked automatically, because its content boundary changed. An administrator can review and re-approve it under the new rules.
Operations on this page
| Operation | Method and path | Python | Node.js |
|---|---|---|---|
| List selectable channels | GET …/{connection_id}/slack/available-channels | connections.slack.available_channels | connections.slack.availableChannels |
| List selected channels | GET …/{connection_id}/slack/channels | connections.slack.channels | connections.slack.channels |
| Select channels | POST …/{connection_id}/slack/channels | connections.slack.add_channels | connections.slack.addChannels |
| Deselect a channel | DELETE …/{connection_id}/slack/channels/{channel_id} | connections.slack.remove_channel | connections.slack.removeChannel |
| Read the exclusion policy | GET …/{connection_id}/slack/exclusion-policy | connections.slack.exclusion_policy | connections.slack.exclusionPolicy |
| Replace the exclusion policy | PUT …/{connection_id}/slack/exclusion-policy | connections.slack.set_exclusion_policy | connections.slack.setExclusionPolicy |
| List identity mappings | GET …/{connection_id}/slack/identities | connections.slack.identities | connections.slack.identities |
| Link an identity | POST …/{connection_id}/slack/identities/link | connections.slack.link_identity | connections.slack.linkIdentity |
| Re-sync identities | POST …/{connection_id}/slack/identities/sync | connections.slack.sync_identities | connections.slack.syncIdentities |
Authentication and scope
| Requirement | Contract |
|---|---|
| Credential | An API key sent as X-API-Key. Connector operations are not end-user scoped. |
| Read scope | integrations:read for every GET. |
| Write scope | integrations:write for every POST, PUT, PATCH and DELETE. |
| Tenant | Derived from the authenticated key. There is no tenant parameter to pass or to get wrong. |
X-End-User-ID | Not used. A connection belongs to the organization, not to one end user. |
Before you start
You need a working Slack connection. Create one with the OAuth flow on Providers & OAuth — Slack cannot be connected with an API key. Everything on this page assumes connection["status"] == "connected".
1. See which channels are available
Reads the channels the installation can see, annotated for a picker, so a user chooses from reality rather than typing a channel name that may not exist or may not be visible to the bot. It takes no parameters and performs no ingestion.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)available = client.connections.slack.available_channels("conn_8f21a4")print(available["total"])for channel in available["channels"]:print(channel["id"], channel["name"], channel["selectable"], channel["reason"])
| Field on each channel | Meaning |
|---|---|
id, name | The Slack channel id and name. |
channel_type, is_private, is_external_shared | What kind of channel it is. |
is_member, is_archived | Whether the bot is in it, and whether Slack has archived it. |
num_members, topic, purpose | Context for a human choosing from a list. May be absent. |
approved | Already selected on this connection. |
selectable | Whether it can be approved at all. Check this before offering it. |
reason | Why it is not selectable, when it is not — an exclusion pattern, or a missing invite. |
2. Select the channels to sync
Selecting a channel does not import it immediately. It marks it for the next sync, which you trigger on Sync & Jobs.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)client.connections.slack.add_channels("conn_8f21a4", ["C0123SUPPORT", "C0456PRODUCT"])
3. Read back what is selected
This one returns a bare JSON array rather than an object with a channels key, so iterate the response itself.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)for channel in client.connections.slack.channels("conn_8f21a4"):print(channel["channel_id"], channel["channel_name"], channel["state"], channel["is_active"])
| Field | Meaning |
|---|---|
channel_id, channel_name | Slack's identifier and name. The name is nullable. |
state, state_detail | Approval state, and why it is in that state. |
is_active | Whether future syncs will read it. |
messages_synced | Lifetime tally of messages read across all runs. |
last_message_ts, last_synced_at | Position reached and when it was last read. |
authorized_at | When it was approved. |
4. Block channels by name pattern
The exclusion policy is a list of channel-name patterns this connection will never sync. It is a standing rule rather than a per-channel decision: a pattern blocks matching channels that are selected now and any that appear later, which is what you want for whole families like incident-* or dm-*.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)client.connections.slack.set_exclusion_policy("conn_8f21a4",patterns=["random", "incident-*", "*-alerts"],)policy = client.connections.slack.exclusion_policy("conn_8f21a4")print(policy["tenant_patterns"], policy["effective_patterns"])
| Response field | Meaning |
|---|---|
deployment_patterns | The floor set by the deployment. Read-only here; PUT cannot remove one. |
tenant_patterns | The patterns you sent. This is the only list PUT replaces. |
effective_patterns | Both lists combined — what actually gets applied. |
| Pattern rule | Behaviour |
|---|---|
| Syntax | Shell-style globbing: *, ? and [seq]. incident-* blocks incident-2026-01. |
| Case | Both pattern and channel name are lowercased before matching, so HR-* and hr-* behave alike. |
Leading # | Stripped. #random and random are the same pattern. |
| Limits | Up to 200 patterns, each truncated to 128 characters. Duplicates are dropped. |
| Unnamed channels | A channel with no resolvable name is not blocked by a pattern. |
5. Map Slack users to MemorySync users
This is the step that makes Slack memories useful. Without a mapping, a message is not attributed to a person, so querying as that person will not find it. A mapping joins a Slack member id to a numeric MemorySync user id.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)roster = client.connections.slack.identities("conn_8f21a4")print(roster["total"], roster["matched"], roster["unmatched"])client.connections.slack.link_identity("conn_8f21a4",slack_user_id="U024BE7LH",memorysync_user_id=4821,)
| Field | Meaning |
|---|---|
slack_user_id | Required. The Slack member id, such as U024BE7LH. |
memorysync_user_id | The numeric MemorySync user id to attribute messages to. Send null to unlink. |
6. Refresh the roster
Pulls the workspace member list again so newly joined people appear as linkable. It does not create mappings — those stay deliberate.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)client.connections.slack.sync_identities("conn_8f21a4")
7. Drop a channel
Removes it from the selection so future syncs skip it. Objects and memories already imported are untouched.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",)client.connections.slack.remove_channel("conn_8f21a4", "C0456PRODUCT")
Errors and next action
| Status | Meaning | Next action |
|---|---|---|
401 | Missing, malformed or inactive API key. | Check server configuration without printing the key. |
403 | The key lacks integrations:read or integrations:write. | Grant the scope on the key, or use a key that has it. |
404 | The connection, object or job is not visible to this tenant. | Confirm the identifier belongs to this organization. |
409 | The connection is in a state that forbids the operation. | Read the connection status first and act on it. |
429 | Rate limited, either by MemorySync or by the upstream provider. | Back off; do not tighten a polling loop in response. |
5xx | Service failure. | Treat a write outcome as uncertain and reconcile by reading the connection back. |