Trigger Workflow from API

Guide to configure and trigger workflow using go SDK

Pre-requisites

  1. Integrate Go SDK
  2. Create Template on SuprSend platform

Trigger Workflow from API

You can trigger workflow from go SDK using suprClient.TriggerWorkflow method

// Create workflow body
wfBody := map[string]interface{}{
  "name":                  "Workflow Name",
  "template":              "template slug",
  "notification_category": "category",
  // "delay":                 "15m", // Chek duration format in documentation

  "users": []map[string]interface{}{
    {
      "distinct_id": "__distinct_id__",

      // if $channels is present, communication will be tried on mentioned channels only.
      // "$channels": []string{"email"},
      "$email": []string{"[email protected]"},
      "$androidpush": []map[string]interface{}{
        {"token": "__android_push_token__", "provider": "fcm", "device_id": ""},
      },
    },
  },

  // delivery instruction. how should notifications be sent, and whats the success metric
  "delivery": map[string]interface{}{
    "smart":   false,
    "success": "seen",
  },

  // data can be any json string
  "data": map[string]interface{}{
    "key1":   "value1"
  },
}

wf := &suprsend.Workflow{
  Body:           wfBody,
  IdempotencyKey: "",
  BrandId:        "",
}

// Call TriggerWorkflow to send request to Suprsend
_, err = suprClient.TriggerWorkflow(wf)
if err != nil {
  log.Fatalln(err)
}




For configuring a workflow from backend, you can pass following properties in your method

ParameterDescriptionFormatObligation
nameIt is the unique name of the workflow. You can see workflow-related analytics on the workflow page (how many notifications were sent, delivered, clicked or interacted). The workflow name should be easily identifiable for your reference at a later stagetextMandatory
templateIt is the unique slug of the template created on SuprSend platform. You can get this slug by clicking on the clipboard icon next to the Template name on SuprSend templates page.
It is the same for all channels
slug nameMandatory
notification_categoryYou can understand more about them in the Notification Category documentationsystem / transactional / promotionalMandatory
delayWorkflow will be halted for the time mentioned in delay, and become active once the delay period is over.XXdXXhXXmXXs or if its number (n) then delay is in seconds (n)Optional
usersArray object of target users.

Atleast 1 user mandatory.

distinct_id for each user mandatory

