Files
magnus919_agent-skills/slack/references/01-web-api-operations.md
T
Magnus HedemarkGitHubfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
3256a87bcb feat(skill): add collaboration & business-app tool layer (Slack, Notion, email, CRM, payments) (#269)
Adds five top-level operational tool skills, one per named tool:

- slack: messages, channels, threads, search, files, and webhook signature
  verification (HMAC-SHA256) via a bounded, stdlib-only slack-cli.
- notion: pages, database queries, search, and guarded page updates via
  notion-cli.
- email: transactional email via Twilio SendGrid (send, deliverability
  bounces/spam reports, Signed Event Webhook verification with a
  self-contained ECDSA P-256 verifier) via email-cli.
- crm: HubSpot CRM records, contact search, and deal pipeline views with
  guarded stage updates via crm-cli.
- stripe: read-only-first balance, payment, and subscription queries with
  a guarded period-end subscription cancellation via stripe-cli.

Each skill ships an executable script (--json output, --limit bounded reads,
--dry-run/--yes mutation gate), a human README with the five required
sections, a schema-v1 evals/evals.json with six output-quality cases, a dated
source index + operations reference, and a deterministic unittest suite run
by check-artifacts. All five are indexed in the top-level README and the
generated catalogs were regenerated. Eval coverage rises from 78/139 to
83/144.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-08-03 20:19:26 -04:00

3.7 KiB

Slack Web API Operations

Last Updated: 2026-08-03

Operational detail for the Slack Web API surface the skill owns: methods, scopes, pagination, error handling, and webhook signature verification. The bundled slack-cli implements this reference; use this document when a call behaves unexpectedly or you need the exact scope/method contract.

Method surface

All calls POST form-encoded fields to https://slack.com/api/<method> with the token as Authorization: Bearer and read the JSON response; ok: false plus error is the error shape.

Operation Method Required scopes Notes
List channels conversations.list channels:read, groups:read types selects public/private/IM/MPIM; exclude_archived filters
Read history conversations.history channels:history, groups:history Newest first; returns messages + response_metadata.next_cursor
Thread replies conversations.replies channels:history, groups:history Parent message is the first result; ts is the parent timestamp
Post message chat.postMessage chat:write Guarded mutation; thread_ts replies in a thread
Search messages search.messages search:read Supports in:, from:, before:/after:, quoted phrases
List files files.list files:read Optionally filter by channel or user

Pagination and bounded reads

  • Every listing method returns at most limit results per page (max 100 for most) plus response_metadata.next_cursor.
  • Bounded-read rule: request only what the task needs; slack-cli --limit caps at the request level. If a task needs more, page explicitly with --cursor, and stop when the question is answered.
  • Search returns total (total matches) alongside the bounded matches array — report the total, return only the cap.

Error handling

  • ok: false with an error string: invalid_auth (token bad/expired), missing_scope (token lacks the scope — the exact scope is in the response needed/provided fields), channel_not_found, not_in_channel, ratelimited (429 — back off and retry with Retry-After).
  • is_ratelimited: true in a 200 response: the method was throttled; slow down.
  • Never retry a failed send blindly: chat.postMessage can be retried with the same text (it is not idempotent in the strict sense), so confirm state via conversations.history before re-sending.

Webhook signature verification

Slack signs every outbound HTTP request to your endpoints (events, slash commands, interactivity). Algorithm per Verifying requests from Slack:

  1. Take the exact raw request body bytes — any re-encoding (JSON pretty-print, charset change) breaks the signature.
  2. Reject if |now - X-Slack-Request-Timestamp| > 300 seconds (replay window).
  3. Compute v0=HMAC_SHA256(signing_secret, "v0:" + timestamp + ":" + body).
  4. Compare with X-Slack-Signature using a constant-time comparison (hmac.compare_digest).

The app signing secret lives in the Slack app settings (Basic Information → App Credentials → Signing Secret) and is distinct from the bot token. Never log the secret, the signature comparison, or full webhook bodies; slack-cli webhook verify reports a boolean result.

Token and scope hygiene

  • Bot tokens (xoxb-) act as the app; user tokens (xoxp-) act as a user. Scope needs differ: reading public channels needs channels:history; reading private channels needs groups:history on a bot that has been added to the channel.
  • Store tokens in the environment (SLACK_TOKEN), never in code, chat, or commit messages. Revoke and rotate a token that leaks — it is a credential, not a config value.