# Slack Destination Config Reference

<p><a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/slack/" >Slack</a> is a business messaging destination. RudderStack turns <code>identify</code> and <code>track</code> events into messages and posts them to Slack channels through incoming webhooks, from its servers.</p>
<p>In a Slack destination spec:</p>
<ul>
<li><code>type: slack</code></li>
<li><code>definition_version: 1</code></li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="sample-configuration">Sample configuration</h2><div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: destination
metadata:
  name: slack-prod
spec:
  id: slack-prod
  display_name: Slack Production
  type: slack
  definition_version: 1
  enabled: true
  config:
    webhook_url: &#34;{{ .SLACK_WEBHOOK_URL }}&#34;

    incoming_webhooks_type: modern
    event_channel_settings:
      - name: Order Completed
        webhook: &#34;{{ .SLACK_ORDERS_WEBHOOK_URL }}&#34;
        regex: false
      - name: &#34;^Trial (Started|Ended)$&#34;
        webhook: &#34;{{ .SLACK_GROWTH_WEBHOOK_URL }}&#34;
        regex: true

    identify_template: &#34;Identified {{name}}{{newline}}Plan: {{plan}}&#34;
    event_template_settings:
      - name: Order Completed
        template: &#34;{{name}} completed an order worth {{revenue}}&#34;
        regex: false

    whitelisted_trait_settings:
      - email
      - plan
    deny_list_of_events:
      - Heartbeat

    connection_mode:
      web: cloud
      cloud: cloud
    consent_management:
      web:
        - provider: oneTrust
          consents:
            - analytics</code></pre></div>
</div>
<p>The above example sets <code>incoming_webhooks_type</code> to <code>modern</code>, so each channel entry carries its own <code>webhook</code> instead of a <code>channel</code> name — see <a href="#channel-routing" >Channel routing</a>. The webhook URLs are secrets, written as <code>{{ .VAR }}</code> references — see <a href="#secrets" >Secrets</a>.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="config-keys">Config keys</h2><p><code>config</code> accepts only the keys listed below. The <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/destination-types/#config-key-rules" >shared config key rules</a> cover unknown keys, defaults, and immutability.</p>

<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text">Slack accepts only <code>identify</code> and <code>track</code> events. RudderStack doesn&rsquo;t deliver any other event type to it.</div>
  </div>
</blockquote>

</html>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="connection">Connection</h3><div class="rs-ckeys">
<div class="rs-ckey" id="webhook_url">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">webhook_url</p>RequiredSecret</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Slack incoming webhook URL. RudderStack posts every <code>identify</code> message here, and every <code>track</code> message that <a href="#channel-routing" >channel routing</a> doesn&rsquo;t send elsewhere.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>At most 100 characters, and must not contain line breaks.</li>
<li>Any value containing <code>.ngrok.io</code> is rejected.</li>
<li>Templates aren&rsquo;t accepted in place of a literal; a template is measured as text against the same limits.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <p>Supply it as a <code>{{ .VAR }}</code> reference rather than a literal — see <a href="#secrets" >Secrets</a>.</p>
<p>See <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/slack/#how-do-i-obtain-the-incoming-webhook-url" >How do I obtain the incoming webhook URL?</a>.</p>

</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="channel-routing">Channel routing</h3><p><code>event_channel_settings</code> sends <code>track</code> events to channels other than the one <code>webhook_url</code> posts to, and <code>incoming_webhooks_type</code> decides how. <code>identify</code> messages always go to <code>webhook_url</code>.</p>
<div class="rs-ckeys">
<div class="rs-ckey" id="incoming_webhooks_type">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">incoming_webhooks_type</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>legacy</code>
  </p>
<p class="rs-ckey__field">
  Description:
  How a matching <code>event_channel_settings</code> entry reaches its channel.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li><code>legacy</code> — RudderStack posts through <code>webhook_url</code> and names the entry&rsquo;s <code>channel</code> in the message. The dashboard marks this method as due for deprecation.</li>
<li><code>modern</code> — RudderStack posts to the entry&rsquo;s own <code>webhook</code>, a URL from a Slack app with incoming webhooks enabled for that channel.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  See <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/slack/#event-channel-settings" >Event channel settings</a>.
</div>

