Skip to main content

Suprsend library for Python

Project description

suprsend-py-sdk

This package can be included in a python3 project to easily integrate with SuprSend platform.

We're working towards creating SDK in other languages as well.

SuprSend SDKs available in following languages

  • python3 >= 3.7 (suprsend-py-sdk)
  • node (suprsend-node-sdk)
  • java (suprsend-java-sdk)

Installation

suprsend-py-sdk is available on PyPI. You can install using pip.

pip install suprsend-py-sdk

This SDK depends on a system package called libmagic. You can install it as follows:

# On debian based systems
sudo apt install libmagic

# If you are using macOS
brew install libmagic

Usage

Initialize the SuprSend SDK

from suprsend import Suprsend
# Initialize SDK
supr_client = Suprsend("workspace_key", "workspace_secret")

Following example shows a sample request for triggering a workflow. It triggers a notification to a user with id: distinct_id, email: user@example.com & androidpush(fcm-token): __android_push_fcm_token__ using template purchase-made and notification_category system

from suprsend import Workflow
# Prepare Workflow body
workflow_body = {
    "name": "Purchase Workflow",
    "template": "purchase-made",
    "notification_category": "system",
    # "delay": "15m",  # Check duration format below
    "users": [
        {
          "distinct_id": "0f988f74-6982-41c5-8752-facb6911fb08",
          # if $channels is present, communication will be tried on mentioned channels only.
          # "$channels": ["email"],
          "$email": ["user@example.com"],
          "$androidpush": [{"token": "__android_push_token__", "provider": "fcm", "device_id": ""}],
        }
    ],
    # delivery instruction. how should notifications be sent, and whats the success metric
    "delivery": {
        "smart": False,
        "success": "seen"
    },
    # data can be any json / serializable python-dictionary
    "data": {
        "first_name": "User",
        "spend_amount": "$10",
        "nested_key_example": {
            "nested_key1": "some_value_1",
            "nested_key2": {
              "nested_key3": "some_value_3",
            },
        }
    }
}
wf = Workflow(body=workflow_body)
# Trigger workflow
response = supr_client.trigger_workflow(wf)
print(response)

When you call supr_client.trigger_workflow, the SDK internally makes an HTTP call to SuprSend Platform to register this request, and you'll immediately receive a response indicating the acceptance status.

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

# If the call succeeds, response will looks like:
{
    "success": True,
    "status": "success",
    "status_code": 202,
    "message": "Message received",
}

# In case the call fails. You will receive a response with success=False
{
    "success": False,
    "status": "fail",
    "status_code": 400/500,
    "message": "error message",
}

Duration Format

format for specifying duration: [xx]d[xx]h[xx]m[xx]s Where

  • d stands for days. value boundary: 0 <= d
  • h stands for hours. value boundary: 0 <= h <= 23
  • m stands for minutes. value boundary: 0 <= m <= 59
  • s stands for seconds. value boundary: 0 <= s <= 59

Examples:

  • 2 days, 3 hours, 12 minutes, 23 seconds -> 2d3h12m23s or 02d03h12m23s
  • 48 hours -> 2d
  • 30 hours -> 1d6h
  • 300 seconds -> 5m
  • 320 seconds -> 5m20s
  • 60 seconds -> 1m

Delivery instruction

All delivery options:

