Skip to content
Back to skills

Slack Api

ASecurity

Integrates Slack API (Web API, Events API, Bolt Framework, Incoming Webhooks,

  • 4 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added June 12, 2026
developmentpythongoreactdebugginggitapisecuritydocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned June 12, 2026

npx -y skills add paulpas/agent-skill-router --skill slack-api --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Slack Api?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Slack Api
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/paulpas-slack-api/badge)](https://www.skillsdirectory.com/skills/paulpas-slack-api)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---




name: slack-api
description: Integrates Slack API (Web API, Events API, Bolt Framework, Incoming Webhooks,
  Block Kit) using the slack-sdk Python v3.x with proper event handling, Block Kit
  construction, and OAuth patterns.
license: MIT
compatibility: opencode
metadata:
  version: "1.0.0"
  domain: coding
  triggers: slack, slack api, slack bot, slack webhook, block kit, slack events, bolt
    python, send message to slack
  archetypes:
  - tactical
  - generation
  anti_triggers:
  - brainstorming
  - vague ideation
  - code golf
  - over-engineering
  response_profile:
    verbosity: low
    directive_strength: high
    abstraction_level: operational
  role: implementation
  scope: implementation
  output-format: code
  content-types:
  - code
  - guidance
  - do-dont
  - examples
  related-skills: coding-discord-api, coding-twilio-api, coding-sendgrid-api




---




# Slack API Integration (Bolt, Web API, Block Kit, Events)

Integrates the Slack platform — Web API, Events API, Bolt Framework, Incoming Webhooks, and Block Kit — using the `slack-sdk` Python SDK v3.x and `bolt-python`. When loaded, this skill makes the model implement Slack integrations with proper event handling, Block Kit message construction, OAuth flow, webhook verification, and slash command processing.

## TL;DR for Code Generation

- [ ] Initialize `WebClient` from `SLACK_BOT_TOKEN` environment variable — never hardcode tokens
- [ ] Use Block Kit (`blocks` parameter) for rich messages — never send plain text fallback without blocks
- [ ] For event-driven apps, use `Bolt` (`from slack_bolt import App`) with Socket Mode for development
- [ ] Verify Slack request signatures on every incoming webhook and command using `request_verification`
- [ ] Handle `SlackApiError` with status-specific logic — inspect `response["error"]` for the error code
- [ ] Use `views_open` / `views_update` for modal interactions; `ack()` every interaction within 3 seconds
- [ ] Use `chat_postMessage` with `blocks` for messages, `files_upload_v2` for file sharing

---

## When to Use

Use this skill when:

- Building Slack bots that respond to messages, slash commands, or events
- Sending rich (Block Kit) notifications to Slack channels from external applications via Incoming Webhooks
- Implementing OAuth-based Slack app installations with the OAuth flow
- Creating interactive components (modals, message actions, shortcuts) for Slack users
- Monitoring Slack events (messages, reactions, channel joins) via the Events API
- Automating channel management, message archiving, or user provisioning via the Web API

---

## When NOT to Use

Avoid this skill for:

- SMS or email delivery (use `coding-twilio-api` or `coding-sendgrid-api` instead)
- Voice or video calling — Slack handles that natively; use the Web API to create huddles instead
- Replacing a dedicated customer support platform — Slack is an internal communication tool
- Discord-specific integrations (use `coding-discord-api` for Discord bots)

---

## Core Workflow

1. **Initialize the Client** — Create a `WebClient(token=os.environ["SLACK_BOT_TOKEN"])` for API calls, or use Bolt `App(token=..., signing_secret=...)` for event-driven apps. **Checkpoint:** Verify the token by calling `client.auth_test()` on startup — this validates the token and returns the bot user ID and team info.

2. **Construct the Message** — Use Block Kit builders for rich messages. Always include a fallback `text` parameter for notifications. Structure blocks as an array of block dicts. **Checkpoint:** Preview Block Kit JSON using [Slacks Block Kit Builder](https://app.slack.com/block-kit-builder) before deploying.

3. **Send or Respond** — Use `client.chat_postMessage()` for proactive messages, `say()` in Bolt for command responses, or `response.write()` for webhook replies. For slash commands, always call `ack()` first within 3 seconds. **Checkpoint:** Check the response `ts` (timestamp) — its presence confirms successful delivery.

4. **Handle Events (Bolt Framework)** — Register event listeners with `@app.event("event_type")`. Use `@app.command()` for slash commands, `@app.action()` for interactive components, `@app.view()` for modal submissions. **Checkpoint:** Always call `ack()` as the first operation in every handler to prevent timeout errors.

5. **Error Handling and Retry** — Catch `SlackApiError` and inspect `response["error"]`. Common errors: `not_authorized`, `invalid_blocks`, `ratelimited`, `channel_not_found`. Implement retry with exponential backoff for rate limits. **Checkpoint:** Log the error payload with correlation IDs for debugging.

---

## Implementation Patterns

### Pattern 1: Block Kit Notification with Webhook

```python
import os
import json
import requests
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

# ❌ BAD — plain text only, no blocks, no error handling, hardcoded channel
client = WebClient(token="xoxb-xxx")
client.chat_postMessage(channel="#general", text="Deploy complete")

# ✅ GOOD — Block Kit message with fallback text, error handling, env-based config
import logging

logger = logging.getLogger(__name__)


def send_deploy_notification(service: str, version: str, environment: str, status: str) -> str | None:
    """Send a rich Block Kit deployment notification to Slack."""
    client = WebClient(token=os.environ["SLACK_BOT_TOKEN"])
    channel = os.environ.get("SLACK_DEPLOY_CHANNEL", "#deployments")

    color = "#36a64f" if status == "success" else "#ff0000"
    blocks = [
        {
            "type": "header",
            "text": {"type": "plain_text", "text": f"Deploy: {service} v{version} — {status}"},
        },
        {
            "type": "section",
            "fields": [
                {"type": "mrkdwn", "text": f"*Service:*\n{service}"},
                {"type": "mrkdwn", "text": f"*Version:*\n{version}"},
                {"type": "mrkdwn", "text": f"*Environment:*\n{environment}"},
                {"type": "mrkdwn", "text": f"*Status:*\n{status}"},
            ],
        },
        {
            "type": "context",
            "elements": [{"type": "mrkdwn", "text": f"Deploy completed at {__import__('datetime').datetime.now().isoformat()}"}],
        },
    ]

    try:
        response = client.chat_postMessage(
            channel=channel,
            text=f"Deploy: {service} v{version} — {status}",  # Fallback for notifications
            blocks=blocks,
            unfurl_links=False,
        )
        ts: str = response["ts"]
        logger.info("Notification sent", extra={"channel": channel, "ts": ts, "service": service})
        return ts
    except SlackApiError as exc:
        error_code = exc.response["error"]
        logger.error("Slack API error", extra={"error": error_code, "channel": channel})
        if error_code == "ratelimited":
            retry_after = exc.response.headers.get("Retry-After", "5")
            logger.warning("Rate limited", extra={"retry_after": retry_after})
        return None
```

### Pattern 2: Bolt Slash Command with Modal

```python
import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from slack_sdk.errors import SlackApiError

# ❌ BAD — plain text response, no ack() handling, no error checking
@app.command("/ticket")
def handle_ticket(command, respond):
    respond(f"Creating ticket: {command['text']}")

# ✅ GOOD — modal response with ack(), input validation, error handling
app = App(
    token=os.environ["SLACK_BOT_TOKEN"],
    signing_secret=os.environ["SLACK_SIGNING_SECRET"],
)


@app.command("/ticket")
def open_ticket_modal(command, ack, client, logger):
    """Open a modal to create a support ticket."""
    # Acknowledge the command immediately (must be within 3 seconds)
    ack()

    modal_view = {
        "type": "modal",
        "callback_id": "ticket_submit",
        "title": {"type": "plain_text", "text": "Create Ticket"},
        "submit": {"type": "plain_text", "text": "Submit"},
        "close": {"type": "plain_text", "text": "Cancel"},
        "blocks": [
            {
                "type": "input",
                "block_id": "title_block",
                "element": {
                    "type": "plain_text_input",
                    "action_id": "title_input",
                    "placeholder": {"type": "plain_text", "text": "Brief description"},
                },
                "label": {"type": "plain_text", "text": "Title"},
            },
            {
                "type": "input",
                "block_id": "priority_block",
                "element": {
                    "type": "static_select",
                    "action_id": "priority_select",
                    "placeholder": {"type": "plain_text", "text": "Select priority"},
                    "options": [
                        {"text": {"type": "plain_text", "text": "Low"}, "value": "low"},
                        {"text": {"type": "plain_text", "text": "Medium"}, "value": "medium"},
                        {"text": {"type": "plain_text", "text": "High"}, "value": "high"},
                        {"text": {"type": "plain_text", "text": "Critical"}, "value": "critical"},
                    ],
                },
                "label": {"type": "plain_text", "text": "Priority"},
            },
        ],
    }

    try:
        client.views_open(trigger_id=command["trigger_id"], view=modal_view)
    except SlackApiError as exc:
        logger.error(f"Failed to open modal: {exc.response['error']}")


@app.view("ticket_submit")
def handle_ticket_submission(ack, body, client, logger):
    """Handle modal submission."""
    ack()

    values = body["view"]["state"]["values"]
    title = values["title_block"]["title_input"]["value"]
    priority = values["priority_block"]["priority_select"]["selected_option"]["value"]

    # Store or process the ticket
    ticket_id = f"TICKET-{hash(title) % 10000:04d}"
    user_id = body["user"]["id"]

    try:
        client.chat_postMessage(
            channel=user_id,
            text=f"Ticket {ticket_id} created!",
            blocks=[
                {
                    "type": "section",
                    "text": {"type": "mrkdwn", "text": f"*Ticket {ticket_id} Created*\n*Title:* {title}\n*Priority:* {priority}"},
                }
            ],
        )
    except SlackApiError as exc:
        logger.error(f"Failed to confirm: {exc.response['error']}")


# Socket Mode for local development
if __name__ == "__main__":
    handler = SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"])
    handler.start()
```

### Pattern 3: Incoming Webhook (Simplest Integration)

```python
import os
import json
import requests

# ❌ BAD — no Block Kit, no error handling, assumes webhook URL is valid
requests.post(
    "https://hooks.slack.com/services/T00/B00/xxx",
    json={"text": "Hello"},
)

# ✅ GOOD — Block Kit, structured payload, error handling, timeout
def send_webhook_notification(webhook_url: str, message: str, title: str | None = None) -> bool:
    """Send a simple Block Kit notification via Slack Incoming Webhook."""
    blocks = [
        {
            "type": "section",
            "text": {"type": "mrkdwn", "text": message},
        }
    ]
    if title:
        blocks.insert(0, {
            "type": "header",
            "text": {"type": "plain_text", "text": title},
        })

    payload = {
        "text": message,  # Fallback for notifications
        "blocks": blocks,
        "unfurl_links": False,
    }

    try:
        resp = requests.post(
            webhook_url,
            json=payload,
            timeout=10,
            headers={"Content-Type": "application/json"},
        )
        resp.raise_for_status()
        return True
    except requests.exceptions.RequestException as exc:
        logging.getLogger(__name__).error("Webhook failed", extra={"error": str(exc)})
        return False
```

---

## Constraints

### MUST DO
- Store `SLACK_BOT_TOKEN`, `SLACK_SIGNING_SECRET`, and `SLACK_APP_TOKEN` in environment variables — never hardcode
- Always include a `text` fallback parameter alongside `blocks` for notification banners and accessibility
- Call `ack()` as the first operation in every Bolt handler (commands, actions, shortcuts, views) — you have 3 seconds
- Verify request signatures on every incoming Slack request using Bolt built-in verification or manual HMAC
- Use Socket Mode (`SocketModeHandler`) for local development — no public HTTP endpoint required
- Check `response["error"]` in `SlackApiError` for specific error codes — `ratelimited`, `invalid_blocks`, `not_authorized`
- Preview Block Kit JSON in the [Block Kit Builder](https://app.slack.com/block-kit-builder) before deploying to production

### MUST NOT DO
- Never reuse or expose OAuth access tokens across different workspaces — each Slack installation gets its own token
- Never skip `ack()` in interaction handlers — unacknowledged interactions will produce a timeout error to the user
- Hardcode channel IDs or names — load them from configuration or use `conversations_list` to resolve names
- Send sensitive data (passwords, API keys, PII) in Slack messages — Slack is not an encrypted platform
- Poll the Events API — use the Event Subscriptions or Socket Mode for real-time event delivery

---

## Output Template

When implementing Slack API code, the output must follow this structure:

1. **Client Initialization** — `WebClient` from `SLACK_BOT_TOKEN` env var; Bolt `App` from bot token + signing secret
2. **Message Construction** — Block Kit JSON array with at least one block type; `text` fallback always included
3. **Interaction Handling** — `ack()` called immediately; async processing after acknowledgment
4. **Error Handling** — Catches `SlackApiError` and inspects `response["error"]`; logs error with correlation context
5. **Security** — Request signature verification on all incoming requests (Bolt handles this automatically)

---

## Related Skills

| Skill | Purpose |
|---|---|
| `coding-discord-api` | Discord bot development — alternative to Slack for community-oriented messaging |
| `coding-twilio-api` | SMS and Voice communication — use alongside Slack for multi-channel notifications |
| `coding-sendgrid-api` | Transactional email — use for email fallback when Slack notifications need escalation |

---

## Live References

- [Slack Python SDK (slack-sdk v3.x) Documentation](https://docs.slack.dev/tools/python-slack-sdk)
- [Bolt for Python Documentation](https://tools.slack.dev/bolt-python/)
- [Slack Web API Methods](https://docs.slack.dev/methods)
- [Block Kit Reference](https://api.slack.com/block-kit)
- [Block Kit Builder (Interactive Preview)](https://app.slack.com/block-kit-builder)
- [Slack Event Types](https://api.slack.com/events)
- [Slack Incoming Webhooks](https://api.slack.com/messaging/webhooks)
- [PyPI: slack-sdk package](https://pypi.org/project/slack-sdk/)
- [GitHub: slackapi/python-slack-sdk](https://github.com/SlackAPI/python-slack-sdk)
- [GitHub: slackapi/bolt-python](https://github.com/slackapi/bolt-python)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.