</div>

<div class="rs-ckey" id="event_channel_settings">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">event_channel_settings</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>array of objects</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Routes <code>track</code> events to channels by event name. RudderStack uses the first entry that matches, and posts an event that matches none through <code>webhook_url</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li><code>name</code> — event name to match. At most 100 characters, and must not contain line breaks. It also must not contain a parenthesized group that holds <code>*</code>, <code>+</code>, <code>{</code>, or <code>|</code> and is followed by <code>*</code>, <code>+</code>, <code>?</code>, or <code>{</code> — such as <code>(a|b)+</code> — even when <code>regex</code> is <code>false</code>.</li>
<li><code>regex</code> — boolean. <code>true</code> treats <code>name</code> as a regular expression, which matches anywhere in the event name — anchor it with <code>^</code> and <code>$</code> to match the whole name. Omit it, or set <code>false</code>, for an exact match.</li>
<li><code>channel</code> — channel to post to when <code>incoming_webhooks_type</code> is <code>legacy</code>: a channel name such as <code>#orders</code>, or <code>@user</code> for a direct message. At most 100 characters, and must not contain line breaks. Quote it, since an unquoted <code>#</code> starts a YAML comment.</li>
<li><code>webhook</code> — incoming webhook URL to post to when <code>incoming_webhooks_type</code> is <code>modern</code>. Same limits as <code>webhook_url</code>, including the <code>.ngrok.io</code> ban. <strong>Secret</strong> — see <a href="#secrets" >Secrets</a>.</li>
<li>Templates aren&rsquo;t accepted in place of a literal in these fields; a template is measured as text against the same limits.</li>
<li>Rudder CLI doesn&rsquo;t check that an entry carries the field its webhook type uses. RudderStack skips an entry without it, as though its <code>name</code> never matched.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">incoming_webhooks_type: legacy
event_channel_settings:
  - name: Order Completed
    channel: &#34;#orders&#34;
  - name: &#34;^Trial (Started|Ended)$&#34;
    channel: &#34;#growth&#34;
    regex: true</code></pre></div>
</div>
<p>See <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/slack/#event-channel-settings" >Event channel settings</a>.</p>
</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="message-templates">Message templates</h3><p>Both template keys take <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/slack/#handlebar-expressions" >Handlebars expressions</a>. Write each template in quotes: an unquoted value starting with <code>{</code> isn&rsquo;t read as a string in YAML. Rudder CLI substitutes only <code>{{ .VAR }}</code> references, which start with a dot, so <code>{{name}}</code> reaches Slack as written.</p>
<p>A template can use:</p>
<table>
  <thead>
      <tr>
          <th>Expression</th>
          <th>Value</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>{{name}}</code></td>
          <td>The user&rsquo;s name — <code>traits.name</code>, or first and last name — falling back to their username or email, then to <code>User &lt;userId&gt;</code>, or <code>Anonymous user &lt;anonymousId&gt;</code>.</td>
      </tr>
      <tr>
          <td><code>{{event}}</code></td>
          <td>The event name. <code>track</code> only.</td>
      </tr>
      <tr>
          <td><code>{{property_name}}</code>, <code>{{properties.property_name}}</code></td>
          <td>An event property, where <code>property_name</code> is its name — such as <code>{{revenue}}</code>. <code>track</code> only.</td>
      </tr>
      <tr>
          <td><code>{{trait_name}}</code></td>
          <td>A trait, where <code>trait_name</code> is its name — such as <code>{{plan}}</code>. <code>identify</code> only. <code>{{traitsList.trait_name}}</code> works in both.</td>
      </tr>
      <tr>
          <td><code>{{traits}}</code></td>
          <td>The user&rsquo;s traits as <code>key: value</code> text, limited to <code>whitelisted_trait_settings</code> when it&rsquo;s set.</td>
      </tr>
      <tr>
          <td><code>{{propertiesList}}</code></td>
          <td>Every event property as <code>key: value</code> text. <code>track</code> only.</td>
      </tr>
      <tr>
          <td><code>{{newline}}</code></td>
          <td>A line break. Templates can&rsquo;t contain literal line breaks, so this is the only way to write a multi-line message.</td>
      </tr>
  </tbody>
