Slack audit logs record who did what across your Enterprise organization - logins, channel and file actions, app installs, and more. Helr pulls these events via the Slack Audit Logs API (Using the Audit Logs API): GET https://api.slack.com/audit/v1/logs. Events are returned in an entries array and paginated with a cursor in response_metadata.next_cursor; you pass it back as the cursor query parameter on the next request.
You authenticate with a Slack user token (prefix xoxp-) that has the auditlogs:read scope. The app must be installed by the Owner of an Enterprise organization (not a single workspace). The token must be associated with that Enterprise org owner.
- The Audit Logs API is only available for Slack workspaces on an Enterprise plan. Standard (Free, Pro, Business+) workspaces do not have access; the API returns errors such as
feature_not_enabled,invalid_workspace, orteam_not_authorized. - An Enterprise organization and an app with the
auditlogs:readUser Token Scope, installed on the organization (not a workspace) by the Owner. - Data is not available prior to March 2018.
- Go to Slack API - Create app and create an app (or use an existing one).
- In the app, open OAuth & Permissions. Under User Token Scopes, add auditlogs:read.
- Under Manage Distribution, enable distribution as needed, then use Share Your App with Your Workspace (or org). Copy the Install to Workspace (or Install to Organization) URL.
- Open that URL in a browser and complete the OAuth flow. You must be logged in as the Owner of the Enterprise organization. In the install screen, choose the organization in the dropdown, not a single workspace.
- After install, copy the User OAuth Token (starts with
xoxp-). Store it asSLACK_AUDIT_TOKEN(or another env var you reference inhelr.yaml).
Note: The token must be a user token (xoxp-) for an Enterprise organization owner. Enterprise org administrator tokens are not currently supported for the Audit Logs API.
In helr.yaml, add a Slack audit log source. The API base URL is fixed; you can use query params for time range and filters.
slack-audit:
url: "https://api.slack.com/audit/v1/logs"
schedule:
interval_secs: 300
jitter_secs: 30
auth:
type: bearer
token_env: SLACK_AUDIT_TOKEN
headers:
Accept: "application/json"
query_params:
limit: "200"
pagination:
strategy: cursor
cursor_param: cursor
cursor_path: response_metadata.next_cursor
max_pages: 25
resilience:
timeout_secs: 30
retries:
max_attempts: 5
initial_backoff_secs: 2
max_backoff_secs: 60
multiplier: 2.0
circuit_breaker:
enabled: true
failure_threshold: 5
success_threshold: 2
half_open_timeout_secs: 60
rate_limit:
respect_headers: true
page_delay_secs: 2SLACK_AUDIT_TOKEN: Your Slack user token (xoxp-...) withauditlogs:read, from an Enterprise org owner install.limit: Slack accepts up to 9,999 per request; 100–200 is recommended for steady pagination. Helr already supports theentriesarray and cursor fromresponse_metadata.next_cursor.- Rate limit: The Audit Logs API is Tier 3: up to 50 calls per minute per organization (org-wide, not per-app). Use a conservative
interval_secs(e.g. 300) andpage_delay_secs(e.g. 2) to avoidrate_limitederrors.
export SLACK_AUDIT_TOKEN="xoxp-..."
helr validate
helr test --source slack-audit # or: helr run --onceYou should see NDJSON lines (one per audit event). Then run helr run for continuous collection.
You can narrow results with optional query parameters. Add them under query_params in helr.yaml (or use first_request_query_params if you only want them on the first request when there is no saved cursor).
| Parameter | Type | Description |
|---|---|---|
oldest |
Integer | Unix timestamp of the least recent event to include (inclusive). Data not available before March 2018. |
latest |
Integer | Unix timestamp of the most recent event to include (inclusive). |
limit |
Integer | Max results per request (optimistic); maximum 9,999. |
action |
String | Comma-separated action names (e.g. user_login,file_uploaded), max 30. |
actor |
String | User ID who initiated the action (e.g. W123AB456). |
entity |
String | ID of the target entity (channel, workspace, file, etc.). |
Example: only logins for a specific user since a given time:
slack-audit:
url: "https://api.slack.com/audit/v1/logs"
# ...
query_params:
limit: "200"
oldest: "1521214343"
action: "user_login"
actor: "W123AB456"Incremental from last event: To resume from the latest event timestamp on each first request (no saved cursor), use incremental_from. Helr stores the max value of the given event field after each poll and sends it as the specified query param on the first request. Slack events use date_create (Unix timestamp); the API accepts oldest as that param:
slack-audit:
url: "https://api.slack.com/audit/v1/logs"
# ... auth, pagination, etc.
incremental_from:
state_key: "oldest_ts"
event_timestamp_path: "date_create"
param_name: "oldest"On the first request (or after cursor reset), Helr will add oldest=<last_stored_ts> from state so you only fetch events newer than the last run. You can still set oldest / latest explicitly in query_params for a fixed window.
Events include an id field. To skip duplicates across polls or replay, add:
slack-audit:
# ...
dedupe:
id_path: "id"
capacity: 10000To test without calling the API repeatedly: run once with --record-dir ./recordings (with valid credentials) to save responses, then use helr run --once --replay-dir ./recordings to replay from disk.
| Symptom | Check |
|---|---|
SLACK_AUDIT_TOKEN unset |
Export the token; use a user token (xoxp-) with auditlogs:read. |
missing_authentication / invalid_authentication |
Token present and valid; must be for an Enterprise organization owner and have auditlogs:read. |
feature_not_enabled / invalid_workspace / team_not_authorized |
Audit Logs API is only for Slack Enterprise. Install the app on the organization (not a workspace) and ensure the workspace is part of an Enterprise org. |
user_not_authorized |
The user who installed the app must be an Enterprise organization owner. |
invalid_cursor |
Cursor expired or corrupted. With on_cursor_error: reset, Helr clears the cursor and starts from the first page on the next poll. |
rate_limited |
Tier 3 = 50 calls/min org-wide. Increase interval_secs, lower max_pages, set page_delay_secs; Helr uses Retry-After when respect_headers: true. |
| No events | Check oldest / latest; data not available before March 2018. |
- API: Audit Logs API methods & actions —
GET https://api.slack.com/audit/v1/logs. - Auth: User token (
xoxp-) withauditlogs:read;Authorization: Bearer <token>; app installed by Enterprise org Owner. - Pagination: Cursor in
response_metadata.next_cursor; send as query paramcursor. Helr usesstrategy: cursorwithcursor_param: cursor,cursor_path: response_metadata.next_cursor. - Rate limit: 50 calls per minute (Tier 3), organization-wide.
- Env:
SLACK_AUDIT_TOKEN.