This automations page is moving! We've been working hard at building out our tools documentation at tools.slack.dev — the new home of our Deno Slack SDK and Slack CLI docs! You can start using the new docs today, but we'll keep the content on both sites up to date during the transition.

Event triggers

Developing automations requires a paid plan. Don't have one? Join the Developer Program and provision a sandbox with access to all Slack features for free.

Invoke a workflow when a specific event happens in Slack

Event triggers are a type of automatic trigger, as they don't require manual activation. Instead, they're automatically invoked when a certain event happens.

Supported events

Your app needs to have the proper scopes to use event triggers. Include these scopes within your app's manifest. Your app also needs to be a member of any channel where you want to listen for events.

Supported event How to reference Description Required scopes
app_mentioned
TriggerEventTypes.AppMentioned
Subscribe to only the message events that mention your app or bot.
channel_archived
TriggerEventTypes.ChannelArchived
A channel was archived.
channel_created
TriggerEventTypes.ChannelCreated
A channel was created.
channel_deleted
TriggerEventTypes.ChannelDeleted
A channel was deleted.
channel_renamed
TriggerEventTypes.ChannelRenamed
A channel was renamed.
channel_shared
TriggerEventTypes.ChannelShared
A channel has been shared with an external workspace.
channel_unarchived
TriggerEventTypes.ChannelUnarchived
A channel was unarchived.
channel_unshared
TriggerEventTypes.ChannelUnshared
A channel has been unshared with an external workspace.
dnd_updated
TriggerEventTypes.DndUpdated
Do not Disturb settings changed for a member.
emoji_changed
TriggerEventTypes.EmojiChanged
A custom emoji has been added or changed.
message_metadata_posted
TriggerEventTypes.MessageMetadataPosted
Message metadata was posted.
message_posted
TriggerEventTypes.MessagePosted
A message was sent to a channel. Note: a filter is required to listen for this event.
pin_added
TriggerEventTypes.PinAdded
A pin was added to a channel.
pin_removed
TriggerEventTypes.PinRemoved
A pin was removed from a channel.
reaction_added
TriggerEventTypes.ReactionAdded
A member has added an emoji reaction.
reaction_removed
TriggerEventTypes.ReactionRemoved
A member removed an emoji reaction.
shared_channel_invite_accepted
TriggerEventTypes.SharedChannelInviteAccepted
A shared channel invite was accepted.
shared_channel_invite_approved
TriggerEventTypes.SharedChannelInviteApproved
A shared channel invite was approved.
shared_channel_invite_declined
TriggerEventTypes.SharedChannelInviteDeclined
A shared channel invite was declined.
shared_channel_invite_received
TriggerEventTypes.SharedChannelInviteReceived
A shared channel invite was sent to a Slack user.
shared_channel_invite_requested
TriggerEventTypes.SharedChannelInviteRequested
A shared channel invite was requested to be sent.
user_joined_channel
TriggerEventTypes.UserJoinedChannel
A user joined a public or private channel.
user_joined_team
TriggerEventTypes.UserJoinedTeam
A new member has joined.
user_left_channel
TriggerEventTypes.UserLeftChannel
A user left a public or private channel.

Events can activate multiple triggers

When an event happens, all event triggers listening for that event will be invoked at roughly the same time. If you want to control which workflow runs first, you have two options:

  • Combine the functions of both workflows into a single workflow, invoked with a single event trigger.
  • Have the second workflow be invoked by the first workflow, instead of the original event trigger.

Avoid infinite loops

Your app can respond to events and be the cause of events. This can create situations where your app gets stuck in a loop.

For example, if your app listens for all message_posted events in a channel and then posts its own message in response, it'll keep posting messages forever! That's why the message_posted event requires a filter.

Carefully construct a filter to prevent boundless behavior. If your app does get stuck in an infinite loop, you can delete the trigger and the behavior will cease.

Create an event trigger

Triggers can be added to workflows in two ways:

  • You can add triggers with the CLI. These static triggers are created only once. You create them with the Slack CLI, attach them to your app's workflow, and that's that. The trigger is defined within a trigger file.
  • You can add triggers at runtime. These dynamic triggers are created at any step of a workflow so they can incorporate data acquired from other workflow steps. The trigger is defined within a function file.