</table>
<div class="rs-ckeys">
<div class="rs-ckey" id="identify_template">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">identify_template</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Template for the message an <code>identify</code> event posts. When omitted, RudderStack posts <code>Identified {{name}}</code> followed by the user&rsquo;s traits as <code>key: value</code> pairs, limited to <code>whitelisted_trait_settings</code> when it&rsquo;s set.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>At most 1000 characters, and must not contain line breaks.</li>
<li><code>{{ path || fallback }}</code> templates aren&rsquo;t accepted in place of a literal; the value is measured as text against the same limits.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">identify_template: &#34;Identified {{name}}{{newline}}Plan: {{plan}}&#34;</code></pre></div>
</div>
<p>See <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/slack/#identify-template-settings" >Identify template settings</a>.</p>
</div>

</div>

<div class="rs-ckey" id="event_template_settings">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">event_template_settings</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>array of objects</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Templates for the messages <code>track</code> events post, by event name. RudderStack uses the first entry that matches. An event that matches none posts <code>{{name}} did {{event}}</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li><code>name</code>, <code>regex</code> — match events on the same terms as <a href="#event_channel_settings" ><code>event_channel_settings</code></a>.</li>
<li><code>template</code> — the message template. At most 1000 characters, and must not contain line breaks.</li>
<li><code>{{ path || fallback }}</code> templates aren&rsquo;t accepted in place of a literal in these fields; the value is measured as text against the same limits.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">event_template_settings:
  - name: Order Completed
    template: &#34;{{name}} completed an order worth {{revenue}}&#34;</code></pre></div>
</div>
<p>See <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/slack/#event-template-settings" >Event template settings</a>.</p>
</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="filtering">Filtering</h3><div class="rs-ckeys">
<div class="rs-ckey" id="whitelisted_trait_settings">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">whitelisted_trait_settings</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>array of strings</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Traits RudderStack lists in the default <code>identify</code> message and in <code>{{traits}}</code>. When empty, every trait is listed. A template can still name any trait directly.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Each trait name is at most 100 characters, and must not contain line breaks.</li>
<li>Templates aren&rsquo;t accepted in place of a literal; a template is measured as text against the same limits.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">whitelisted_trait_settings:
  - email
  - plan</code></pre></div>
</div>

</div>

</div>

<div class="rs-ckey" id="deny_list_of_events">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">deny_list_of_events</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>array of strings</code>
  </p>
<p class="rs-ckey__field">
  Description:
  <code>track</code> event names RudderStack doesn&rsquo;t post to Slack. A match is exact and case-sensitive, and RudderStack fails a matching event with a configuration error instead of posting it.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Each name is at most 100 characters, and must not contain line breaks.</li>
<li>Templates aren&rsquo;t accepted in place of a literal; a template is measured as text against the same limits.</li>
</ul>

</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="per-source-keys">Per-source keys</h3><p>Both keys are objects keyed by the local source type — the tokens listed under <a href="#source-types" >Source types</a>. A key naming a source type this destination doesn&rsquo;t support fails validation.</p>
<div class="rs-ckeys">
<div class="rs-ckey" id="connection_mode">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">connection_mode</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>object</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Maps each source type you connect to the mode its events reach Slack in, using the modes in <a href="#source-types" >Source types</a>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>An entry is required for each source type you connect — see <a href="#connect-a-source" >Connect a source</a>.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">connection_mode:
  web: cloud
  cloud: cloud</code></pre></div>
</div>

</div>

</div>

<div class="rs-ckey" id="consent_management">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">consent_management</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>object</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Consent provider configuration per source type. The entry shape, accepted providers, and the rules on <code>resolution_strategy</code> and <code>consents</code> are shared across all destination types — see <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/destination-types/#consent-management" >Consent management</a>.
</p>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="source-types">Source types</h2><p>Slack accepts events from these source types in the mentioned connection modes:</p>
<table>
  <thead>
      <tr>
          <th>Source type</th>
          <th>Connection mode</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>android</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>android_kotlin</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>ios</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>ios_swift</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>web</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>unity</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>react_native</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>flutter</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>cordova</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>cloud</code></td>
          <td><code>cloud</code></td>
      </tr>
      <tr>
          <td><code>warehouse</code></td>
          <td><code>cloud</code></td>
      </tr>
  </tbody>
