Introduction to triggered actions

Perform actions in response to Skedulo events.

Triggered actions allow you to perform actions in response to events that occur within the Skedulo platform. They are defined as a combination of a trigger and an action. A trigger defines the event that causes the triggered action to be executed and the action defines what should happen.

The most common type of triggered action is a “call_url”, which executes an HTTP request when a tenant data record is modified.

Triggered actions can be managed via the /triggered_actions endpoints in the Skedulo API.

Triggers

There are two types of triggers that can be defined:

  • object_modified: Executes when a tenant data record is inserted, updated or deleted.
  • event: Executed when a predefined event occurs. The following event types are supported:
    • async_task_completed: An asynchronous task executed by the platform has completed. Supported async tasks are:

      • bulk_user_import
      • copy_schedule
      • apply_schedule_template
    • recurring_schedule: This event can be triggered with an API call to /recurring/schedules/jobs/event to indicate that a Recurring Schedule update has finished.

Object modified triggers

An object modified trigger requires the following information:

  • A filter that specifies when the action should be performed.
  • The target schema/object name.
  • Optionally, a deferred specification.

The filter is a special version of the EQL format that is relevant to change events. It may refer to the Operation that caused the change (INSERT, UPDATE OR DELETE) and must refer to fields of the object via the Current or Previous parent object. For example, Operation == 'INSERT' AND Current.JobStatus != Previous.JobStatus.

For more information about using EQL filters, see the EQL filter section.

See also ‘Change event tracking for custom objects’ below.

Deferred triggers

The deferred specification for a trigger describes when in the future the action should be performed. This specification resolves to an instant in time that is calculated relative to the value of a specified DateTime field of the object (the “anchor” time).

The offset is specified as either a static value in milliseconds or a dynamic value that is provided by a field of the object.

If the value of the anchor time field or the offset field changes, the action will be rescheduled to the new time.

Example 1: Perform the action 5 minutes before the Start time of the job:

    "deferred": {
        "fieldName": "Start",
        "offset": -300000
    }

Example 2: Perform the action at some offset after the Start time of the job, as specified by the NotificationAfterStartOffset custom field, defaulting to 10 minutes:

    "deferred": {
        "fieldName": "Start",
        "offset": {
          "fieldName": "NotificationAfterStartOffset",
          "default": 600000
        }
    }

Actions

Actions are executed in response to a trigger event. There are two types of action: call_url and send_sms.

Call URL

A Call URL action requires the following information:

  • The action type: call_url.
  • The URL to call.
  • A list of headers to include in the request.

For object_modified triggers:

  • A GraphQL query block that specifies the data to include in the request payload. This query can include nested relationships and is executed relative to the object that triggered the action.
  • Optionally, a GraphQL query block that specifies the previous data values to include in the request payload from the data record that changed.

The call_url action configuration may contain Configuration Variable templates within these fields:

  • action.url
  • action.headers

See our triggered action guide for an example.

Set user context

For triggered actions from an object_modified trigger to a call_url action, you can include a template string {{ SKEDULO_USER_TOKEN }} in the header of the action, which is replaced at runtime by the access token of the user who performed the data change that initiated the object_modified trigger. Audit fields, such as ‘CreatedBy’ and ‘LastUpdatedBy’ record the user that initiates the change.

Note that the access token of the initiating user usually has fewer access privileges than API tokens from administrator users. Hence, when migrating to use this feature, the function invoked should make sure that it will work with the new access privileges.

Call URL payload for object_modified triggers

For object_modified triggers, the call_url action sends a POST request to the specified URL with a JSON payload. The payload contains the results of the configured GraphQL query block, combined with the previous values of selected fields, and the type of operation that triggered the action. The payload is a JSON array that includes a result for every record that has changed.

Note that the query is performed immediately before the action (HTTP request) is executed, so the data is current at the time of the action (it is not re-queried if the action is retried). This is different to a Skedulo webhook, which provides the data as it was at the time of the change event.

If previousFields is specified, the payload will include a previous object for each record that was updated or deleted. This object will contain the fields in the previousFields query block with values from before the triggering change event occurred. Values are provided for all the requested fields, even if they were null or they weren’t changed. previousFields cannot include nested objects.

Note that INSERT operations do not have a previous object and DELETE operations do not have a data object. Note also that the UID field is automatically added to the previous object for DELETE operations so the user can determine which record was deleted.

Multiple triggered action events can be combined into a single HTTP request payload with a JSON object for each record change.

A typical payload looks like below. This example is for an object_modified trigger on the Jobs object with the following configuration:

Configuration

  ...
  "query": "{ UID Name Region { Name } Duration JobStatus Description }",
  "previousFields": "{ Duration Quantity JobStatus }"
  ...

Payload

Note that this payload contains three JSON objects, meaning three different records were changed within a short time window, which all invoked the triggered action.

[
  {
    "data": {
      "jobs": {
        "UID": "00145e74-4acb-4369-89a1-37544f2a4d4f",
        "Name": "JOB-6633",
        "Region": {
          "Name": "New York"
        },
        "Duration": 60,
        "JobStatus": "Queued",
        "Description": "Testing triggered actions"
      }
    },
    "operation": "INSERT"
  },
  {
    "previous": {
      "Duration": 200,
      "Quantity": null,
      "JobStatus": "Queued"
    },
    "data": {
      "jobs": {
        "End": null,
        "UID": "00146198-6242-4fe0-9b53-bd4a55a6bc22",
        "Name": "JOB-6629",
        "Start": null,
        "Region": {
          "Name": "New York"
        },
        "Duration": 20,
        "JobStatus": "Queued",
        "Description": "Testing triggered actions"
      }
    },
    "operation": "UPDATE"
  },
  {
    "previous": {
      "Duration": 60,
      "Quantity": null,
      "JobStatus": "Queued",
      "UID": "001472cd-87ae-464e-bc15-d4e1855aa736"
    },
    "operation": "DELETE"
  }
]

Retries and timeouts

See the section about retries for more information about call_url actions, including when they are retried and their timeout period.

Send SMS

A Send SMS action ends an SMS message to a phone number provided in the configuration. It requires the following information:

  • The action type: send_sms.
  • The phone number(s) to send the SMS to.
  • The message template.

The phone number can be defined statically or as an EQL field name. For example, for a trigger on the Jobs object, the phone number can be Contact.MobilePhone.

The message template is defined in {{mustache}} format and may include EQL field names that can be extracted from the data provided by the trigger. The EQL field expression can use dot notation to refer to a field of a lookup reference. For example, a message template for a trigger on the Jobs object might look like this:

"template": "Hi {{ Contact.FirstName }}! Your {{ Type }} is due to start at {{ Start }}. It should take around {{ Duration }}"

Change event tracking for custom objects

In order for a data object to trigger a triggered action, it has to be tracked for changes. Tracking is automatically enabled on standard data model objects, and on all custom objects created after 10 May 2024. Custom objects created prior to this date need to have tracking manually enabled. Additionally, Skedulo for Salesforce teams require additional configuration within Salesforce in order to enable change event tracking for all objects.

To manually enable tracking on a custom object, follow these steps:

  1. Find the id of the custom object (schema) using the /custom/schemas endpoint in the Skedulo API
  2. Pass the id to this endpoint: /custom/standalone/schema/{id}/track