Channel information is non-mandatory. If you pass channel information here, then these channels will be used for sending notification otherwise channels will be picked from user profile.
"users":
[
{
"distinct_id": "value",
"$channels":[],
channel_information_dict #(optional)
],
Mandatory
deliveryDelivery instructions for the workflow. You can enable smart delivery by setting "smart":True

By default, delivery instruction will be "delivery": {
"smart": False,
"success": "seen"
}

Further details are given in the below section
delivery = {
"smart": True/False,
"success": "seen/interaction/",
"time_to_live": "",
"mandatory_channels": [] # list of mandatory channels e.g gation",

}
Optional
dataJSON.
To replace the variables in the template, templates use handlebars language
"data":
{ "key": {
"key": "value",
"key": "value"
}
},
Optional

2878

To find the template slug name on SuprSend platform, click on the clipboard icon on Templates page.
Templates > Template Details Page



Smart Delivery

Multi-channel strategy is indeed important to increase the effectiveness of communications (eg. it improves overall delivery rate, seen rate and interactions), but it comes with a side effect. While the intention is right to reach out to your users on multiple channels, it sometimes leads to user bombarding. Example, you have created templates for 4 channels, when a notification is triggered, it goes to all the channels together. For a user who has already seen the message or interacted with the message on 1 channel, rest of the channels are just noise. Needless to say, it is also a cost to the company.

SuprSend Workflows handle this via Smart Delivery. For any workflow, you can turn Smart Delivery on /off in your API call, along with few additional details:

All delivery options:

"delivery": map[string]interface{}{
  "smart": true/false,
  "success": "seen/interaction/<some-user-defined-success-event>",
  "time_to_live": "<TTL duration>",
  "mandatory_channels": []string{}, // list of mandatory channels e.g ["email"]
}

Where

  • smart (boolean) - whether to optimize for number of notifications sent?

    • Possible values: True / False
    • Default value: False
    • If False, then notifications are sent on all channels at once.
    • If True, then notifications are sent one-by-one (on regular interval controlled by time_to_live)
      on each channel until given success-metric is achieved.
  • success - what is your measurement of success for this notification?

    • Possible values: seen / interaction / <some-user-defined-success-event>
    • Default value: seen
    • If seen: If notification on any of the channels is seen by user, consider it a success.
    • If interaction: If notification on any of the channels is clicked/interacted by the user, consider it a success.
    • If <some-user-defined-success-event>: If certain event is done by user within the event-window (1 day), consider it a success.
      • currently, event-window is not configurable. default set to 1d (1 day).
        success-event must happen within this event-window since notification was sent.
  • time_to_live - What's your buffer-window for sending notification.

    • applicable when smart=True, otherwise ignored
    • Default value: 1h (1 hour)
    • notification on each channel will be sent with time-interval of [time_to_live / (number_of_channels - 1)] apart.
  • mandatory_channels - Channels on which notification has to be sent immediately (irrespective of notification-cost).

    • applicable when smart=True, otherwise ignored
    • Default value: [] (empty list)
    • possible channels: email, sms, whatsapp, androidpush, iospush etc.

If delivery instruction is not provided, then default value is:

"delivery": map[string]interface{}{
  "smart":   false,
  "success": "seen",
},

How Smart Delivery Works?

  • When you turn on Smart Delivery, Workflows pick up mandatory channels provided and triggers notification on them immediately. If there are no mandatory channels provided, workflows order channels in low-to-high cost basis, and trigger notification on first channel in the order immediately. Cost is picked up from the value entered in Vendor Settings page. Eg. FCM has 0 cost and it will be picked up first. If cost is not mentioned, it is considered 'zero' for order-calculation purpose.
  • Now for rest of the channels, workflows will trigger on them one by one with some interval between them. This time interval is calculated from time_to_live you have defined: time-interval = [time_to_live / (number_of_channels - 1)]. Eg. if you provide 4 channels and your message is relevant for 1 hour (ie. time_to_live = 1 hour), first channel will be triggered immediately, and the rest 3 will be triggered in every 20 minutes.
  • In between the channel triggers, workflows will listen to the response, and check whether the success defined is met or not. If it is met, rest of the channel triggers are not attempted. If success is not met, the process will continue until all channels are exhausted.

Add file attachment in email

To add one or more Attachments to a Notification (viz. Email), call wfInstance.AddAttachment() for each file with local-path or an accessible URL.

workflowBody := {...}
wfInstance := Workflow{Body: workflowBody}

// this snippet can be used to add attachment to workflow
err = wfInstance.AddAttachment("/home/user/billing.pdf", &suprsend.AttachmentOption{FileName: "Billing.pdf"})
if err != nil {
    log.Println(err)
} 

Attachment structure

The AddAttachment() call appends below structure to data->'$attachments'

{
    "filename": "billing.pdf",
    "contentType": "application/pdf",
    "data": "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh",
}

Where:

filename - name of file.
contentType - MIME-type of file content.
data - base64-encoded content of file.


Sample Workflow body

Below is a sample workflow body with all the possible configurations for your reference. You can copy paste below code and replace the values with the actual values

// Create workflow body
wfBody := map[string]interface{}{
  "name":                  "Purchase Workflow",
  "template":              "purchase-made",
  "notification_category": "transactional",
  
  "users": []map[string]interface{}{
    {
      "distinct_id": "0f988f74-6982-41c5-8752-facb6911fb08",
      "$email": []string{"[email protected]"},
    },
  },
  
  // delivery instruction. how should notifications be sent, and whats the success metric
  "delivery": map[string]interface{}{
    "smart":   false,
    "success": "seen",
  },
  
  // # data can be any any json string
  "data": map[string]interface{}{
    "first_name":   "Joe",
    "spend_amount": "$10",
    "nested_key_example": map[string]interface{}{
      "nested_key1": "some_value_1",
      "nested_key2": map[string]interface{}{
        "nested_key3": "some_value_3",
      },
    },
  },
}

wf := &suprsend.Workflow{
  Body:           wfBody,
  IdempotencyKey: "",
  BrandId:        "",
}

// Call TriggerWorkflow to send request to Suprsend
_, err = suprClient.TriggerWorkflow(wf)
if err != nil {
  log.Fatalln(err)
}



👍

+CountryCode Required for SMS and Whatsapp

For setting $sms and $whatsapp, +<countrycode> is mandatory to send along with phone number. Eg: +1 for US


Response structure

When you call suprClient.TriggerWorkflow, the SDK internally makes an HTTP call to SuprSend Platform to register this request, and you'll get an error message if something fails

Note: The actual processing/execution of workflow happens asynchronously.


What happens once you get 20x response

Once your request is accepted, you can check the status of your request in the ' SuprSend Logs' section. In the background, a workflow is created with the given workflow name.


Bulk API for triggering multiple workflows

Bulk API allows you to send multiple workflow requests in a single call. There isn't any limit on number-of-records that can be added to bulk_workflows instance.

Use .Append() on BulkWorkflows instance to add however-many-records to call in bulk.

// Workflow: 1
wf1 := &suprsend.Workflow{
  Body: map[string]interface{}{
    "name":                  "__workflow_name__",
    "template":              "__template_slug__",
    "notification_category": "__category__", // system/transactional/promotional
    "users": []map[string]interface{}{
      {
        "distinct_id": "__distinct_id__",
        "$email":      []string{"__email__"},
      },
    },
  },
  IdempotencyKey: "",
  BrandId:        "",
}

// Workflow: 2
wf2 := &suprsend.Workflow{
  Body: map[string]interface{}{
    "name":                  "__workflow_name__",
    "template":              "__template_slug__",
    "notification_category": "__category__", // system/transactional/promotional
    "users": []map[string]interface{}{
      {
        "distinct_id": "__distinct_id__",
        "$email":      []string{"__email__"},
      },
    },
  },
  IdempotencyKey: "123456",
  BrandId:        "default",
}
// ...... Add as many Workflow records as required.

// Create bulk workflows instance
bulkIns := suprClient.BulkWorkflows.NewInstance()

// add all your workflows to bulkInstance
bulkIns.Append(wf1, wf2)

// Trigger
bulkResponse, err := bulkIns.Trigger()
if err != nil {
  log.Println(err)
}
log.Println(bulkResponse)


How SuprSend Processes the bulk API request

  • On calling bulkIns.Trigger(), the SDK internally makes one-or-more Callable-chunks.
  • Each callable-chunk contains a subset of records, the subset calculation is based on each record's bytes-size and max allowed chunk-size, chunk-length etc.
  • For each callable-chunk SDK makes an HTTP call to SuprSend to register the request.

Response

Response is an instance of suprsend.BulkResponse type

// Response structure

suprsend.BulkResponse{
  Status : "success",
  Total : 10, // number of records sent in bulk
  Success : 10, // number of records succeeded
  Failure : 0, // number of records failed
  FailedRecords : [],
}

suprsend.BulkResponse{
  Status : "fail",
  Total : 10, // number of records sent in bulk
  Success : 0, // number of records succeeded
  Failure : 10, // number of records failed
  FailedRecords : [{"record": {...}, "error": "error_str", "code": 500}]
}

suprsend.BulkResponse{
  Status : "partial",
  Total : 10, // number of records sent in bulk
  Success : 6, // number of records succeeded
  Failure : 4, // number of records failed
  FailedRecords : [{"record": {...}, "error": "error_str", "code": 500}]
}


Limitation

A single workflow body size must not exceed 800KB (800 * 1024 bytes). If size exceeds this limit, it will return error