</table>
<p>Every source type is <code>cloud</code> only — RudderStack posts to Slack from its servers, never in device mode.</p>

<p><code>warehouse</code> is the token a <a href="https://www.rudderstack.com/docs/sources/reverse-etl/" >Reverse ETL source</a> resolves to. Rudder CLI manages the destination’s <code>warehouse</code> entry — if the destination is connected to a Reverse ETL source, set <code>connection_mode.warehouse: cloud</code> in its spec, or <code>apply</code> removes it.</p>
<p>Rudder CLI can also declare the Reverse ETL connection itself, for the types listed under <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/yaml-retl-connections/#supported-destinations" >Supported destinations</a> — see <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/retl-connections/" >Manage Reverse ETL Connections using Rudder CLI</a>.</p>

<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text">The dashboard additionally offers Slack to AMP and Shopify sources. Rudder CLI doesn&rsquo;t manage those connections, so <code>amp</code> and <code>shopify</code> are invalid here.</div>
  </div>
</blockquote>

</html>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="connect-a-source">Connect a source</h2><p>An event stream connection to this destination is checked against two rules at <code>validate</code> time.</p>
<p><strong>The source&rsquo;s type must be supported.</strong> A source&rsquo;s type resolves to one of the tokens above before the check — a JavaScript source resolves to <code>web</code>, and webhook and server-side SDK sources resolve to <code>cloud</code>. Every type an event stream source can resolve to is supported here, so this check always passes.</p>
<p><strong>The destination config must carry a <code>connection_mode</code> entry for that source type.</strong> This lives on the destination spec, not on the <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/yaml-connections/" >connection spec</a>. Without it:</p>
<div class="rs-code">
  <div class="rs-code__head"><button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-text" data-lang="text">destination &#39;slack-prod&#39; config has no &#39;connection_mode&#39; entry for source type &#39;web&#39;</code></pre></div>
</div>
<p>Slack needs no additional config keys to connect a source of any type.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="secrets">Secrets</h2><p><code>webhook_url</code> and each <code>event_channel_settings</code> entry&rsquo;s <code>webhook</code> are the secret keys. Write each one you use as a <code>{{ .VAR }}</code> reference and supply the value at apply time:</p>
<div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">config:
  webhook_url: &#34;{{ .SLACK_WEBHOOK_URL }}&#34;
  event_channel_settings:
    - name: Order Completed
      webhook: &#34;{{ .SLACK_ORDERS_WEBHOOK_URL }}&#34;</code></pre></div>
</div>
<div class="rs-code">
  <div class="rs-code__head">bash<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">export RUDDER_SLACK_WEBHOOK_URL=&#34;...&#34;
export RUDDER_SLACK_ORDERS_WEBHOOK_URL=&#34;...&#34;
rudder-cli apply

# or
rudder-cli apply --var-file secrets.vars.yaml</code></pre></div>
</div>
<p>Note that:</p>
<ul>
<li><code>rudder-cli import</code> writes only the secrets the API returns, as <code>{{ .VAR }}</code> references, and leaves the others out. Add any secret key it leaves out, then supply the variables before you apply — see <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/destination-types/#secrets" >Secrets</a>.</li>
<li>Each substituted value is validated like a literal, so a webhook URL still has to meet the <code>webhook_url</code> limits.</li>
</ul>
<p>See <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/variable-substitution/" >How to Use Variable Substitution in Rudder CLI</a>.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="changes-by-release">Changes by release</h2>
<p>No changes since this type became available.</p>
<p>For changes across every destination type, see <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/destination-types/changes/" >Destination Type Changes by Release</a>.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="see-more">See more</h2><ul>
<li><a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/slack/" >Slack Destination</a> for incoming webhook setup, Handlebars expressions, and message examples</li>
<li><a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/destination-types/" >Destination Type Reference for Rudder CLI</a> for the rules shared across destination types</li>
<li><a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/yaml-destinations/" >Destination YAML Reference</a> for the spec envelope</li>
</ul>

