Joining Huddles in Non-Member Channels
By default, your Slack huddle bot will not be able to request to join huddles in the following circumstances:
- Private huddles in channels where the bot not a member
- One-on-one huddles between individual users (direct messages)
To allow your bot to do this, you'll need to create a Slack application and have individual end users authorize it. Once authorized, your bot can request access to these restricted huddles.
While this step is optional, it is recommended if you want to ensure that your integration can access all available Slack huddle data for your users.
Integration Steps
If you already have a Slack app set up for your product, there’s no need to start from scratch. You can simply integrate your existing Slack app with Recall.ai to take advantage of all these features. If so, you can jump to step 2. Otherwise, read on.
Slack Marketplace Review
If you do not already have a published Slack app, we do not recommend trying to publish this app to the Slack Marketplace. The approval process can take up to 8 weeks and has strict requirements, and approval is not guaranteed.
If your app is not listed on the Slack Marketplace, you are not required to go through app review and can still distribute your app.
Step 1: Create your Slack App
- Navigate to https://api.slack.com/apps?new_app=1 and select “From scratch”
- Enter your Slack application’s name. This should reflect your brand as it will be visible to all end-users.
- Select a workspace to develop it in. This will just be for testing: you’ll be able to add it to all your end-users’ workspaces.
- Click "Create App"

Choose an appropriate workspace to develop your app in
Slack Apps are permanently tied to a home workspace. You should choose your company's Slack workspace rather than create a new workspace just for this app.
Step 2: Update the Slack App's Redirect URL
When a user tries to connect to your Slack app, they’ll be sent to Slack’s authorization page, where they’ll review and approve the permissions your app is requesting. After the user grants access, Slack will redirect them back to the redirect URL you specified in your app settings. This redirect includes a special authorization code in the URL.
Your application should be set up to receive this code and immediately exchange it with Slack for an access token. This access token is what Recall will store and use to interact with Slack on behalf of the user to discover channels and automatically listen for huddles happening within them.
To set up your redirect URL:
- Navigate to “OAuth & Permissions”
- In “Redirect URLs”, add your product’s redirect URL (e.g.
https://myproduct.com/slack/oauth/callback
) to process the Slack authorization grant (this should not include recall's domain) - Click "Save URLs"

- Add appropriate logic to your product to handle the Slack OAuth flow.
const SLACK_CLIENT_ID = process.env.SLACK_CLIENT_ID!;
const SLACK_CLIENT_SECRET = process.env.SLACK_CLIENT_SECRET!;
const SLACK_REDIRECT_URI = process.env.SLACK_REDIRECT_URI!;
const RECALL_API_KEY = process.env.RECALL_API_KEY!;
// This endpoint is the redirect url you set in your Slack App's settings
app.get('/slack/oauth/callback', async (req, res) => {
const code = req.query.code as string;
const state = req.query.state as string;
const error = req.query.error as string | undefined;
if (error) {
return res.status(400).send(`Slack OAuth error: ${error}`);
}
if (!code) {
return res.status(400).send('Missing code parameter from Slack');
}
if (!checkState(state)) {
return res.status(400).send('Invalid state parameter');
}
let accessToken;
try {
// Exchange the code for an access token
const response = await fetch('https://slack.com/api/oauth.v2.access', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
code,
client_id: SLACK_CLIENT_ID,
client_secret: SLACK_CLIENT_SECRET,
redirect_uri: SLACK_REDIRECT_URI,
}),
});
const data = await response.json();
if (!data.ok) {
return res.status(400).send(`Slack OAuth failed: ${data.error}`);
}
// you now have access_token, team info, authed user, etc.
// you can store these securely in your database for future use
// example: data.access_token, data.team, data.authed_user
accessToken = data.access_token;
} catch (err) {
res.status(500).send('Internal server error');
}
try {
const response = await fetch(`https://api.recall.ai/api/v2/slack-teams/{slack_team_integration_id}/oauth-tokens/`, {
method: 'POST',
headers: {
'Authorization': RECALL_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
token: accessToken,
}),
});
const data = await response.json();
return res.status(200);
} catch (err) {
res.status(500).send('Internal server error');
}
});
Step 3: Update the Slack App's permissions
- Navigate to “OAuth & Permissions”
- Click "Save URLs"
- Under “User Token Scopes” in “Scopes”, click “Add an OAuth Scope” and add the following:
channels:read
,groups:read
,im:read
,mpim:read
,team:read
andusers:read

