---
url: https://salimhamed.github.io/jigs/api/steps/slack.md
---
# steps/slack

Low-level Slack operations for factory-owned steps. Workflow code calls their
`#jigs/steps` wrappers; waiting for a thread reply is `waitForSlackReply`
from `#jigs/routines`. `callSlack` reaches any other Web API method from a
factory's own `"use step"` function.

See [Slack](https://salimhamed.github.io/jigs/guide/slack).

## Errors

### SlackApiError {#slackapierror}

Slack answered a Web API call with `ok: false`. Check `code` to handle one
answer, such as `already_reacted`.

#### Extends

* [`ProviderApiError`](../steps.md#providerapierror)

#### Constructors

##### Constructor

```ts
new SlackApiError(
   method, 
   code, 
   needed?, 
   answer?): SlackApiError;
```

###### Parameters

| Parameter | Type |
| :------ | :------ |
| `method` | `string` |
| `code` | `string` |
| `needed?` | `string` |
| `answer?` | { `body`: `string`; `status`: `number`; } |
| `answer.body?` | `string` |
| `answer.status?` | `number` |

###### Returns

[`SlackApiError`](#slackapierror)

###### Overrides

[`ProviderApiError`](../steps.md#providerapierror).[`constructor`](../steps.md#constructor)

#### Properties

| Property | Type | Description |
| :------ | :------ | :------ |
|  `body` | `string` | - |
|  `code` | `string` | Slack's `error` string, such as `invalid_auth` or `already_reacted`. |
|  `hint?` | `string` | What the reader can do about it. Quote each command to run in backticks, as in ``stop the service first: `pnpm exec jigs service stop` ``: the CLI prints it on its own line. |
|  `provider` | `Provider` | - |
|  `status` | `number` | - |

## Create and update

### postSlackMessage() {#postslackmessage}

```ts
function postSlackMessage(__namedParameters): Promise<string>;
```

Post plain `mrkdwn` text to a channel, or as a reply in the thread under
`threadTs`, as the bot of the Slack installation `installationName` names.
Returns the new message's ts.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `__namedParameters` | { `channel`: `string`; `installationName`: `string`; `text`: `string`; `threadTs?`: `string`; } |
| `__namedParameters.channel` | `string` |
| `__namedParameters.installationName` | `string` |
| `__namedParameters.text` | `string` |
| `__namedParameters.threadTs?` | `string` |

#### Returns

`Promise`<`string`>

## Read

### fetchSlackMessage() {#fetchslackmessage}

```ts
function fetchSlackMessage(__namedParameters): Promise<SlackMessageSnapshot>;
```

Read a Slack message, its permalink and its thread's replies, with each
author's name and email, through the Slack installation `installationName` names.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `__namedParameters` | { `channel`: `string`; `installationName`: `string`; `ts`: `string`; } |
| `__namedParameters.channel` | `string` |
| `__namedParameters.installationName` | `string` |
| `__namedParameters.ts` | `string` |

#### Returns

`Promise`<[`SlackMessageSnapshot`](../jigs.md#slackmessagesnapshot)>

#### Remarks

`ts` must be a top-level message. A reply's ts fails the step without a
retry, naming the top-level message's ts.

## Any Web API method

### SlackParams {#slackparams}

```ts
type SlackParams = Record<string, JsonValue | undefined>;
```

Web API arguments. A value that is not a string is sent JSON-encoded, the way
Slack takes `blocks`.

***

### callSlack() {#callslack}

```ts
function callSlack<T>(
   method, 
   params, 
options): Promise<T>;
```

Call any Slack Web API method as the factory's bot in the Slack installation
`installationName` names, and return Slack's response body. Wrap it in your own `"use step"` function.

#### Type Parameters

| Type Parameter | Default type |
| :------ | :------ |
| `T` | `Record`<`string`, `unknown`> |

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `method` | `string` |
| `params` | [`SlackParams`](#slackparams) |
| `options` | { `installationName`: `string`; } |
| `options.installationName` | `string` |

#### Returns

`Promise`<`T`>

#### Remarks

Arguments that are not strings, such as `blocks`, are sent JSON-encoded, and
`undefined` ones are left out. When Slack answers `ok: false`, it throws a
[SlackApiError](#slackapierror) with Slack's error as its `code`. Rate-limited calls are
retried.

A step can run more than once, so a call that is not safe to repeat has to
accept what a repeat gets back, such as `already_reacted` from
`reactions.add`, or `message_not_found` once the message is deleted. Add
any scope the method needs that jigs does not already use to the app's bot
scopes in the hub; without it Slack answers `missing_scope`.

#### Example

```ts
// workflows/deploys/steps.ts
import { callSlack, SlackApiError } from "@jigs-ai/jigs/steps/slack";

export async function react(channel: string, timestamp: string, name: string) {
  "use step";
  try {
    await callSlack(
      "reactions.add",
      { channel, timestamp, name },
      { installationName: "slack-acme" },
    );
  } catch (error) {
    const tolerated = ["already_reacted", "message_not_found"];
    if (!(error instanceof SlackApiError && tolerated.includes(error.code))) throw error;
  }
}
```
