Trigger Workflow from API
Guide to configure and trigger workflow using go SDK
Pre-requisites
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
Parameter | Description | Format | Obligation |
---|---|---|---|
name | It 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 stage | text | Mandatory |
template | It 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 name | Mandatory |
notification_category | You can understand more about them in the 'Notification Category' documentation | system / transactional / promotional | Mandatory |
delay | Workflow 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 |
users | Array object of target users. Atleast 1 user mandatory. distinct_id for each user mandatoryChannel 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 |
delivery | Delivery 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 |
data | JSON. To replace the variables in the template, templates use [handlebars](https://handlebarsjs.com/guide/) language | "data": { "key": { "key": "value", "key": "value" } }, | Optional |

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 givensuccess
-metric is achieved.
- Possible values:
-
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.
- currently, event-window is not configurable. default set to
- Possible values:
-
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.
- applicable when
-
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.
- applicable when
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. Ifsuccess
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 WhatsappFor setting
$sms
and+<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
Updated 8 months ago