Skip to main content

Overview

The Channels API lets you integrate Shannon with external messaging platforms. Create channels to connect Slack workspaces or LINE accounts, and Shannon will automatically process incoming messages through its agent system.

Features

  • Slack integration with event subscription and bot messaging
  • LINE integration with webhook-based messaging
  • HMAC signature verification for secure inbound webhooks
  • Agent routing via agent_name config to direct messages to specific agents
  • Per-user isolation with unique constraint on type + name per user
  • Credential security — credentials are never exposed in API responses

Create Channel

Create a new messaging channel.
curl -X POST http://localhost:8080/api/v1/channels \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "type": "slack",
    "name": "My Slack Channel",
    "credentials": {
      "signing_secret": "your-slack-signing-secret",
      "bot_token": "xoxb-your-bot-token",
      "app_id": "A0123456789"
    },
    "config": {
      "agent_name": "research-agent"
    }
  }'

Request Body

FieldTypeRequiredDescription
typestringYesChannel type: "slack" or "line"
namestringYesChannel display name
credentialsobjectYesPlatform-specific credentials (see below)
configobjectNoOptional configuration (e.g., agent_name)

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "type": "slack",
  "name": "My Slack Channel",
  "config": {
    "agent_name": "research-agent"
  },
  "enabled": true,
  "created_at": "2026-03-10T10:00:00Z",
  "updated_at": "2026-03-10T10:00:00Z"
}
The credentials field is never returned in API responses for security. Store your credentials securely on your side.

List Channels

List all channels for the authenticated user.
curl http://localhost:8080/api/v1/channels \
  -H "Authorization: Bearer <token>"

Response

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "user_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "type": "slack",
    "name": "My Slack Channel",
    "config": {
      "agent_name": "research-agent"
    },
    "enabled": true,
    "created_at": "2026-03-10T10:00:00Z",
    "updated_at": "2026-03-10T10:00:00Z"
  }
]

Get Channel

Get details of a specific channel.
curl http://localhost:8080/api/v1/channels/{id} \
  -H "Authorization: Bearer <token>"

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "type": "slack",
  "name": "My Slack Channel",
  "config": {
    "agent_name": "research-agent"
  },
  "enabled": true,
  "created_at": "2026-03-10T10:00:00Z",
  "updated_at": "2026-03-10T10:00:00Z"
}

Update Channel

Update an existing channel. All fields are optional — only provided fields will be updated.
curl -X PUT http://localhost:8080/api/v1/channels/{id} \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "Renamed Slack Channel",
    "config": {
      "agent_name": "financial-agent"
    },
    "enabled": false
  }'

Request Body

FieldTypeRequiredDescription
namestringNoNew channel name
credentialsobjectNoNew platform credentials
configobjectNoNew configuration
enabledbooleanNoEnable or disable the channel

Response

Returns the updated channel object (same schema as Get Channel).

Delete Channel

Delete a channel permanently.
curl -X DELETE http://localhost:8080/api/v1/channels/{id} \
  -H "Authorization: Bearer <token>"

Response

Response
{
  "message": "Channel deleted"
}
(HTTP 200 OK with JSON body)

Inbound Webhook

Receive messages from external platforms. This endpoint is called by Slack or LINE when a user sends a message.
POST /api/v1/channels/{channel_id}/webhook
This endpoint requires no authentication. Instead, each platform uses its own HMAC signature verification to ensure requests are genuine.

Response

{
  "status": "dispatched"
}
The webhook validates the inbound request, extracts the message, and dispatches it to Shannon’s agent system asynchronously. The response is returned immediately.

Credential Formats

Slack Credentials

{
  "signing_secret": "your-slack-signing-secret",
  "bot_token": "xoxb-your-bot-token",
  "app_id": "A0123456789"
}
FieldDescription
signing_secretFound in your Slack app’s Basic Information page
bot_tokenBot user OAuth token (starts with xoxb-)
app_idYour Slack app ID

LINE Credentials

{
  "channel_secret": "your-line-channel-secret",
  "channel_access_token": "your-line-channel-access-token"
}
FieldDescription
channel_secretFound in your LINE Developer Console channel settings
channel_access_tokenLong-lived channel access token from LINE Developer Console

Webhook Behavior

Slack

  • Signature verification: Validates X-Slack-Request-Timestamp and X-Slack-Signature headers using HMAC-SHA256 with the channel’s signing_secret
  • Clock skew: Requests older than 5 minutes are rejected
  • URL verification: Automatically responds to Slack’s url_verification challenge during app setup
  • Bot filtering: Messages from bots are ignored to prevent loops
  • Supported events: message and app_mention

LINE

  • Signature verification: Validates X-Line-Signature header using HMAC-SHA256 (base64-encoded) with the channel’s channel_secret
  • Reply behavior: Sends a “Thinking…” reply immediately using the reply token
  • Message handling: Processes the first text message from the event payload

Agent Routing

Set the agent_name field in the channel’s config to route incoming messages to a specific agent:
{
  "config": {
    "agent_name": "research-agent"
  }
}
If agent_name is not set, messages are handled by Shannon’s default agent routing.

Channel Response Object

FieldTypeDescription
idstring (UUID)Unique channel identifier
user_idstring (UUID)Owner user ID (optional)
typestringChannel type: "slack" or "line"
namestringChannel display name
configobjectChannel configuration
enabledbooleanWhether the channel is active
created_atstring (ISO 8601)Creation timestamp
updated_atstring (ISO 8601)Last update timestamp

Error Responses

StatusErrorDescription
400Invalid requestMissing required fields or invalid channel type
401UnauthorizedMissing or invalid authentication
403ForbiddenCannot access another user’s channel
404Channel not foundInvalid channel ID
409ConflictDuplicate channel (same user + type + name)
500Internal server errorServer-side failure
All errors follow the standard format:
{
  "error": "error message here"
}

Next Steps