Skip to main content
An installed app writes to a circle in one of two ways. Pick by what you’re posting: Answers to slash commands and message actions are conversational writes too; Reintersect places them for you. Both kinds of write follow your app’s reach: public circles, private circles that invited your app, and never circles connected to another workspace or a Slack channel.

App stream events

src/deploys.ts
Inside handlers, use the context’s reintersect, or reintersect.forInstall(installId) in a route. Your app gets one stream in each circle it sends events to, named after the app and shown with its icon. Nobody creates it by hand: it appears with your app’s first event in that circle. Sending needs the replies:write scope. Send exactly one of content and markdown. Events can’t upload files or mention people: the SDK rejects Image, File and Mention content before sending, with ReintersectSdkInvalidInputError. Link to the resource instead. The answer is { conversationId, url, created }. created is false when the event became a reply in an existing conversation. A circle’s streams take 60 events a minute from your app. sendEvent makes one request and never retries. Pass an idempotencyKey if your own code retries. Its errors: A circle admin can revoke your app’s stream. A stream is also revoked when your app sends an event to a circle it can no longer reach: that event answers ReintersectAppCircleNotFoundError. A revoked stream stays revoked, and later events to it answer ReintersectAppStreamRevokedError; stop sending them. See the endpoint reference: POST /v0/streams/events.

Streams without an install

A circle admin can also create a webhook URL for an outside tool, such as a deploy script, in the circle’s settings. That URL is its own credential: post to it with createReintersectStream({ url }) from @reintersect/sdk, without an app or an install. Use it for one circle and one tool; use streams.sendEvent when your app serves many workspaces and circles.

Replies and blocks

replies.create and blocks.insert take one target:
Replies answer with circleId and a conversationId that is null while the message isn’t filed in a conversation. Blocks carry circleId too. Events about a chat message, such as reply.created, app.mentioned and block.created, carry circleId with a null conversation until it’s filed; subscribe to message.filed to hear when a message is filed or moved. Replies need replies:write and blocks need blocks:write. See Create a reply and Insert a block.