Courier's Automations let you trigger a series of steps –like send, delay, update profile, fetch-data– where each step represents a specific action that the automation will execute on your behalf when an event is sent to the Automation API.

Automations can be defined and triggered ad-hoc with a single API call or by calling a re-usable Automation template defined in the Automations designer.


Table of Contents

Structuring an automation

Automation templates

Triggering an automation

Examples


Structuring an Automation

  • There are six step types that can be used to build an automation: Send, Send-list, Fetch-Data, Delay, Update-Profile, Cancellation

  • There are two ways to create and trigger an automation to a recipient or list of recipients: on a one-off ad hoc basis using the /invoke endpoint or by triggering a reusable automation template created in the Courier Designer via the /template/invoke endpoint.

Automation Steps

An automation step represents a specific action, that the automation will execute on your behalf. There are four step options that you can build into an Ad Hoc or Templated automation

Send

A send step will deliver a single message to a recipient.

{
"action": "send",
"data": {}, // optional
"if": "<CONDITIONAL_EXPRESSION>", // optional javascript boolean
expression
"override": {}, // optional: send provider override
"profile": {}, // optional
"recipient": "<RECIPIENT_ID">,
"template": "<TEMPLATE_ID>"
}

Send List

A send-list step will deliver a message to a list of recipients.

{
"action": "send-list",
"brand": "<BRAND_ID>", //optional:
"if":"<CONDITIONAL_EXPRESSION>", //optional javascript boolean
expression
"override": {}, //optional: send provider override
"data": {}, //optional
"list": "<LIST_ID>",
"template": "<TEMPLATE_NAME_OR_ID>"
"data_source": { //optional
"webhook": {
"body": {},//optional
"headers": {}, //optional
"params": {}, //optional
"method": "GET"|"POST", //optional, default GET
"url": string
},
"merge_strategy": "replace|overwrite|soft-merge|none";
};
"idempotency_expiry": "<IDEMPOTENT_EXPIRATION>"
"idempotency_key": "<IDEMPOTENT_KEY>"
}

  • You can use the data-source property to define an API resource to be used to render a notification template.

  • The data_source.url should accept a recipientId query string parameter.

  • The response from the data_source property will be merged with the existing automation data that was defined at runtime, based on the merge strategy, and will be passed to the notification template as the data property.

Send Idempotency features

send and send-list steps support idempotency for safely retrying requests without accidentally performing the same operation twice.

To define an idempotent send or send-list step, provide an idempotency_key property on the step. An idempotency key is a unique value generated by the client which the server uses to recognize subsequent retries of the same request. How you create unique keys is up to you, but we suggest using V4 UUIDs, or another random string with enough entropy to avoid collisions.

In addition to the idempotency_key , you can define an idempotency_expiry that allows you to set an expiration on the idempotency_key that is longer than 24 hours (up to 1 year).

Example: Idempotent send step.

{
action: "send",
recipient: "example@emaildomain.com",
template: "Idempotence",
idempotency_key: "abcd-1234",
idempotency_expiry: 1618947104 //expiration date in epoch time
}

Fetch-Data

A fetch-data step will fetch data from an API resource and store it into run context, to be used for subsequent step executions.

{
"action": "fetch-data",
"webhook": {
"body": {

},
//optional"headers": {

},
//optional"params": {

},
//optional"method": "GET"|"POST",
//optional,
defaultGET"url": "<API_RESOURCE>"
},
"merge_strategy": "replace|overwrite|soft-merge|none",
"idempotency_expiry": "<IDEMPOTENT_EXPIRATION>",
"idempotency_key": "<IDEMPOTENT_KEY>"
}

The response from the fetch-data step will be merged with the existing automation data that was defined at runtime, based on the merge strategy, and will be passed to the notification template as the data property.

Delay

Important: When using the delay step, an automation will be processed serially. Each item in the automation is processed one at a time and the next step will not be undertaken until the current one has completed. When delay steps are not present steps will be processed in parallel.

There are two ways to delay an automation step

  • Delay until a specific time

  • Delay for a period of time

Delay until a specific time