Slack CLI built-in documentation
Use slack trigger --help to easily access information on the trigger command's flags and subcommands.

The triggers you create when running locally (with the slack run command) will not work when you deploy your app in production (with the slack deploy command). You'll need to create any triggers again with the CLI.

Create the trigger file

To create an event trigger with the CLI, you'll need to create a trigger file. The trigger file contains the payload you used to define your trigger.

Create a TypeScript trigger file within your app's folder with the following form:

import { Trigger } from "deno-slack-api/types.ts";
import { TriggerEventTypes, TriggerTypes, TriggerContextData } from "deno-slack-api/mod.ts";

const trigger: Trigger<typeof ExampleWorkflow.definition> = {
  // your TypeScript payload
};

export default trigger;

Your TypeScript payload consists of the parameters needed for your own use case. The following is a trigger file with a payload creating an event trigger that listens for a reaction_added event in a specific channel:

import { Trigger } from "deno-slack-api/types.ts";
import { TriggerEventTypes, TriggerTypes, TriggerContextData } from "deno-slack-api/mod.ts";

const trigger: Trigger<typeof ExampleWorkflow.definition> = {
  type: TriggerTypes.Event,
  name: "Reactji response",
  description: "responds to a specific reactji",
  workflow: "#/workflows/myWorkflow",
  event: {
    event_type: TriggerEventTypes.ReactionAdded,
    channel_ids: ["C123ABC456"],
    filter: {
      version: 1,
      root: {
        statement: "{{data.reaction}} == sunglasses"
      }
    }
  },
  inputs: {
    stringtoSend: {
      value: "how cool is that",
    },
    channel: {
      value: "C123ABC456",
    },
  },
};

export default trigger;

Use the trigger create command

Once you have created a trigger file, use the following command to create the event trigger:

slack trigger create --trigger-def "path/to/trigger.ts"

If you have not used the slack triggers create command to create a trigger prior to running the slack run command, you will receive a prompt in the Slack CLI to do so.

Your app needs to have the triggers:write scope to use a trigger at runtime. Include the scope within your app's manifest.

The logic of a runtime trigger lies within a function's TypeScript code. Within your functions folder, you'll have the functions that are the steps making up your workflow. Within this folder is where you can create a trigger within the relevant <function>.ts file.

When you create a runtime trigger, you can leverage inputs acquired from functions within the workflow. Provide the workflow definition to get additional typing for the workflow and inputs fields.

Create an event trigger at runtime using the client.workflows.triggers.create method within the relevant function file.

const triggerResponse = await client.workflows.triggers.create<typeof ExampleWorkflow.definition>({
  // your TypeScript payload
});

Your TypeScript payload consists of the parameters needed for your own use case. Below is a function file with an example TypeScript payload for an event trigger. This specific TypeScript payload is for creating an event trigger that listens for a reaction_added event in a specific channel:

// functions/example_function.ts
import { DefineFunction, Schema, SlackFunction } from "deno-slack-sdk/mod.ts";
import { ExampleWorkflow } from "../workflows/example_workflow.ts";
import { TriggerEventTypes, TriggerTypes } from "deno-slack-api/mod.ts";

export const ExampleFunctionDefinition = DefineFunction({
  callback_id: "example_function_def",
  title: "Example function",
  source_file: "functions/example_function.ts",
});