delivery = {
    "smart": True/False,
    "success": "seen/interaction/<some-user-defined-success-event>",
    "time_to_live": "<TTL duration>",
    "mandatory_channels": [] # 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_valid_channels - 1))] apart.
    • Currently, channels are tried in low-to-high notification-cost order based on Notification Cost mentioned in Vendor Config. If cost is not mentioned, it is considered 0 for order-calculation purpose.
    • Process will continue until all channels are exhausted or success metric is achieved, whichever occurs first.
  • 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

{
    "smart": False,
    "success": "seen"
}

Add attachments

To add one or more Attachments to a Workflow/Notification (viz. Email), call Workflow.add_attachment(file_path) for each file with local-path. Ensure that file_path is proper, otherwise it will raise FileNotFoundError.

from suprsend import Workflow
workflow_body = {...}
wf_instance = Workflow(workflow_body)

# this snippet can be used to add attachment to workflow.
file_path = "/home/user/billing.pdf"
wf_instance.add_attachment(file_path)

Attachment structure

The add_attachment(...) call appends below structure to workflow_body->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.

Limitation

  • a single workflow body size must not exceed 200KB (200 * 1024 bytes). While calculating size, attachments are ignored
  • if size exceeds above mentioned limit, SDK raises python's builtin ValueError.

Batching Workflow Requests

You can batch multiple workflow requests in one call. Use workflow_batch.append(...) on batch-instance to add however-many-records to call in batch.

from suprsend import Workflow

batch_ins = supr_client.workflow_batch.new()

# one or more workflow instances
workflow1 = Workflow(body={...}) # body must be a proper workflow request json/dict
workflow2 = Workflow(body={...}) # body must be a proper workflow request json/dict

# --- use .append on batch instance to add one or more records
batch_ins.append(workflow1)
batch_ins.append(workflow2)
# OR
batch_ins.append(workflow1, workflow2)

# -------
response = batch_ins.trigger()

print(response)
  • There isn't any limit on number-of-records that can be added to batch-instance.
  • On calling workflow_batch.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 and chunk-length etc.
  • for each callable-chunk SDK makes an HTTP call to SuprSend To register the request.

Set channels in User Profile

If you regularly trigger a workflow for users on some pre-decided channels, then instead of adding user-channel-details in each workflow request, you can set those channel-details in user profile once, and after that, in workflow trigger request you only need to pass the distinct_id of the user. All associated channels in User profile will be automatically picked when executing the workflow.

  • First Instantiate a user object
distinct_id = "__uniq_user_id__"  # Unique id of user in your application
# Instantiate User profile
user = supr_client.user.new(distinct_id=distinct_id)
  • To add channel details to this user (viz. email, sms, whatsapp, androidpush, iospush etc) use user.add_* method(s) as shown in the example below.
# Add channel details to user-instance. Call relevant add_* methods

user.add_email("user@example.com") # - To add Email

user.add_sms("+919999999999") # - To add SMS

user.add_whatsapp("+919999999999") # - To add Whatsapp

user.add_androidpush("__android_push_fcm_token__") # - by default, token is assumed to be fcm-token

# You can set the optional provider value [fcm/xiaomi/oppo] if its not a fcm-token
user.add_androidpush("__android_push_xiaomi_token__", provider="xiaomi")

user.add_iospush("__iospush_token__")

user.add_slack_email("user@example.com")  # - To add Slack using email
user.add_slack_userid("U03XXXXXXXX")  # - To add Slack if slack member_id is known

# After setting the channel details on user-instance, call save()
response = user.save()
print(response)
# Response structure
{
    "success": True, # if true, request was accepted.
    "status": "success",
    "status_code": 202, # http status code
    "message": "OK",
}

{
    "success": False, # error will be present in message
    "status": "fail",
    "status_code": 500, # http status code
    "message": "error message",
}
  • Similarly, If you want to remove certain channel details from user, you can call user.remove_* method as shown in the example below.
# Remove channel helper methods
user.remove_email("user@example.com")
user.remove_sms("+919999999999")
user.remove_whatsapp("+919999999999")
user.remove_androidpush("__android_push_fcm_token__")
user.remove_androidpush("__android_push_xiaomi_token__", provider="xiaomi")
user.remove_iospush("__iospush_token__")

user.remove_slack_email("user@example.com")
user.remove_slack_userid("U03XXXXXXXX")

# save
response = user.save()
print(response)
  • If you need to delete/unset all emails (or any other channel) of a user, you can call unset method on the user instance. The method accepts the channel key/s (a single key or list of keys)
# --- To delete all emails associated with user
user.unset("$email")
response = user.save()
print(response)

# what value to pass to unset channels
# for email:                $email
# for whatsapp:             $whatsapp
# for SMS:                  $sms
# for androidpush tokens:   $androidpush
# for iospush tokens:       $iospush
# for webpush tokens:       $webpush
# for slack:                $slack

# --- multiple channels can also be deleted in one call by passing argument as a list
user.unset(["$email", "$sms", "$whatsapp"])
user.save()
  • Note: After calling add_*/remove_*/unset methods, don't forget to call user.save(). On call of save(), SDK sends the request to SuprSend platform to update the User-Profile.

Once channels details are set at User profile, you only have to mention the user's distinct_id while triggering workflow. Associated channels will automatically be picked up from user-profile while processing the workflow. In the example below, we are passing only distinct_id of the user:

from suprsend import Workflow

# Prepare Workflow body
workflow_body = {
    "name": "Purchase Workflow",
    "template": "purchase-made",
    "notification_category": "system",
    # "delay": "15m",
    "users": [
        {
            "distinct_id": "0f988f74-6982-41c5-8752-facb6911fb08",
        }
    ],
    # data can be any json / serializable python-dictionary
    "data": {
        "first_name": "User",
        "spend_amount": "$10",
        "nested_key_example": {
            "nested_key1": "some_value_1",
            "nested_key2": {
              "nested_key3": "some_value_3",
            },
        }
    }
}
wf = Workflow(body=workflow_body)
# Trigger workflow
response = supr_client.trigger_workflow(wf)
print(response)

Batch Users

You can batch multiple subscriber requests in one call. Use user_batch.append(...) on batch-instance to add however-many-records to call in batch.

batch_ins = supr_client.user_batch.new()
# Prepare multiple users
u1 = supr_client.user.new("distinct_id_1") # User 1
u1.set_email("u1@example.com")

u2 = supr_client.user.new("distinct_id_2") # User 2
u2.set_email("u2@example.com")

# --- use .append on batch instance to add one or more records
batch_ins.append(u1)
batch_ins.append(u2)
# OR
batch_ins.append(u1, u2)

# -------
response = batch_ins.save()
print(response)

Track and Send Event

You can track and send events to SuprSend platform by using supr_client.track_event method. An event is composed of an event_name, tracked wrt a user: distinct_id, with event-attributes: properties

from suprsend import Event

# Example
distinct_id = "__uniq_user_id__" # Mandatory, Unique id of user in your application
event_name = "__event_name__"   # Mandatory, name of the event you're tracking
properties = {} # Optional, default=None, a dict representing event-attributes

event = Event(distinct_id=distinct_id, event_name=event_name, properties=properties)

# Send event
response = supr_client.track_event(event)
print(response)
# Response structure
{
    "success": True, # if true, request was accepted.
    "status": "success",
    "status_code": 202, # http status code
    "message": "OK",
}

{
    "success": False, # error will be present in message
    "status": "fail",
    "status_code": 500, # http status code
    "message": "error message",
}

Batching events

You can batch multiple events in one call. Use event_batch.append(...) on batch-instance to add however-many-records to call in batch.

from suprsend import Event

batch_ins = supr_client.event_batch.new()
# Example
e1 = Event("distinct_id1", "event_name1", {"k1": "v1"}) # Event 1
e2 = Event("distinct_id2", "event_name2", {"k2": "v2"}) # Event 2

# --- use .append on batch instance to add one or more records
batch_ins.append(e1)
batch_ins.append(e2)
# OR
batch_ins.append(e1, e2)

# -------
response = batch_ins.trigger()
print(response)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

suprsend-py-sdk-0.1.5.tar.gz (30.1 kB view details)

Uploaded Source

Built Distribution

suprsend_py_sdk-0.1.5-py3-none-any.whl (33.8 kB view details)

Uploaded Python 3

File details

Details for the file suprsend-py-sdk-0.1.5.tar.gz.

File metadata

  • Download URL: suprsend-py-sdk-0.1.5.tar.gz
  • Upload date:
  • Size: 30.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.7.3

File hashes

Hashes for suprsend-py-sdk-0.1.5.tar.gz
Algorithm Hash digest
SHA256 9f2ee271eb5d105192747eeab168eb2309c2738ca6ff941ad924096333f65e2f
MD5 0400f6a28d1f482aa816631fe5b0e3cd
BLAKE2b-256 ad864c167f1a364fdb36e1907ea9f6326687fde2bd860a6681b63d2e36dfbf7b

See more details on using hashes here.

File details

Details for the file suprsend_py_sdk-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: suprsend_py_sdk-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 33.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.7.3

File hashes

Hashes for suprsend_py_sdk-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 beeff534d53276032a7ebdd580109eeb7b9ea3a7e74447caf52b33e48b8280df
MD5 732c332c95d642d1d3f094f682f59ace
BLAKE2b-256 4e10e0701bd0d0cc89c7ec9444bbc452493d038c16272bd002f6f866ee490635

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page