Platforms

Slack

Install the app in a Slack workspace, publish channel messages and thread replies with files, set the message identity, and handle DMs and mentions in the inbox.

Slack publishing runs through a hosted app. A workspace member installs it with OAuth, picks a channel, and that channel becomes an account you post to with POST /v1/posts using the platform id slack. You do not create a Slack app, host a bot or handle tokens. The same account receives DMs and mentions in the Inbox and can start a DM with any member of the workspace.

#What you can do

Feature Supported Where
Channel messages in Slack mrkdwn Yes Post types
Thread replies Yes, with threadTs Post types
Files Up to 10 per post Media requirements
Link and media unfurling On or off per post Platform fields
Custom name and avatar Per post or per account Message identity
Scheduling Yes Scheduling
Edit and delete published messages Yes Editing
DMs and mentions in the inbox Yes Inbox
Start a DM with a member Yes Inbox
Analytics No Slack has no message analytics API

#Connect

Slack installs into a workspace, not a channel, so the flow ends with a channel choice. One connected account is one channel. To post in several channels, connect each as its own account.

#Start OAuth

Call List Slack channels with only profileId (and your redirect_url). With no pendingDataToken or accountId, it returns authUrl and state. Send the user to authUrl to approve the app.

Terminal
curl "https://api.pozy.ai/v1/connect/slack?profileId=66a1f0c2a4b9d3e8f1a2b3c4&redirect_url=https://app.example.com/connected" \
  -H "Authorization: Bearer $POZY_API_KEY"

#Pick the channel

Pozy shows a channel picker by default. In headless mode (headless=true), the redirect back to you carries a pendingDataToken. Call the same endpoint with it to list the workspace's channels yourself: public and private, archived ones left out, up to 2,000. isMember says whether the app is already in a channel.

#Save it

Call Connect a Slack channel with the channelId (or several in channelIds) and the pendingDataToken:

Terminal
curl -X POST https://api.pozy.ai/v1/connect/slack \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "profileId": "66a1f0c2a4b9d3e8f1a2b3c4", "pendingDataToken": "'"$PENDING_DATA_TOKEN"'", "channelId": "C07ABCDEF12" }'

The response carries the new accountId. The channel now shows up in List accounts for that profile.

To add another channel from the same workspace, skip OAuth: call List Slack channels with an existing Slack accountId, then save with accountId instead of pendingDataToken.

Things that trip people up:

  • Private channels. The app cannot join a private channel on its own. Someone in the channel must invite it first (type /invite in the channel and choose the app). Until then the channel does not appear in the list. Public channels are joined automatically.
  • Admin approval. Some workspaces need an admin to approve new apps, so Slack may show a "request approval" screen.
  • Unlisted app warning. Slack may say the app "has not been reviewed by Slack" during install. That is expected for apps that are not in the Slack Marketplace.

#Post types

A post with content becomes a message in the account's channel. There is no channelId field on a Slack post; sending one returns 400. To post somewhere else, connect that channel and use its accountId.

curl -X POST https://api.pozy.ai/v1/posts \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "*Deploy finished* for `api` v2.4.1. Release notes: <https://example.com/notes|read here>",
    "platforms": [{
      "platform": "slack",
      "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
      "platformSpecificData": { "unfurlLinks": false, "username": "Release Bot" }
    }],
    "publishNow": true
  }'

To reply inside a thread, pass the parent message's timestamp as threadTs, for example "threadTs": "1503435956.000247". Scheduling happens in Pozy; Slack's own scheduler is not used.

#Platform fields

Field Type Notes
threadTs string Post as a reply in this thread
unfurlLinks boolean, default true Expand links into preview cards
unfurlMedia boolean, default true Expand media links into inline previews
username string Display name for this message
iconUrl URL Avatar for this message

#Message identity

username and iconUrl change the name and avatar on one message. Set a default for every post from a channel with Update Slack account settings; the per-post fields still win. The override is cosmetic: Slack still shows an APP badge, and the app's own name stays in the sidebar.

