# Slack

> The slack destination: tokens, channels and DMs.

A Slack channel or DM: the `slack` destination, from the `slack` package. Declare the package once in `dependencies.yml`; DRE installs it on demand:

dependencies.yml

```yaml
plugins:
  - slack
```

### Profile fields

Set in `profiles.yml`, under `destinations:`, in a target with `type: slack`.

Field

Default

Notes

`token` (required)

Bot token (xoxb-…) Secret: use `env_var()`.

`channel`

Default channel ID (C0123) or #name.

`api_url`

Slack’s API URL, for a proxy.

`connect_timeout`

`30s`

How long to wait for a connection (`30s`, `2m`, or seconds) A duration (`30s`, `2m`) or seconds.

`timeout`

`60s`

How long a read or write may make no progress before it fails. A duration (`30s`, `2m`) or seconds.

`retries`

`3`

How many times to try again after a temporary error (0: never)

### Options

Set in the report’s `output.destination` entry.

Option

Type

Default

Notes

`channel`

string

A channel ID (C0123) or #name.

`user`

string

A user ID (U0123), for a direct message.

`message`

string

The text posted with the files.

## Notes

Uploads the output to a Slack channel, or to one person’s DM, as a single post with a message. If a report produces several files, they all go in the same post.

The profile holds `token`, a bot token (`xoxb-...`), which is never logged. It can also hold a default `channel`, and `api_url` (default `https://slack.com/api`) for a proxy. Destination options:

Option

Meaning

`channel`

A channel ID (`C0123ABCD`) or `#name`. A name is looked up among the channels the bot can see.

`user`

A user ID (`U0123ABCD`). The file goes to the bot’s DM with that person.

`message`

The post’s text.

Give exactly one of `channel` or `user`. If you give neither, the profile’s `channel` is used.

```yaml
destination:
  - profile: team_slack
    channel: "#finance-reports"
    message: "Monthly report for {{ var('client') }} ({{ run.date.iso }})"
```

Slack app setup: create an app, add a bot user, install it to the workspace, and use its bot token. Bot scopes:

-   `files:write`: always needed.
-   `channels:read` and `groups:read`: needed to post to a `#name`.
-   `im:write` and `chat:write`: needed for `user`.

A DM also needs the app’s Messages tab turned on (App Home > Show Tabs > Messages Tab). With it off, Slack accepts a file for the DM and then silently drops it, so before uploading the plugin checks that the DM accepts messages. The check posts nothing, and if the tab is off the delivery fails and says what to change.

The bot must be a member of the channel. Invite it with `/invite @your-bot`.

**Messages** (slack 1.1.0): for a [`message`](https://getdre.com/docs/plugins/#the-message-format) output, the post is the message itself: the title in bold, then the text in Slack’s formatting, sent with `chat.postMessage` (scope `chat:write`) to the same `channel` or `user`. `message:` isn’t used. Slack’s recommended maximum is 4,000 characters: a longer message is posted cut short, with a note and the full message attached as its `.md` file (scope `files:write`). `attach: [<output>]` on the entry uploads those outputs’ files in the same post, with the message as its text.

```yaml
output:
  - name: workbook
    format: xlsx
    queries: [detail]
  - name: headline
    format: message
    queries: [headline]
    text: "Revenue yesterday: **{{ results.headline.value | currency('EUR') }}**"
    destination:
      - {profile: team_slack, channel: "#finance", attach: [workbook]}
```

If Slack rate-limits a call or answers 503, the plugin tries again after Slack’s `Retry-After` (at most 60 seconds), up to `retries` times (see [Tries again](https://getdre.com/docs/plugins/#tries-again)). Errors such as a rejected token, a missing scope, or the bot not being in the channel are reported with what to fix. The delivered location is the uploaded files’ permalinks.

## Try the headline project

Use the complete [Slack headline example](https://github.com/get-dre/dre/blob/v0.5.1/examples/slack-headline/) for a query, conditional message and dev target that posts nothing. The minimum Slack profile is:

```yaml
destinations:
  team_slack:
    targets:
      dev: {deliver: false}
      prod:
        type: slack
        token: "{{ env_var('DRE_SECRET_SLACK_BOT_TOKEN') }}"
        channel: C0123ABCD
```

Run a preview before selecting prod. A channel ID avoids the channel-name lookup; using a `#name` also requires read scopes. `invalid-destination-option` can mean both `channel` and `user` were supplied. `delivery-failed` with a missing scope needs the bot reauthorized; an absent channel membership needs the bot invited. Increasing retries cannot fix either. See [message configuration](https://getdre.com/docs/messages/), [destination keys](https://getdre.com/docs/reference-report/#outputdestination), [error codes](https://getdre.com/docs/reference-error-codes/) and [message](https://getdre.com/docs/glossary/#message).

[Edit page](https://github.com/get-dre/dre/edit/master/docs/plugin-slack.md)

[Previous  
Email](https://getdre.com/docs/plugin-email/)[Next  
Microsoft Teams](https://getdre.com/docs/plugin-teams/)
