Slack
Slack is a messaging app for business that connects people to the information they need. By bringing people together to work as one unified team, Slack transforms the way organizations communicate.
The Slack Wrapper is a WebAssembly (Wasm) foreign data wrapper which allows you to query Slack workspaces, channels, messages, and users directly from your Postgres database.
Available Versions
Version | Wasm Package URL | Checksum |
---|---|---|
0.0.6 | https://github.com/supabase/wrappers/releases/download/wasm_slack_fdw_v0.0.6/slack_fdw.wasm |
349cb556f87a0233e25eb608a77e840531bc87f1acf9916856268bdcdd9973e2 |
0.1.0 | https://github.com/supabase/wrappers/releases/download/wasm_slack_fdw_v0.1.0/slack_fdw.wasm |
5b022b441c0007e31d792ecb1341bfffed1c29cb865eb0c7969989dff0e8fdc3 |
Preparation
Before you can query Slack, you need to enable the Wrappers extension and store your credentials in Postgres.
Enable Wrappers
Make sure the wrappers
extension is installed on your database:
1 |
|
Enable the Slack Wrapper
Enable the Wasm foreign data wrapper:
1 2 3 |
|
Create a Slack API Token
- Visit the Slack API Apps page
- Click "Create New App" and select "From scratch"
- Name your app and select the workspace to install it
- Navigate to "OAuth & Permissions" in the sidebar
- Under "Scopes", add the following Bot Token Scopes:
channels:history
- Read messages in public channelschannels:read
- View basic channel informationusers:read
- View users in workspaceusers:read.email
- View email addressesfiles:read
- View files shared in channelsreactions:read
- View emoji reactionsteam:read
- View information about the workspaceusergroups:read
- View user groups and their members- Install the app to your workspace
- Copy the "Bot User OAuth Token" that starts with
xoxb-
Store credentials (optional)
By default, Postgres stores FDW credentials inside pg_catalog.pg_foreign_server
in plain text. Anyone with access to this table will be able to view these credentials. Wrappers is designed to work with Vault, which provides an additional level of security for storing credentials. We recommend using Vault to store your credentials.
1 2 3 4 5 6 7 |
|
Connecting to Slack
We need to provide Postgres with the credentials to access Slack and any additional options. We can do this using the create server
command:
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 |
|
The full list of server options are below:
fdw_package_*
: required. Specify the Wasm package metadata. You can get the available package version list from above.api_token
|api_token_id
api_token
:Slack Bot User OAuth Token, required if not using Vault.api_token_id
: Vault secret key ID storing the Slack token, required if using Vault.
workspace
- Slack workspace name, optional.
Create a schema
We recommend creating a schema to hold all the foreign tables:
1 |
|
Entities
The Slack Wrapper supports data reads from the Slack API.
Messages
This represents messages from channels, DMs, and group messages.
Ref: Slack conversations.history API
Operations
Object | Select | Insert | Update | Delete | Truncate |
---|---|---|---|---|---|
messages | ✅ | ❌ | ❌ | ❌ | ❌ |
Usage
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Notes
- The
ts
field is the message timestamp ID and is used as the primary key - Supports query pushdown for channel filtering
- Requires the
channels:history
scope
Channels
This represents all channels in the workspace.
Ref: Slack conversations.list API
Operations
Object | Select | Insert | Update | Delete | Truncate |
---|---|---|---|---|---|
channels | ✅ | ❌ | ❌ | ❌ | ❌ |
Usage
1 2 3 4 5 6 7 8 9 10 11 |
|
Notes
- The
id
field is the channel ID and is used as the primary key - Requires the
channels:read
scope
Users
This represents all users in the workspace.
Ref: Slack users.list API
Operations
Object | Select | Insert | Update | Delete | Truncate |
---|---|---|---|---|---|
users | ✅ | ❌ | ❌ | ❌ | ❌ |
Usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
|
Notes
- The
id
field is the user ID and is used as the primary key - Requires the
users:read
scope - Email field requires the
users:read.email
scope - Supports query pushdown for filtering by
name
,email
, andteam_id
directly via the Slack API - Supports sorting by
name
,real_name
, andemail
- Supports LIMIT and OFFSET clauses for pagination
User Groups
This represents user groups (a.k.a. user groups) in the workspace.
Ref: Slack usergroups.list API
Operations
Object | Select | Insert | Update | Delete | Truncate |
---|---|---|---|---|---|
usergroups | ✅ | ❌ | ❌ | ❌ | ❌ |
Usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Notes
- The
id
field is the user group ID and is used as the primary key - Requires the
usergroups:read
scope - Supports query pushdown for filtering by
team_id
andinclude_disabled
- Supports sorting by
name
,handle
,date_create
, anddate_update
- Supports LIMIT and OFFSET clauses for pagination
User Group Members
This represents the membership relationship between users and user groups.
Ref: Slack usergroups.users.list API
Operations
Object | Select | Insert | Update | Delete | Truncate |
---|---|---|---|---|---|
usergroup_members | ✅ | ❌ | ❌ | ❌ | ❌ |
Usage
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Notes
- The
usergroup_id
anduser_id
fields form a composite primary key - Requires the
usergroups:read
scope - Supports LIMIT and OFFSET clauses for pagination
- To avoid excessive API calls and potential rate limiting, consider using materialized views instead of direct joins
Files
This represents files shared in the workspace.
Ref: Slack files.list API
Operations
Object | Select | Insert | Update | Delete | Truncate |
---|---|---|---|---|---|
files | ✅ | ❌ | ❌ | ❌ | ❌ |
Usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Notes
- The
id
field is the file ID and is used as the primary key - Requires the
files:read
scope - Supports query pushdown for filtering by channel or user
Team Info
This represents information about the team/workspace.
Ref: Slack team.info API
Operations
Object | Select | Insert | Update | Delete | Truncate |
---|---|---|---|---|---|
team-info | ✅ | ❌ | ❌ | ❌ | ❌ |
Usage
1 2 3 4 5 6 7 8 9 10 |
|
Notes
- Returns a single row with team information
- No special scopes required beyond authentication
Query Pushdown Support
This FDW supports the following condition pushdowns:
Resource | Supported Filters | Sorting | Limit/Offset |
---|---|---|---|
messages | channel_id, oldest, latest | No | Yes* |
users | name, email, team_id | name, real_name, email | Yes |
usergroups | team_id, include_disabled | name, handle, date_create, date_update | Yes |
usergroup_members | (no filter support) | No | Yes |
channels | types (public/private) | No | Yes* |
files | channel_id, user_id, ts_from, ts_to | No | No |
team-info | (no filter support) | No | No |
* Pagination is supported through cursor-based pagination from the Slack API
Supported Data Types
Postgres Data Type | Slack JSON Type |
---|---|
text | string |
boolean | boolean |
integer | number |
bigint | number |
timestamp | string (Unix timestamp) |
Required Slack API Scopes
Each entity type in the Slack FDW requires specific API scopes. If you get a missing_scope
error, you may need to add additional scopes and reinstall your app to the workspace.
Entity Type | Required Scopes | Error If Missing |
---|---|---|
users | users:read |
"The token used is not granted the required scopes" |
users (emails) | users:read.email |
"missing_scope" on email fields |
usergroups | usergroups:read |
"missing_scope" when querying user groups |
usergroup_members | usergroups:read |
"missing_scope" when querying user group members |
channels | channels:read |
"missing_scope" when querying channels |
messages | channels:history , channels:read |
"missing_scope" when querying messages |
files | files:read |
"missing_scope" when querying files |
team-info | team:read |
"missing_scope" when querying team info |
Adding Scopes to an Existing App
If you need to add scopes to an existing Slack app:
- Go to Your Slack Apps
- Select your app
- Click "OAuth & Permissions" in the sidebar
- Under "Bot Token Scopes", click "Add an OAuth Scope"
- Add any missing scopes from the table above
- Scroll up and click "Reinstall to Workspace"
- Approve the new permissions
- Copy the new Bot User OAuth Token (it may have changed)
- Update your token in your database server configuration
Limitations
This section describes important limitations and considerations when using this FDW:
- Large result sets may experience slower performance due to pagination requirements
- Rate limits are enforced by the Slack API (Tier 2: 20+ requests/minute)
- Messages older than the workspace retention policy are not accessible
- Private channels require the
groups:history
andgroups:read
scopes - Direct messages require the
im:history
andim:read
scopes
Troubleshooting
Error: "Slack API error: missing_scope"
This error occurs when your Slack token doesn't have all the required OAuth scopes for the resource you're trying to access.
Solution: 1. Check the Required Slack API Scopes section above to see which scopes are needed for the entity you're querying 2. Follow the steps in the "Adding Scopes to an Existing App" section to add the missing scopes 3. Reinstall your app to the workspace 4. Update your token in the PostgreSQL server configuration
Error: "channel_id is required for querying messages"
When querying the messages
table, you must include a WHERE channel_id = 'CXXXXXXXX'
clause.
Solution:
1 2 3 4 5 |
|
Error: "Rate limit exceeded"
Slack's API enforces rate limits (Tier 2: ~20 requests/minute).
Solution: - Add more specific WHERE clauses to reduce the number of API calls - Use smaller LIMIT values - Consider materialized views for frequent queries:
1 2 3 4 5 6 7 8 |
|
Examples
Below are some examples on how to use Slack foreign tables.
Basic Example
This example will create a "foreign table" inside your Postgres database and query its data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
User Information
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
User Groups Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Messages from a Specific Channel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|