To delay a step until a specific time, set the time using an ISO-8601 timestamp

{
"action": "delay",
"delayUntil": "2021-02-18T18:40:05.960Z"//ISO-8601timestamp
"if": "<CONDITIONAL_EXPRESSION>", //optional booleanexpression
}

Delay for a period of time

You are able to delay an automation step for the following whole increments: -

  • minute(s)

  • hours(s)

  • day(s)

  • month(s)

{ 
"action": "delay", "delayFor": "1 hour"
"if": "<CONDITIONAL_EXPRESSION>", // optional boolean expression
}

Update-Profile

An update-profile step will update the recipient's profile according to the "merge" strategy provided in the step.

{ 
"action": "update-profile",
"recipient_id": "<RECIPIENT_ID>",
"profile": {},
"merge": "replace|overwrite|soft-merge|none"
}

Merge strategy definitions:

In the following definitions, A = a profile attribute defined in the step; B = an existing profile in Courier.

  • Replace: overwrites all properties in B from A; remove properties in B that do not exist in A

  • Overwrite: overwrite all properties in B from A

  • Soft-merge: only overwrite properties in B from A that do not yet exist in B

  • None: No changes to B if B already exists; else B = A

Cancelation

Automations can be marked as cancelable by providing a cancelationToken then cancelled by providing a cancelation tep on a subsequent automation.

Any automations that have a matching cancelation token will be cancelled.

Providing a cancelationToken

{ 
"cancelationToken": "<CANCELATION_TOKEN>",
"steps": [
// ... step configuration
]
}

Cancelling automations using a cancelationToken

{ 
"steps": [
{ "action": "cancel", "cancelationToken": "<CANCELATION_TOKEN>" }
]
}

Step Conditionals

You can define conditions that will determine if a step is executed or not. Adding an if property to a step makes it a conditional step. The value of the if property should be a valid javascript expression that evaluates to a boolean.

For example, the following send step has a conditional expression that should evaluate to true , therefore, the step will be executed.

{
"template": "TEST",
"recipient": "abcd-1234-efgh-5678",
"profile": {
"email": "test@gmail.com"
},
"data": {
"foo": "send-it"
},
"automation": {
"steps": [
{
"action": "send",
"if": "data.foo === 'send-it'"
}
]
}
}

Step References and Conditionals

You can define a step level reference, by adding a ref property to a step definition.

In subsequent send steps, you can then reference metadata about the sent message.

For example, you only want to send a follow-up message if that message hasn't been opened yet, you can define the following automation run:

{
"automation": {
"steps": [
{
"action": "send",
"template": "OUTREACH",
"ref": "outreach"
},
{
"action": "delay",
"delayFor": "24 hours"
},
{
"action": "send",
"template": "FOLLOWUP",
"ref": "followup",
"if": "refs.outreach.status < MessageStatus.Opened"
},
]
}
}

Run-Step Composition

There are a few object properties that can be defined at both the step and the run level. data and profile properties will compose, with the step level properties taking precedence.

For example, the "Title" property will compose into each step and will be available to each step.

{
[...]
"data": {
"Title": "Back to the Future"
}
"automation": {
"steps": [
{
[...]
"data": {
"Username": "Doc Brown"
}
},
{
[...]
"data": {
"Username": "Marty McFly"
}
},
[...]
]
}
}

Templates

You can pre-define a list of automation steps by creating an automation template in the Designer UI. Automation Templates support JSONNET.

You can create templates from scratch or start from one of the predefined templates for common use cases.

Note: Edits you make to an automation template will not apply retroactively to any recipients or lists already added to an automation run.

Build a Notification Automation Template

The template builder lets you create and save a reusable Automation.

Scheduling and Delaying Notifications Using Courier

Structure

Automation templates

// define global variables here
{
sources: ["<EVENT_NAME>"], // list of event source that this
template can be triggered by
steps: [], // a list of automation steps
}

At runtime, you can pass a data and/or profile property into your template.

//1.define the template to send to a list of users 
local list=data('users', []);
{
steps: [
{
action: "send",
profile: {
email: email
},
recipient: item.userId,

}
for item in list
for email in item.email
]
}

