Portal / Nodes / Slack / channel/getHistory
channel/getHistory
Retrieves the message history of a Slack channel, with optional time-range filters using Unix timestamps. Supports full pagination for compliance exports or bounded retrieval for recent-message analysis. Requires channels:history scope.
When to Use
- Compliance archiving: Export complete channel message history to a data warehouse, S3 bucket, or audit log on a scheduled basis to meet retention requirements.
- Outage replay: After a system outage, retrieve messages from the monitoring channel to understand what alerts fired and in what order.
- Usage analytics: Analyze message frequency over time to determine peak usage hours, most active channels, or engagement trends.
- Action item extraction: Pull recent messages from standup or meeting channels and feed them to an AI summarizer to extract action items.
- AI summarization feed: Retrieve the last N messages from a channel as context for an LLM-powered summary or triage assistant.
Configuration
Connection
| Field | Type | Required | Description |
botToken | string | Required | Bot Token starting with xoxb-. Requires channels:history (public) or groups:history (private) scopes. |
Operation Fields
| Field | Type | Required | Description |
channelId | string | Required | The Slack channel ID (starts with C for public, G for private). Example: C08AB3XYZ12. |
returnAll | boolean | Optional | When true, paginates through all messages in the specified time range. Default: true. |
limit | integer | Optional | Maximum messages to return when returnAll is false. Default: 100. Max: 1000. |
oldest | string | Optional | Start of time range as Unix timestamp (float). Only returns messages after this time. Example: 1716700000.000000. |
latest | string | Optional | End of time range as Unix timestamp (float). Only returns messages before this time. Defaults to current time. |
Timestamp Format: Slack uses Unix epoch timestamps with microsecond precision (e.g., 1716729600.000000). To get the timestamp for "24 hours ago" use: {{(Date.now() / 1000 - 86400).toString()}}
Sample Configuration
{
"operation": "channel/getHistory",
"connection": {
"botToken": "{{credentials.slackBotToken}}"
},
"fields": {
"channelId": "{{$json.channelId}}",
"returnAll": false,
"limit": 100,
"oldest": "{{(Date.now() / 1000 - 86400).toString()}}",
"latest": "{{(Date.now() / 1000).toString()}}"
}
}
Validation Errors
| Error Code | Cause | Resolution |
channel_not_found | The channel ID is invalid or the bot is not a member of the private channel. | Verify the channel ID. For private channels, join the channel first using channel/join. |
missing_scope | Bot token lacks channels:history or groups:history scope. | Re-authorize the Slack app with the required history scopes. |
not_in_channel | The bot is not a member of the requested channel. | Use channel/join to add the bot to the channel before reading its history. |
Output
Success Port
| Field | Type | Description |
messageCount | number | Number of messages returned in this response. |
messages | array | Array of message objects. Each contains: messageTs, channel, userId, text, permalink. |
nextCursor | string | Pagination cursor for next page. Empty when all results have been returned. |
status | string | success or error. |
errorCode | string | Slack error code when status is error. |
payload | object | Full raw Slack API response. |
Error Port
On failure with Continue on Error enabled, routes to the error port with status: "error" and populated errorCode. Common cause: bot not in channel — handle by routing to a channel/join node first.
Sample Output
{
"messageCount": 3,
"messages": [
{
"messageTs": "1716729600.001200",
"channel": "C08AB3XYZ12",
"userId": "U01USER12345",
"text": "Deployment to production completed successfully.",
"permalink": "https://yourworkspace.slack.com/archives/C08AB3XYZ12/p1716729600001200"
},
{
"messageTs": "1716729500.000900",
"channel": "C08AB3XYZ12",
"userId": "U01USER67890",
"text": "Starting deployment pipeline for v2.4.1",
"permalink": "https://yourworkspace.slack.com/archives/C08AB3XYZ12/p1716729500000900"
}
],
"nextCursor": "",
"status": "success",
"errorCode": "",
"payload": { "ok": true, "messages": [ ... ], "has_more": false }
}
Expression Reference
| Expression | Result |
{{$node["channel-gethistory"].json.messageCount}} | Total messages returned — use as loop bound or report metric. |
{{$node["channel-gethistory"].json.messages}} | Full message array — pass to AI summarization or compliance export node. |
{{$node["channel-gethistory"].json.messages[0].text}} | Text of the most recent message. |
{{$node["channel-gethistory"].json.messages.map(m => m.text).join('\n')}} | All message texts joined — useful as input to an AI summarization prompt. |
{{(Date.now() / 1000 - 86400).toString()}} | Unix timestamp for 24 hours ago — use as the oldest parameter. |
Node Policies & GuardRails
| Policy Area | Recommendation |
| Scope requirements | Requires channels:history for public channels and groups:history for private channels. The bot must also be a member of the channel. |
| Rate limiting | Tier 3 (50+ req/min). History retrieval can generate many paginated requests on busy channels — always bound the time range with oldest and latest for production workflows. |
| No hard-coded IDs | Always pass channelId dynamically. Never hard-code channel IDs in configuration. |
| Time-range bounding | Always set oldest for production runs. Unbounded returnAll on a busy channel can return tens of thousands of messages, consuming significant memory and time. |
| Privacy consideration | Message history contains user-generated content. Ensure downstream storage and processing complies with your organization's data retention and privacy policies. |
| Archive access | You can retrieve history from archived channels. The bot must have been a member when messages were sent, or have admin-level access. |
Examples
Example 1 — Daily Compliance Archive Export
Scheduled nightly workflow that exports the previous day's messages from all regulated channels to a compliance database.
// Runs at 00:05 daily
// Calculates yesterday's time window
const yesterdayStart = (new Date().setHours(0,0,0,0) / 1000 - 86400).toString();
const yesterdayEnd = (new Date().setHours(0,0,0,0) / 1000).toString();
{
"operation": "channel/getHistory",
"fields": {
"channelId": "{{$json.channelId}}",
"returnAll": true,
"oldest": yesterdayStart,
"latest": yesterdayEnd
}
}
// Next: HTTP Request node → POST to compliance archive API
Example 2 — AI-Powered Daily Standup Summary
Pulls the last 24 hours of standup messages and sends them to an LLM for summarization, then posts the summary to a digest channel.
{
"operation": "channel/getHistory",
"fields": {
"channelId": "C08STANDUP01",
"returnAll": false,
"limit": 50,
"oldest": "{{(Date.now() / 1000 - 86400).toString()}}"
}
}
// Code node: format messages as LLM prompt
const messages = $node["channel-gethistory"].json.messages
.map(m => `${m.userId}: ${m.text}`).join('\n');
// AI node → summarize → message/send to #standup-digest
Example 3 — Post-Incident Message Replay
After a monitoring outage, retrieves all messages from the incident window to reconstruct the timeline.
{
"operation": "channel/getHistory",
"fields": {
"channelId": "C08INCIDENTS",
"returnAll": true,
"oldest": "{{$json.incidentStartTs}}",
"latest": "{{$json.incidentEndTs}}"
}
}
// Output: ordered message list for incident post-mortem report