Custom triggers

Build a custom trigger that will listen to events on external system to ignite the integration recipe.

What is a trigger?

A trigger is a type of workflow block that invokes an automation. Typically the trigger will happen (for example, a status changes to "Done") and this will trigger one or more action blocks.

The monday Apps framework supports two types of triggers: built-in triggers and custom triggers.

Built-in triggers are used when you want your recipe to be triggered by an event on the monday.com platform (e.g creating an item, updating a column, etc.). These can be used as default triggers in your recipe.

Next are custom triggers. You can use custom triggers when you want your recipe to be triggered by an event on your system side to perform some action on the monday.com side (e.g. a lead in a CRM system was created, the inventory in an ERP system was updated, etc.).

Custom triggers

In order to successfully use custom triggers, you will need to build the custom trigger and connect it to the system you are using.

Custom triggers can also be used for monday-to-monday automations. If there's a specific trigger you need that isn't available in our Built-in Triggers, they can still be implemented on the backend with the help of monday webhooks or data polling.

Now that we identified the 2 different types of triggers, let's get to building them.

When building a custom trigger, you'll need to define a few things that make up the API of your trigger:

  • Input fields, which are the configuration your trigger needs to run
  • Output fields, which is the data your trigger will pass to the action
  • A subscribe URL
  • A mechanism to store webhook URLs and call them when the specific trigger is invoked
  • An unsubscribe URL

Build your first custom trigger

To start building a custom trigger, you will need to open the "Workflow Blocks" tab of your app's integration and click "Create New" and then on "Trigger"

1786

Input fields

You can define the input fields for your custom trigger; in the event you want to choose some parameter in the recipe.

For example, a user can choose a "Leads Category" if they are looking to select leads from a CRM system. This will then sync into monday.com.

For this specific case, you would be creating a custom field type with the ability to gather leads from categories on the backend. This would then use these as an input field for your custom trigger.

Output fields

Output fields are how you pass data between your custom trigger and the action. You can map your trigger's output fields to the input fields of your action, thus combining them and allowing for more logic.

📘

NOTE

The max character limit for a custom trigger or action is 255 characters for each one - meaning they can be used together for a total of 510 characters on the entire recipe. As a best practice we recommend making recipes short and easily configurable, breaking the logic into multiple recipes if necessary.

Subscription URLs

The endpoints of your server are represented by two types of URLs: a subscribe and an unsubscribe URL. These endpoints will both need to be defined before they are called by the monday.com platform whenever a specific user adds or removes recipes from a board.

These will need to be implemented by your server in order to save/remove context information as well as for understanding which data needs to be updated when the custom trigger is called.

When the monday server calls these endpoints, it will supply the current configuration for any input fields (for example, the board ID).

The full flow looks like this (e.g for the case of custom trigger "When the Lead in CRM system was created"):

Subscribing to your trigger

Subscribe URL

Every time a user adds your recipe to a board, the Subscribe URL will be called with the following parameters:

Method: POST

Body

{
  "payload": {
    "webhookUrl": "https://api.monday.com/trigger/123", //callback url, which you should call when recipe action should be triggered
    "subscriptionId": 123456789012, //unique identifier of the specific user subscription    
    "inputFields": { //values of all input fields, which were configured for your custom trigger
      "boardId": 234567890123 //f.e. boardId
      }, 
    "recipeId": 345678901234, //unique ID of the recipe in your app. the same recipe ID will be sent if two different accounts are using the same recipe
    "integrationId": 456789012345 //unique ID of the integration recipe on your board
    }
}

Authorization header

The Authorization header is the JWT token signed by your app's Signing Secret. It will be included whenever the Subscribe URL is called and should be verified with your Signing Secret on each call.

The JWT token has the following structure:

{
  "accountId": 739628, // user account ID
  "userId": 4616666, // user ID
  "aud": "https://my-app-backend.com/subscribe", // which URL was meant to be called
  "exp": 1592342588, // when the token will be expired
  "iat": 1592342288 // when the token was issued
}

To prevent your token from being stolen and used, ensure your endpoint is listed in the "aud" field. You should also verify that the token is valid and has not expired.

Response

You can manage your subscription and place it in your storage during the response call. At the same time, your endpoint must respond to the response call in a JSON format with a 200 status and the following response body:

{
  "webhookId": 111
}

In this response, the webhookId is the unique identifier of a subscription instance created on your side. It can be in any format and will be sent to your Unsubscribe URL when the user deletes the recipe. If you don't respond with the webhookId, the subscriptionId will be used instead.

Calling your action

Whenever custom events are triggered in your system (e.g. when a lead is created in the CRM), you need to identify what instance of the recipe (subscription) you would like triggered on the monday.com side.

A POST request to the webhookURL should then be sent with the set of output fields defined in your custom trigger. This should be signed with a JWT that contains the app's ID and signing secret in the Authorization header.

const authorization : string =
  jwt.sign( payload: { appId: 'YOUR_APP_ID_HERE', secretOrPrivateKey: 'YOUR_SIGNING_SECRET_HERE');

Body

{
  "trigger": {
    "outputFields": { //values of all output fields, which were configured for your custom trigger
      "itemId": 12345678 //f.e. itemId
    }
  }
}

Unsubscribing from your trigger

Unsubscribe URL

When a user removes your recipe from a board, your Unsubscribe URL will be called with the following parameters:

Method: POST

Body

{
  "payload": {
    "webhookId": 111 //the same webhookId, which you responded in your Subscribe endpoint
  }
}

Authorization header

The Authorization header is the JWT token signed by your app's Signing Secret. It will be included whenever the Unsubscribe URL is called and should be verified with your Signing Secret on each call.

The JWT token has the following structure:

{
  "accountId": 739628, // user account ID
  "userId": 4616666, // user ID
  "aud": "https://my-app-backend.com/subscribe", // which URL was meant to be called
  "exp": 1592342588, // when the token will be expired
  "iat": 1592342288 // when the token was issued
}

Response

During this call, you should remove the subscription from your persistent storage based on the unique webhookId.

After the call, you should respond to the endpoint with 200 HTTP status without the payload. If you respond with an error, not 2XX status, we will prevent the user from deleting the recipe.

📘

NOTE

If a user disables the recipe the Unsubscribe Url will not be called. In this case all the calls to the action from this specific trigger will be ignored.

Congratulations Builder!

Once you've finished this article, read these to learn more about key concepts:

📘

Join our developer community!

We've created a community specifically for our devs where you can search through previous topics to find solutions, ask new questions, hear about new features and updates, and learn tips and tricks from other devs. Come join in on the fun! 😎