export default SlackFunction(
  ExampleFunctionDefinition,
  ({ inputs, client }) => {

  const triggerResponse = await client.workflows.triggers.create<typeof ExampleWorkflow.definition>({
    type: TriggerTypes.Event,
    name: "Reactji response",
    description: "responds to a specific reactji",
    workflow: `#/workflows/${ExampleWorkflow.definition.callback_id}`,
    event: {
      event_type: TriggerEventTypes.ReactionAdded,
      channel_ids: ["C123ABC456"],
      filter: {
        version: 1,
        root: {
          statement: "{{data.reaction}} == sunglasses"
        }
      }
    },
    inputs: {
      stringtoSend: {
        value: "how cool is that",
      },
      channel: {
        value: "C123ABC456",
      },
    }
  });

  // ...

Event trigger parameters

Field Description Required?
name
The name of the trigger.
Yes
type
The type of trigger: TriggerTypes.Event.
Yes
workflow
Path to workflow that the trigger initiates.
Yes
description
The description of the trigger.
No
event
No
inputs
The inputs provided to the workflow. Can use with the event response object.
No

Event triggers are not interactive. Use a link trigger to take advantage of interactivity.

The Event object

Field Description Required?
event_type
The type of event; use one of the properties of TriggerEventTypes.
Yes
team_ids
An array of event-related team ID strings.
Required for Enterprise Grid
all_resources
Trip the event trigger in all channels your app is present in. Defaults to false. Mutually exclusive with channel_ids. See below for more details.
Dependent on the event
channel_ids
An array of channel IDs where the event trigger will trip. Mutually exclusive with all_resources. See below for more details.
Dependent on the event
filter
See trigger filters for more details.
No

Scoping channel-based event triggers

When writing a channel-based event trigger, you can pass the channel_ids field with a list of specific channels for the trigger to trip in. Example:

event: {
  event_type: TriggerEventTypes.ReactionAdded,
  channel_ids: ["C123ABC456", "C01234567", "C09876543"],
}

Alternatively, you can set all_resources to true The channel_ids field will no longer be required, and the event will now trigger in all channels in the workspace the app is a part of. Example:

event: {
  event_type: TriggerEventTypes.ReactionAdded,
  all_resources: true,
}

Setting all_resources to true could cause additional charges, as the event will trip in all channels the app is a member of in the workspace and may therefore lead to many workflow executions in workspaces with a large number of channels.

Channel-based event triggers

The following channel-based event triggers require either the channel_ids or all_resources event object to be set:

The event response object

An event's response object will contain additional information about that specific event instance.

Property Description
data
Contains additional information dependent on event type. See below.
enterprise_id
A unique identifier for the enterprise where this event occurred.
event_id
A unique identifier for this specific event, globally unique across all workspaces.
event_timestamp
A Unix timestamp in seconds indicating when this event was dispatched.
team_id
A unique identifier for the workspace/team where this event occurred.
type
An identifier showing the event type

The data property

Each type of event has unique sub-properties within the data property. You can pass these values on to your workflows. See the example below.

Event types
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "app_id": "A1234ABC",
    "channel_id": "C0123ABC",
    "channel_name": "cool-channel",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/app_mentioned",
    "message_ts": "164432432542.2353",
    "text": "<@U0LAN0Z89> is it everything a river should be?",
    "user_id:": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_name": "cool-channel",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/channel_archived",
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_name": "fun",
    "channel_type": "public",
    "created": 1360782804,
    "creator_id": "U0123ABC",
    "event_type": "slack#/events/channel_created",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_name": "project_planning",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/channel_deleted",
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_name": "project_planning",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/channel_renamed",
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_name": "cool-channel",
    "channel_type": "public/private/im/mpim",
    "connected_team_id": "E0123ABC",
    "event_type": "slack#/events/channel_shared",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_name": "cool-channel",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/channel_unarchived",
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_name": "cool-channel",
    "channel_type": "public/private/im/mpim",
    "disconnected_team_id": "E0123ABC",
    "event_type": "slack#/events/channel_unshared",
    "is_ext_shared": false,
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "dnd_status": {
      "dnd_enabled": true,
      "next_dnd_start_ts": "1734937260.000001",
      "next_dnd_end_ts": "1735365540.000001",
    },
    "event_type": "slack#/events/user_updated_dnd",
    "user_id": "U0123ABC",
  }
}
Emoji added
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "event_type": "slack#/events/emoji_changed",
    "name": "picard_facepalm",
    "subtype": "add",
    "value": "https://my.slack.com/emoji/picard_facepalm/abc123.gif"
  }
}
Emoji removed
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "event_type": "slack#/events/emoji_changed",
    "names": ["picard_facepalm"],
    "subtype": "remove",
  }
}
Emoji renamed
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "event_type": "slack#/events/emoji_changed",
    "new_name": "captain_picard_facepalm",
    "old_name": "picard_facepalm",
    "subtype": "rename",
    "value": "https://my.slack.com/emoji/picard_facepalm/abc123.gif"
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "app_id": "A0123ABC",
    "channel_id": "C0123ABC",
    "event_type": "slack#/events/message_metadata_posted",
    "message_ts": "1630708981.000001",
    "metadata": {
      "event_type": "incident_created",
      "event_payload": {
        "incident": {
          "id": 123,
          "summary": "Someone tripped over",
          "sev": 1
        }
      }
    },
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/message_posted",
    "message_ts": "1355517523.000005",
    "text": "Hello world",
    "thread_ts": "1355517523.000006", // Nullable
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_type": "public/private/im/mpim",
    "channel_name": "project_planning",
    "event_type": "slack#/events/pin_added",
    "message_ts": "1360782804.083113",
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_name": "project_planning",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/pin_removed",
    "message_ts": "1360782804.083113",
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "event_type": "slack#/events/reaction_added",
    "message_context": {
      "message_ts": "1535430114.000100",
      "channel_id": "C0123ABC",
    },
    "message_ts": "1535430114.000100",
    "message_link": "https:\/\/example.slack.com\/archives\/C0123ABC\/p1535430114000100",
    "reaction": "joy",
    "user_id": "U0123ABC",
    "item_user": "U0123ABC",
    "parent_message_link": "https:\/\/example.slack.com\/archives\/C0123ABC\/p1535430114000100",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 12345,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "event_type": "slack#/events/reaction_removed",
    "message_ts": "1535430114.000100",
    "reaction": "thumbsup",
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.088700,
  "type": "event",
  "data": {
    "accepting_user": {
      "display_name": "John Doe",
      "id": "U123",
      "is_bot": false,
      "name": "John Doe",
      "real_name": "John Doe",
      "team_id": "T123",
      "timezone": "America/Los_Angeles",
    },
    "approval_required": false,
    "channel_id": "C12345678",
    "channel_name": "test-slack-connect",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/shared_channel_invite_accepted",
    "invite": {
      "date_created": 1626876000,
      "date_invalid": 1628085600,
      "id": "I028YDERZSQ",
      "inviting_team": {
        "date_created": 1480946400,
        "domain": "corgis",
        "icon": {...},
        "id": "T12345678",
        "is_verified": false,
        "name": "Corgis",
      },
      "inviting_user": {
        "display_name": "John Doe",
        "id": "U123",
        "is_bot": false,
        "name": "John Doe",
        "real_name": "John Doe",
        "team_id": "T123",
        "timezone": "America/Los_Angeles",
      },
      "recipient_email": "golden@doodle.com",
      "recipient_user_id": "U87654321",
    },
    "teams_in_channel": [
      {
        "date_created": 1626789600,
        "domain": "corgis",
        "icon": {...},
        "id": "T12345678",
        "is_verified": false,
        "name": "Corgis",
      }
    ],
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.0887,
  "type": "event",
  "data": {
    "approving_team_id": "T87654321",
    "approving_user": {
      "display_name": "John Doe",
      "id": "U123",
      "is_bot": false,
      "team_id": "T123",
      "name": "John Doe",
      "real_name": "John Doe",
      "team_id": "T12345",
      "timezone": "America/Los_Angeles",
    },
    "channel_id": "C12345678",
    "channel_name": "test-slack-connect",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/shared_channel_invite_approved",
    "invite": {
      "date_created": 1626876000,
      "date_invalid": 1628085600,
      "id": "I0123ABC",
      "inviting_team": {
        "date_created": 1480946400,
        "domain": "corgis",
        "icon": {...},
        "id": "T12345678",
        "is_verified": false,
        "name": "Corgis",
      },
      "inviting_user": {
        "display_name": "John Doe",
        "id": "U123",
        "is_bot": false,
        "name": "John Doe",
        "real_name": "John Doe",
        "team_id": "T123",
        "timezone": "America/Los_Angeles",
      },
      "recipient_email": "golden@doodle.com",
      "recipient_user_id": "U87654321"
    },
    "teams_in_channel": [
      {
        "date_created": 1626789600,
        "domain": "corgis",
        "icon": {...},
        "id": "T12345678",
        "is_verified": false,
        "name": "Corgis",
      }
    ],
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.0887,
  "type": "event",
  "data": {
    "channel_id": "C12345678",
    "channel_type": "public/private/im/mpim",
    "channel_name": "test-slack-connect",
    "declining_team_id": "T87654321",
    "declining_user": {
      "display_name": "John Doe",
      "id": "U123",
      "is_bot": false,
      "name": "John Doe",
      "real_name": "John Doe",
      "team_id": "T123",
      "timezone": "America/Los_Angeles",
    },
    "event_type": "slack#/events/shared_channel_invite_declined",
    "invite": {
      "date_created": 1626876000,
      "date_invalid": 1628085600,
      "id": "I0123ABC",
      "inviting_team": {
        "date_created": 1480946400,
        "domain": "corgis",
        "icon": {...},
        "id": "T12345678",
        "is_verified": false,
        "name": "Corgis",
      },
      "inviting_user": {
        "display_name": "John Doe",
        "id": "U123",
        "is_bot": false,
        "name": "John Doe",
        "real_name": "John Doe",
        "team_id": "T123",
        "timezone": "America/Los_Angeles",
      },
      "recipient_email": "golden@doodle.com",
      "recipient_user_id": "U3472391",
    },
    "teams_in_channel": [
      {
        "date_created": 1626789600,
        "domain": "corgis",
        "icon": {...},
        "id": "T12345678",
        "is_verified": false,
        "name": "Corgis",
      }
    ],
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1643810217.0887,
  "type": "event",
  "data": {
    "channel_id": "C12345678",
    "channel_name": "test-slack-connect",
    "channel_type": "public/private/im/mpim",
    "event_type": "slack#/events/shared_channel_invite_received",
    "invite": {
      "date_created": 1626876000,
      "date_invalid": 1628085600,
      "id": "I0123ABC",
      "inviting_team": {
        "date_created": 1480946400,
        "domain": "corgis",
        "icon": {...},
        "id": "T12345678",
        "is_verified": false,
        "name": "Corgis",
      },
      "inviting_user": {
        "display_name": "John Doe",
        "id": "U123",
        "is_bot": false,
        "name": "John Doe",
        "real_name": "John Doe",
        "team_id": "T123",
        "timezone": "America/Los_Angeles",
      },
      "recipient_email": "golden@doodle.com",
      "recipient_user_id": "U87654321"
    },

  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_type" : "public/private/im/mpim",
    "event_type": "slack#/events/user_joined_channel",
    "user_id": "U0123ABC",
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "event_type": "slack#/events/user_joined_team",
    "user": {
      "display_name": "John Doe",
      "id": "U123",
      "is_bot": false,
      "name": "John Doe",
      "real_name": "John Doe",
      "team_id": "T123",
      "timezone": "America/Los_Angeles",
    }
  }
}
{
  "team_id": "T0123ABC",
  "enterprise_id": "E0123ABC",
  "event_id": "Ev0123ABC",
  "event_timestamp": 1630623713,
  "type": "event",
  "data": {
    "channel_id": "C0123ABC",
    "channel_type" : "public/private/im/mpim",
    "event_type": "slack#/events/user_left_channel",
    "user_id": "W0123ABC",
  }
}

*When developing with these event types on Enterprise Grid, you must include the team_ids field when creating workspace-based event triggers.

The data returned in the event response object can be passed along to workflows. In this example, we take the user_id, channel_id, and message_ts from the reaction_added event's response object and pass them along to the joy_workflow in the inputs field, referencing them by their respective enums.

{
  type: TriggerTypes.Event,
  name: "Joy reactji event trigger",
  description: "Joy reactji trigger",
  workflow: "#/workflows/joy_workflow",
  inputs: {
    user: {
      value: TriggerContextData.Event.ReactionAdded.user_id, // Pulled from event response body and passed into the workflow
    },
    channel: {
      value: TriggerContextData.Event.ReactionAdded.channel_id, // Pulled from event response body and passed into the workflow
    },
    message_ts: {
      value: TriggerContextData.Event.ReactionAdded.message_ts // Pulled from event response body and passed into the workflow
    }
  },
  event: {
    event_type: TriggerEventTypes.ReactionAdded,
    channel_ids: ["C123ABC456"]
  }
}

Event trigger filters

Trigger filters allow you to define a set of conditions for a trigger which must be true in order for the trigger to activate.

Filters can also prevent your app from getting stuck in an infinite loop of responses triggered by responding to events it created.

Trigger filters are implemented by inserting a filter payload within your trigger object. The payload takes the form of an object containing blocks of conditional logic. The logical condition within each block can be one of two types:

  • Conditional expressions (e.g. x < y)
  • Boolean logic (e.g. x AND y)

Conditional expressions

Conditional expression blocks need a single statement key with a string containing the comparison block. Values from the inputs payload can be referenced within the comparison block.

Below is an example payload of a reaction_added event trigger that only invokes a workflow if the reaction was the :eyes: reaction.

{
  type: TriggerTypes.Event,
  name: "Reactji response",
  description: "responds to a specific reactji",
  workflow: "#/workflows/myWorkflow",
  event: {
    event_type: TriggerEventTypes.ReactionAdded,
    channel_ids: ["C123ABC456"],
    filter: {
      version: 1,
      root: {
        statement: "{{data.reaction}} == eyes"
      }
    }
  },
  inputs: {
    stringtoSend: {
      value: "how cool is that",
    },
    channel: {
      value: "C123ABC456",
    },
  },
};

The supported operand types are integer, double, boolean, string, and null. The following comparators are supported.

Comparator Supported types
==
all types
>
int, double
<
int, double
>=
int, double
<=
int, double
CONTAINS
string; i.e. {{data.text}} CONTAINS 'hello'

Boolean logic blocks

Boolean logic blocks are made up of two key:value pairs:

  • An operator key with a string containing the comparison operator: AND, OR, or NOT
  • An inputs key with the child blocks

The child blocks then contain additional logic. The following example filters on the reaction value:

{
  type: TriggerTypes.Event,
  name: "Reactji response",
  description: "responds to a specific reactji",
  workflow: "#/workflows/myWorkflow",
  event: {
    event_type: TriggerEventTypes.ReactionAdded,
    channel_ids: ["C123ABC456"],
    filter: {
      version: 1,
      root: {
        operator: "OR",
        inputs: [{
          statement: "{{data.reaction}} == sunglasses"
        },
        {
          statement: "{{data.reaction}} == smile"
        }],
      }
    }
  },
  inputs: {
    stringtoSend: {
      value: "how cool is that",
    },
    channel: {
      value: "C123ABC456",
    },
  },
};

Nested logic blocks
You can use the same boolean logic to create nested boolean logic blocks. It's boolean logic all the way down - up to a maximum of 5 nested blocks, that is. The NOT operator, however, must contain only one input. Also, at the moment the boolean logic block does not support short-circuit evaluation, so all arguments will be evaluated.

Trigger filters in sample apps

The Simple Survey App lets users collect feedback on specific messages. The process begins when a user reacts to a message with the :clipboard: reaction. This is done with a reaction_added event trigger filtering for the :clipboard: reaction.

The Daily Topic App can reply to messages in a channel. The message_posted event filters out both messages by apps (to prevent recursive replies) and messages within a thread (to reply only once per thread).

Event trigger response

The response will have a property called ok. If true, then the trigger was created, and the trigger property will be populated.

Your response will include a trigger.id; be sure to store it! You use that to update or delete the trigger if need be. See trigger management.

Onward

➡️ With your trigger created, you can now test your app by running your app locally.

✨ Once your app is active, see trigger management for info on managing your triggers in your workspace.


Have 2 minutes to provide some feedback?

We'd love to hear about your experience building Slack automations. Please complete our short survey so we can use your feedback to improve.