> ## Documentation Index
> Fetch the complete documentation index at: https://inkbox.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Slack operations

> Edit messages, manage reactions and pins, join or leave channels, and inspect durable operation outcomes

All paths on this page are relative to `https://inkbox.ai/api/v1/slack`. These operations use the selected workspace connection and its actual Slack permissions. They do not bypass message authorship, channel membership, workspace policies, or rate limits.

## Idempotent operations

Every write below requires `Idempotency-Key`. Use `1`–`128` characters from letters, digits, `.`, `_`, `:`, or `-`.

* Save one key before starting each logical operation.
* Repeating that key with the same operation, conversation, and input returns its existing result without repeating the write.
* Reusing it with different input on the same connection returns `409`.
* A new key requests a new operation. It can duplicate an earlier uncertain write.

These operations and [message sends](/docs/api/slack/messages#send-message) use separate idempotency namespaces. Reusing a key across those two families does not deduplicate them. Within this operation family, the key is shared across operation types on the same connection.

The operation response is distinct from the [send-action response](/docs/api/slack/messages#send-message):

```json theme={null}
{
  "id": "55555555-5555-4555-8555-555555555555",
  "connection_id": "22222222-2222-4222-8222-222222222222",
  "operation": "reaction_add",
  "status": "succeeded",
  "conversation_id": "C0123456789",
  "message_ts": "1789552800.000100",
  "file_id": null,
  "error_code": null,
  "retry_after": null,
  "processing_status": null,
  "agent_status": null
}
```

| Status | Meaning | Next step |
| :- | :- | :- |
| `in_progress` | No outcome has been recorded yet. | Read the same operation later. |
| `succeeded` | Slack accepted the requested change or already has the requested reaction/pin state. | Use the returned coordinates; this is not a read receipt. |
| `failed` | The outcome is known to have failed. | Inspect `error_code` and `retry_after` before deciding on a new operation. |
| `unknown` | Slack may have applied some or all of the change. | Reconcile current Slack state. Do not blindly repeat with a new key. |

A stale `in_progress` operation becomes `unknown` after roughly two minutes, without repeating the write.

HTTP `200` does not mean the operation succeeded. `unknown` is not an automatically reconciling state. `retry_after`, when present, is a delay in seconds; waiting does not cause the original operation to run again.

There are no operation-outcome webhooks for this family. Inspect the response and poll [Get operation](#get-operation) while it is `in_progress`. The `slack.message_sent`, `slack.message_send_failed`, and `slack.message_send_unknown` events report message sends, not these operations.

## Get operation

```text theme={null}
GET /connections/{connection_id}/operations/{operation_id}
```

Both IDs are UUIDs. Returns `200` with the operation object above. Recorded outcomes remain inspectable after disconnect if you still have access to the owning identity.

`operation` is one of `reaction_add`, `reaction_remove`, `pin_add`, `pin_remove`, `message_update`, `message_delete`, `file_upload`, `conversation_join`, `conversation_leave`, or `processing_status`. Optional coordinates and status fields are null when unavailable.

## Edit or delete a message

```text theme={null}
PATCH /connections/{connection_id}/conversations/{conversation_id}/messages/{message_ts}
DELETE /connections/{connection_id}/conversations/{conversation_id}/messages/{message_ts}
```

PATCH body:

```json theme={null}
{
  "text": "The project notes have been updated."
}
```

`text` is required, `1`–`12,000` characters. DELETE has no body. Both return `200` with an operation object. Slack restricts which messages the bot can edit or delete; these endpoints do not grant authority over other users' messages.

## Read reactions

```text theme={null}
GET /connections/{connection_id}/conversations/{conversation_id}/messages/{message_ts}/reactions
```

Returns `200` with `conversation_id`, `message_ts`, and `reactions`. A reaction can include `name`, `count`, and `users`. The response includes at most 100 reactions and 1000 user IDs per reaction; do not interpret the user list as a complete receipt list.

## Add or remove a reaction

```text theme={null}
POST /connections/{connection_id}/conversations/{conversation_id}/messages/{message_ts}/reactions
DELETE /connections/{connection_id}/conversations/{conversation_id}/messages/{message_ts}/reactions/{name}
```

POST body:

```json theme={null}
{
  "name": "white_check_mark"
}
```

`name` is `1`–`100` characters using letters, digits, `_`, `+`, `:`, or `-`. Use the reaction name, not an emoji image. DELETE has no body. Both return an operation object. Adding an already-present bot reaction or removing an absent one succeeds without inventing another reaction.

## Read pins

```text theme={null}
GET /connections/{connection_id}/conversations/{conversation_id}/pins
```

A pin marks an existing conversation item for easy reference. It is not a file copy or a separate archive.

Returns `200` with `items` and `truncated`. Items can include `type`, `channel`, `created`, `created_by`, and supported `message` or `file` metadata. At most 100 items are returned. `truncated: true` means additional items were omitted; this endpoint has no pagination cursor.

## Pin or unpin a message

```text theme={null}
POST /connections/{connection_id}/conversations/{conversation_id}/pins
DELETE /connections/{connection_id}/conversations/{conversation_id}/pins/{message_ts}
```

POST body:

```json theme={null}
{
  "message_ts": "1789552800.000100"
}
```

DELETE has no body. Both return an operation object. Already-pinned and already-unpinned outcomes are treated as success when Slack reports the matching state.

## Join or leave a conversation

```text theme={null}
POST /connections/{connection_id}/conversations/{conversation_id}/join
POST /connections/{connection_id}/conversations/{conversation_id}/leave
```

Neither request has a body. Both require an idempotency key and return an operation object. Join is subject to Slack's supported channel types and workspace restrictions; it cannot force entry into a private channel. Leaving changes the bot's membership and can remove access to live and retained conversation content.

## Set native processing status

```text theme={null}
POST /connections/{connection_id}/conversations/{conversation_id}/processing-status
```

```json theme={null}
{
  "thread_ts": "1789552800.000100",
  "status": "processing"
}
```

Both fields are required. `status` accepts `active`, `processing`, `suspended`, or `closed`. This requests Slack's native agent-session status for a thread. It is not ordinary message text, a universal typing indicator, or a signal that executes or cancels runtime work.

The operation returns Slack's accepted `processing_status` and `agent_status` when available. A granted scope alone does not establish that native agent-session features are available to the app and workspace. Inspect the operation result and [capabilities](/docs/api/slack/users#inspect-capabilities); unsupported requests fail rather than silently posting a substitute message.

## Upload a file

Use the [file-upload endpoint](/docs/api/slack/files#upload-a-file). It uses the same operation statuses and idempotency rules.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.