//2.make the api call and provide the user list

{
event: "SEND-TO-USERS",
user: "abc-123",
//defaultrecipientdata: {
users: [
{
userId: "123-abc-123",
email: [
'user1@gmail.com',
'user1_altl@gmail.com'
]
},
{
userId: "abc-123-abc",
email: [
'user2@yahoo.com'
]
},

]
}
}

Triggering an Automation

To trigger an automation run, there are three apis that can be called with your Courier API token.

  • automations/invoke

  • automations/{templateId}/invoke

Trigger an ad hoc automation via /invoke

POST - /automations/invoke

Invoke an ad hoc automation run, by providing a valid automation definition in the request body.

Structure

{
"brand": "<BRAND_ID>", // optional: brand id
"template": "<TEMPLATE_NAME_OR_ID>", //optional
"recipient": "<RECIPIENT_ID>", //optional: user id for automation
"data": {}, //optional: root level data for the ad hoc automation
"profile": {},
//optional root level profile information for ad hoc
"automation": {
"cancelationToken": "<CANCELATION_TOKEN>",
//optional: can be used to later cancel the running automation
"steps": [
{
"action": "send",
"data": {}, //optional: uses root level data if not present
"profile": {},
//optional: uses root level profile if not present
"recipient": "<RECIPIENT_ID>",
//recipient of the message. will fallback to root recipient
"template": "<TEMPLATE_ID>",
//the notification template to use,
"brand": "<BRAND_ID>",
//optional: will use root level brand_id if not present
"override": {}, //optional: send provider override
"if": "<CONDITIONAL_EXPRESSION>",
//optional javascript boolean expression
//see send step documenation above for more details
},
{
"action": "delay",
//either delayFor or delayUntil is required
//seedelaystepdocumenationaboveformoredetails
},
{
"action": "cancel",
"cancelationToken": "<CANCELATION_TOKEN>",
"if": "<CONDITIONAL_EXPRESSION>",
//optional javascript boolean expression
//see cancel step documenation above for more details
}
]
}
}

Trigger an automation template via /template/invoke

POST - /automations/{templateId}/invoke

Structure

{
"template": "<TEMPLATE_NAME_OR_ID>",
// optional: the notification template name
"recipient": "<RECIPIENT_ID>",
// optional: recipient id for the automation run
"data": {}
// optional: root level data to be passed into automation template
"profile": {}
// optional: root level profile information to be passed into your automation template
}

Examples

Batch Send to Multiple Recipients

Use the send action to send the messages to multiple recipients. Data for each message can vary per step. This includes data, profile, and the template.

// POST /automations/invoke
{
"automation": {
"steps": [
{
"action": "send",
"data": {},
"profile": {},
"recipient": "<RECIPIENT_ID_1>",
"template": "<TEMPLATE_ID_1>",
},
{
"action": "send",
"data": {},
"profile": {},
"recipient": "<RECIPIENT_ID_2>",
"template": "<TEMPLATE_ID_2>",
},
// ... more send events
]
}
}

Use Delay and Cancel Step

The delay step can be used to create delays between actions. The following is an example of an invite user flow that also includes a reminder. Because the user shouldn't be notified if they accept the invite, a cancelation token can be specified. This allows for a follow-up event to be called that can be used to cancel the original workflow.

// POST /automations/invoke
{
"automation": {
"cancelationToken": "<EVENT_NAME>/<USER_ID>", // invite-new-user/abc12345
"steps": [
{
"action": "send",
"template": "invite-user"
// data, profile, and recipient will be taken from the root level event
},
{
"action": "delay",
"delayFor": "1 day"
},
{
"action": "send",
"template": "invite-reminder"
// data, profile, and recipient will be taken from the root level event
}
]
}
}

// POST /automations/invoke (if invitation accepted before reminder sent)
{
"event": "<EVENT_NAME>",
"data": {},
"profile": {},
"user": "<USER_ID>",
"automation": {
"steps": [
{
"action": "cancel",
"cancelationToken": "invite-new-user/abc12345"
}
]
}
}
Did this answer your question?