Actions

Perform actions in response to Skedulo events.

There are two types of actions that can be defined: 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 the 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 may have 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 sends 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.Mobile.

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 }}"

Automatic formatting for Date & time fields

When a Date & time field (e.g. Start) is used in the template, it is automatically formatted. The system looks for a field named Timezone (case insensitive) on the trigger object (e.g. Jobs) and applies this time zone when formatting the Date & time field.

For example:

  • If a Timezone field is present and set to “America/Los_Angeles”, Start would be displayed like “Dec 25, 2:30 AM PST”.
  • If a Timezone field is not present or is invalid, the time is displayed in GMT (Greenwich Mean Time). Start would be displayed like “Dec 25, 10:30 AM GMT”.

Template functions

You can also use built-in functions for more dynamic messages.

1. first

This function returns the value of the first field in a list that is defined. You can also set an optional default string.

{{first Field1 Field2 [Field3 ...] [default] }}

Parameters:

Section Type Example Description
Field1 Field2 Field3 FieldName CustomerPhone Contact.Mobile Contact.OtherPh A list of fields on the trigger object or via a lookup relationship (not quoted)
default String "our office" An optional quoted string that is used if none of the fields have a value

Examples:

Inputs Output SMS
Template: Please call {{first Contact.Mobile Contact.OtherPh "our office"}} to confirm.

Trigger data:
{"Contact": {"Mobile": "+15551234567"}}
“Please call +15551234567 to confirm.”
Template: Please call {{first Contact.Mobile Contact.OtherPh "our office"}} to confirm.

Trigger data:
{"Contact": {"OtherPh": "+15559876543"}}
“Please call +15559876543 to confirm.”
Template: Please call {{first Contact.Mobile Contact.OtherPh "our office"}} to confirm.

Trigger data:
{"Contact": {}}
“Please call our office to confirm.”

2. formatDateTime

This function gives you more control over how a datetime field is formatted.

{{formatDateTime DatetimeVar [TimezoneVar] [default] [pattern] }}

Parameters:

Section Type Example Description
DatetimeVar FieldName Start The date & time field name
TimezoneVar FieldName CustomTz Contact.Timezone The timezone field name. The timezone must be a valid IANA timezone ID

If a timezone isn’t specified, the Timezone field on the trigger object is used. If both are empty and/or invalid, Greenwich Mean Time (GMT) is used.
default String "No time specified" A quoted string that is used if the DatetimeVar field is empty
pattern String "hh:mma" An optional quoted string containing a valid datetime pattern

If the pattern is empty or invalid, the format defaults to "MMM dd, hh:mma zzz" (e.g., “Dec 25, 10:30 AM GMT”).

Examples:

Inputs Output SMS
Template: {{formatDateTime Start }}

Trigger data:
{"Start": "2023-12-25T10:30:00Z"}
"Dec 25, 10:30 AM GMT"
Template: {{formatDateTime Start }}

Trigger data:
{"Start": "2023-12-25T10:30:00Z", "Timezone": "America/Los_Angeles"}
"Dec 25, 2:30 AM PST"
Template: {{formatDateTime Start CustomTz }}

Trigger data:
{"Start": "2023-12-25T10:30:00Z", "Timezone": "America/Los_Angeles", "CustomTz": "Australia/Brisbane"}
"Dec 25, 8:30 PM AEST"
Template: {{formatDateTime Start "No time set" }}

Trigger data:
{}
"No time set"
Template: {{formatDateTime Start "" "hh:mma" }}

Trigger data:
{"Start": "2023-12-25T10:30:00Z", "Timezone": "America/Los_Angeles"}
"2:30 AM"
Template: {{formatDateTime Start }}

Trigger data:
{"Start": "invalid-datetime"}