Step 4: Onboard Users
- In your Slack application's dashboard, navigate to "Manage Distribution"
- Under "Share Your App with Other Workspaces", expand all collapsible sections and follow the steps to prepare your application for public unlisted distribution
- Click "Activate Public Distribution"

- Navigate to "Basic Information" and take note of the following values: Client ID and Client Secret
- Navigate to "OAuth & Permissions" and take note of all the scopes listed
- Programmatically generate your OAuth URL to allow users to authorize your application into their workspace, separating your scopes with a
,
character and properly URL escaping themhttps://slack.com/oauth/v2/authorize?scope={{YOUR APPLICATION BOT SCOPES}}&user_scope={{YOUR APPLICATION USER SCOPES}}&redirect_uri={{YOUR REDIRECT URI}}&client_id={{YOUR CLIENT ID}}&state={{CRYPTOGRAPHICALLY SECURE RANDOM IDENTIFIER}}
- Give this URL to your end-users, such as through a button in your product
Ensure
state
is unique and securely verifiableThe state query param should be encrypted (e.g. JWT) for you to verify in the callback. This guarantees that your app was the one that generated the request and it can't be replayed.
import crypto from 'crypto';
const SLACK_CLIENT_ID = process.env.SLACK_CLIENT_ID!;
const SLACK_REDIRECT_URI = process.env.SLACK_REDIRECT_URI!;
const SLACK_SCOPES = [
'channels:read',
'groups:read',
'im:read',
'mpim:read',
'team:read',
'users:read'
].join(',');
// generates a cryptographically secure random string for the state parameter
function generateSecureState(length = 32): string {
return crypto.randomBytes(length).toString('hex');
}
// generates the Slack OAuth URL and saves the state
export async function generateSlackOAuthUrl(userId: string): Promise<string> {
const state = generateSecureState();
await saveOAuthStateToDB(state, userId);
const params = new URLSearchParams({
scope: SLACK_SCOPES,
redirect_uri: SLACK_REDIRECT_URI,
client_id: SLACK_CLIENT_ID,
state
});
return `https://slack.com/oauth/v2/authorize?${params.toString()}`;
}
app.get('/auth/slack', async (req, res) => {
const userId = req.query.user_id as string || 'user-123';
try {
const oauthUrl = await generateSlackOAuthUrl(userId);
return res.redirect(oauthUrl);
} catch (err) {
console.error('Failed to generate Slack OAuth URL:', err);
return res.status(500).send('Internal server error');
}
});
What Happens Next?
After completing the Slack App integration steps, your application will be ready to interact with Slack workspaces and monitor private huddles. Here’s what you can expect:
-
User Authorization: As users authorize your Slack app using the OAuth flow, your backend will securely receive, store, and forward access tokens. These tokens enable Recall.ai to access necessary Slack resources on behalf of each user or workspace.
-
Channel and Huddle Discovery: With the required permissions in place, Recall.ai will be able to discover channels (including private channels where the app has been authorized) and automatically detect active huddles.
-
Webhook Event Delivery: When a huddle starts or relevant events occur, Recall.ai will send webhook notifications to your registered endpoint. These events will contain meeting metadata and other important information, allowing your application to process or store the data as needed.
Your integration can only monitor private huddles in channels where at least one member has authorized the app.
This means it may not knock on every private huddle across the workspace. It will only knock on the private channels where it has visibility via an authorized user.
Adoption is still beneficial because the more users who install the app, the more private channels it can cover. Full workspace adoption isn’t required for private channel support. Huddles in public channels can always be discovered and detected.
At this point, your Slack app is fully integrated with Recall.ai and ready to capture and process huddle data from across your users’ Slack workspaces!
Updated 8 days ago
Setup your Slack application to work with your Slack team integration