#Media requirements

Up to 10 files per post, uploaded through Slack's file API with the text as the caption. Pozy does not compress or convert files for Slack, and there is no format allowlist: the bytes behind your URL reach Slack as they are.

Whether an upload succeeds depends on the workspace's upload policy and, on Slack's free plan, its storage cap. A file Slack refuses fails the post with Slack's message. Files are named from the media item: type: "video" uploads as .mp4, type: "gif" as .gif, anything else from filename. Media hosts files up to 5 GB.

#Limits

Limit Value
Message content 40,000 characters. Slack truncates beyond this without an error
Editable content 4,000 characters. Longer posts cannot be edited
Files 10 per post
Channels per account 1

#Analytics

Slack has no public message analytics API, so Slack has no analytics in Pozy.

#Inbox

Slack events arrive in real time. The inbox takes in:

  • DMs to the app
  • Channel messages that @-mention the app
  • Replies in threads the app is part of, including under posts you published
  • Emoji reactions, as reaction.received

Ordinary channel conversation is not stored. The inbox is not a mirror of the workspace.

Each incoming message fires message.received, with metadata.threadTs when it is a thread reply and metadata.mentionsBot: true when it mentions the app. That pair is enough for the usual agent rule: always answer DMs, answer in a channel only when mentioned, reply in the thread.

Reply with Send message; replyTo threads the reply. Reactions use Add reaction with a named Slack emoji such as :thumbsup:.

To start a DM, find the member with List Slack workspace members and pass their member id as participantId to Create conversation:

curl "https://api.pozy.ai/v1/accounts/66b2e19d8c3f5a7e9d0b1c2d/slack-members?query=maria" \
  -H "Authorization: Bearer $POZY_API_KEY"

curl -X POST https://api.pozy.ai/v1/inbox/conversations \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "accountId": "66b2e19d8c3f5a7e9d0b1c2d", "participantId": "U04ABCDE123", "message": "Hi Maria, your report is ready." }'

Bots, deactivated members and Slackbot are left out of the member lookup.

Constraints to plan for:

  • No history backfill. The inbox starts when the channel connects.
  • Messages from other bots appear for context but never trigger automations or webhooks.
  • Attachments appear as links that open in Slack.
  • People who DM the app become contacts; people talking in a channel do not. Built-in automations (workflows, sequences) run on DMs only. For channels, react to message.received with your own logic.

#Errors you may see

Error Cause Fix
400 with channelId on a post Slack posts have no channelId field Connect the channel and use its accountId
Private channel missing from the list The app has not been invited Invite the app in that channel, then list again
missing_scope on inbound messages The workspace was connected before the inbox existed Reconnect the workspace once so it grants the new scopes
Edit rejected The post is over 4,000 characters Publish a new message
Upload refused The workspace's upload policy or storage cap Ask the workspace admin, or send a link instead
400 on a reaction The emoji has no Slack name Use a named emoji such as :thumbsup:

Errors covers the error format.

#Endpoints

Endpoint What it does
GET /v1/connect/slack List Slack channels for the channel picker
POST /v1/connect/slack Connect a Slack channel
GET /v1/accounts/{accountId}/slack-settings Get Slack account settings
PATCH /v1/accounts/{accountId}/slack-settings Update Slack account settings
GET /v1/accounts/{accountId}/slack-members List Slack workspace members
POST /v1/posts Create post
POST /v1/posts/{postId}/edit Edit published post
GET /v1/inbox/conversations List conversations
POST /v1/inbox/conversations Create conversation
POST /v1/inbox/conversations/{conversationId}/messages Send message
POST /v1/inbox/conversations/{conversationId}/messages/{messageId}/reactions Add reaction

#Webhook events

Event When it fires
post.published Post published.
post.failed Post failed.
message.received Message received.
conversation.started Conversation started.
message.sent Message sent.
reaction.received Reaction received.