slice icon Context Slice

Slack API Usage Guide

Authentication

Slack API uses OAuth2 Bearer tokens:

const res = await fetch(url, {
  headers: { Authorization: "Bearer PLACEHOLDER_TOKEN" }
});

Common Endpoints

auth.test - Verify Connection

GET https://slack.com/api/auth.test

Returns: user_id, user, team_id, team (workspace name)

users.list - List Workspace Users

GET https://slack.com/api/users.list
  ?limit=200
  &cursor=<next_cursor>

Paginate with response_metadata.next_cursor. Returns all workspace members.

User object fields:

  • id - User ID (U...)
  • name - Username
  • real_name - Full name
  • profile.display_name - Display name (preferred)
  • is_bot - Bot flag
  • deleted - Deactivated flag

Build user map:

const userMap = new Map();
for (const u of users) {
  if (!u.is_bot && !u.deleted) {
    userMap.set(u.id, {
      name: u.profile?.display_name || u.real_name || u.name,
      realName: u.real_name,
    });
  }
}

conversations.list - List Channels

GET https://slack.com/api/conversations.list
  ?types=public_channel,private_channel,im,mpim
  &exclude_archived=true
  &limit=200
  &cursor=<next_cursor>

Types:

  • public_channel - Public channels (C...)
  • private_channel - Private channels (G...)
  • im - Direct messages (D...)
  • mpim - Multi-person DMs (G...)

Channel object fields:

  • id - Channel ID
  • name - Channel name
  • is_member - User is member
  • is_private - Private channel
  • is_im - Direct message
  • is_mpim - Multi-person DM
  • num_members - Member count

conversations.info - Get Channel Info

GET https://slack.com/api/conversations.info
  ?channel=<channel_id>

Returns full channel details.

conversations.history - Get Messages

GET https://slack.com/api/conversations.history
  ?channel=<channel_id>
  &limit=200
  &oldest=<unix_timestamp>
  &latest=<unix_timestamp>
  &cursor=<next_cursor>

Message object fields:

  • ts - Timestamp (also message ID)
  • user - User ID who sent
  • text - Message text
  • thread_ts - Parent thread timestamp
  • reply_count - Replies in thread
  • reactions - Array of reactions
  • subtype - Special message type (join, leave, etc.)
  • attachments - Rich attachments
  • blocks - Block Kit blocks

Convert timestamp:

const date = new Date(parseFloat(msg.ts) * 1000);

Rate Limits

Slack uses tiered rate limits:

  • Tier 1: 1 request/second (auth.test)
  • Tier 2: 20 requests/minute (most list endpoints)
  • Tier 3: 50 requests/minute (conversations.history)
  • Tier 4: 100 requests/minute (users.list)

When fetching many channels, batch with delays:

for (let i = 0; i < channels.length; i += 15) {
  const batch = channels.slice(i, i + 15);
  await Promise.all(batch.map(ch => fetchHistory(ch.id)));
  await new Promise(r => setTimeout(r, 500)); // Rate limit pause
}

Parallelism Pattern

Fetch users and channels in parallel on startup:

const [authData, channelsData, usersData] = await Promise.all([
  fetch("https://slack.com/api/auth.test", { headers }),
  fetchAllChannels(),
  fetchAllUsers(),
]);

Then resolve user IDs from messages:

const userName = userMap.get(msg.user)?.name || msg.user;

Common Filters

Filter out noise:

  • msg.subtype - Skip system messages (join, leave, etc.)
  • !msg.user - Skip messages without user
  • !userMap.has(msg.user) - Skip unresolved users (bots)

Time filters:

const now = Date.now();
const sevenDaysAgo = Math.floor((now - 7 * 24 * 60 * 60 * 1000) / 1000);
// Use as 'oldest' parameter

Error Handling

Slack errors return { ok: false, error: "error_code" }.

Common errors:

  • channel_not_found - Invalid channel ID
  • not_in_channel - No access to channel
  • ratelimited - Hit rate limit (retry after delay)
  • missing_scope - Token missing required OAuth scope