Webhooks
PushTech can make an HTTP POST to your URLs when events occurs. If you would like Pushtech to POST event notifications, you need to configure a callback URL in the Webhooks section in your account.
Configuration
In Api section of your account, you can find the Webhooks section. In this section you will find where to add your Urls to use with the webhook events. The webhook events are organised by channel for the delivery messages or organised by type for the contact activities.
HTTP status code
For Webhook POSTs, Pushtech listens for the following codes from your server and reacts accordingly:
-
if Pushtech receives a
200 (Success)
code it will determine the webhook POST is successful and will not retry.
-
If Pushtech receives a
406 (Not Acceptable)
code, it will determine the POST is rejected and will not retry.
-
For any other code, Pushtech will retry POSTing according to the schedule below for Webhooks other than the delivery events.
if Pushtech receives a 200 (Success) code it will determine the webhook POST is successful and will not retry.
If Pushtech receives a 406 (Not Acceptable) code, it will determine the POST is rejected and will not retry.
For any other code, Pushtech will retry POSTing according to the schedule below for Webhooks other than the delivery events.
If your application is unable to process the webhook request but you do not return a 406 error code, Pushtech will retry (other than for delivery events) during 4 hours at the following intervals before stop trying: 5 minutes, 5 minutes, 10 minutes, 10 minutes, 30 minutes, 1 hour and 2 hours.
Securing Webhooks
To ensure the authenticity of each webhook requests, Pushtech signs them and posts the signature along with other webhook parameters:
Parameter | Type | Location | Description |
---|---|---|---|
Account id | string | Body parameter | String with your account ID |
timestamp | int | Body parameter | Number of seconds passed since January 1, 1970. |
token | string | Body parameter | Randomly generated string with length 50. |
Authorization token | string | Authorization header | String with hexadecimal digits generate by HMAC algorithm. |
To verify the webhook is originating from Pushtech you need to:
-
Concatenate timestamp and token values.
-
Encode the resulting string with the HMAC algorithm (using your Account secret Key as a key and SHA256 digest mode).
-
Compare the resulting hexdigest to the Authorization token
-
Optionally, you can check if the timestamp is not too far from the current time.
Below is a PHP code sample used to verify the Authorization token:
function verify($account_secret_key, $token, $timestamp, $authorization) {
$data = $timestamp . $token;
return hash_hmac('sha256', $data, $account_secret_key) == $authorization;
}
And here’s a sample in Python:
import hashlib, hmac
def verify(account_secret_key, token, timestamp, authorization):
hmac_digest = hmac.new(key=account_secret_key,
msg='{}{}'.format(timestamp, token),
digestmod=hashlib.sha256).hexdigest()
return hmac.compare_digest(unicode(authorization), unicode(hmac_digest))
And here’s a sample in Ruby:
require 'openssl'
def verify(account_secret_key, token, timestamp, authorization)
digest = OpenSSL::Digest::SHA256.new
data = [timestamp, token].join
authorization == OpenSSL::HMAC.hexdigest(digest, account_secret_key, data)
end
Reference
Activities events
Parameter | Description |
---|---|
created_at | The activity created date |
_id | The activity id |
origin | The origin of metric. Values [api, sdk, campaign] |
type | Describe the activity type. Values: [event, update, custom ,open_app , uninstall_app, subscribe_push, unsubscribe_push, add_cart, remove_cart,product_view , product_refund, purchase_failed, gps_location , contact_status] |
event_type | Describe a type of event related with campaigns. Values [opened, delivered, clicked, unsubscribed, sent, failed] |
updated_field | The name of field updated, only available if type is 'update' |
updated_field_value | The value of updated field, only available if type is 'update' |
custom | The custom raw metric,only available if type is 'custom' and origin is 'sdk' |
custom_key | The key of custom metric,only available if type is 'custom' |
custom_value | The value of custom metric,only available if type is 'custom' |
old_status | The old status of contact, only available if type is 'contact_status' |
current_status | Contact status, only available if type is 'contact_status' |
contact[_id] | Id of the contact |
contact[user_id] | Custom user_id of the contact |
contact[device_id] | Associated device_id |
contact[name_first] | First name of the contact |
contact[name_last] | Last name of the contact |
contact[email] | Email of the contact |
contact[phone] | Phone number with country code of the contact |
app[_id] | Id of app,only available if origin is 'sdk' |
app[name] | Name of the app,only available if origin is 'sdk' |
app[icon] | Icon of the app,only available if origin is 'sdk' |
campaign[_id] | Id of campaign,only available if origin is 'campaign' |
campaign[name] | Name of campaign,only available if origin is 'campaign' |
product[UUID] | Uniquee identifier of product, only available if type related with purchase or product |
product[name] | Name of product, only available if type related with purchase or product |
product[price] | Price of product, only available if type related with purchase or product |
product[currency] | Currency of product, only available if type related with purchase or product |
Example of activity json:
{ "created_at":"2016-12-09T15:28:28Z", "_id":"584acd9c85216d892f000002", "origin":"campaign", "type":"event", "event_type":"sent", "contact": { "_id": "584acff2f92ea1bcf7000012", "user_id": "jhon_doe", "name_first": "Jhon", "name_last": "doe", "email": "Jhon.doe@cendyn.com", "phone": "+346xxxxxxxx", "device_id": "5848408485216d13d1000009" }, "campaign":{ "_id":"5848408485216d13d100000a", "name":"Welcome email" }, "timestamp":1481297309, "token":"9ykzr1m09d3jgq04k5j2htlf0rs7wy93rtniaes6v3lyk2scm7", "account_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
Delivery events
Parameter | Description |
---|---|
id | The delivery id |
created_at | The delivery created date |
updated_at | The delivery updated date |
channel | The delivery channel, Values : [sms, push, email] |
status | The status of delivery, Values : [none, queued, sent, deliverd, opened, clicked, rejected, undefined, undelivered, forbidden_country_code, failed, bounced, unsubscribed, dropped, complained] |
refunded | If true refunded the money in your account |
url | Url only available if status is clicked and represent the user url clicked |
campaign[_id] | Id of campaign, only available if delivery created in Pushtech.com Manager |
campaign[name] | Name of campaign, only available if delivery created in Pushtech.com Manager |
template[_id] | Id of template, only available if delivery created in Pushtech.com Manager and channel is email |
template[name] | Name of template, only available if delivery created in Pushtech.com Manager and channel is email |
template_data[sender] | Sender of email, only available if delivery created in Pushtech.com Manager and channel is email |
template_data[subject] | Subject of email, only available if delivery created in Pushtech.com Manager and channel is email |
template_data[content] | Content of sms or push message, only available if delivery created in Pushtech.com Manager and channel is push or sms |
template_data[reply_to] | Email to reply to, only available if delivery created in Pushtech.com Manager and channel is email |
landing_page_sms[_id] | Id of landing page, only available if delivery created in Pushtech.com Manager and channel is sms and contains a landing page link |
landing_page_sms[name] | Name of landing page, only available if delivery created in Pushtech.com Manager and channel is sms and contains a landing page link |
landing_page_sms[url] | Url of landing page, only available if delivery created in Pushtech.com Manager and channel is sms and contains a landing page link |
landing_page_push[_id] | Id of landing page, only available if delivery created in Pushtech.com Manager and channel is push and contains a landing page link |
landing_page_push[name] | Name of landing page, only available if delivery created in Pushtech.com Manager and channel is push and contains a landing page link |
landing_page_push[url] | Url of landing page, only available if delivery created in Pushtech.com Manager and channel is push and contains a landing page link |
channel_data | Data of delivery |
contact[_id] | Id of the contact, only available if campaign sent with Pushtech.com Manager |
contact[user_id] | Custom user_id of the contact |
contact[name_first] | First name of the contact, only available if campaign sent with Pushtech.com Manager |
contact[name_last] | Last name of the contact, only available if campaign sent with Pushtech.com Manager |
contact[email] | Email of the contact, only available if campaign sent with Pushtech.com Manager |
contact[phone] | Phone number with country code of the contact |
app[_id] | Id of app,only available if campaign sent with Pushtech.com Manager and channel is push |
app[name] | Name of the app,only available if campaign sent with Pushtech.com Manager and channel is push |
app[icon] | Icon of the app,only available if campaign sent with Pushtech.com Manager and channel is push |
device[_id] | Id of device,only available if campaign sent with Pushtech.com Manager and channel is push |
device[type] | type of the device (ios, android or web), only available if campaign sent with Pushtech.com Manager and channel is push |
device[device_push_token] | Push token of the device, only available if campaign sent with Pushtech.com Manager and channel is push |
Example of delivery json:
{ "id":"584acffdf92ea1e99a000001", "created_at":"2016-12-09T15:38:37Z", "updated_at":"2016-12-09T15:38:49Z", "channel":"EMAIL", "status":"delivered", "refunded":false, "url":null, "campaign":{ "_id":"5848408485216d13d100000a", "name":"Welcome" }, "template"{ "_id": "5848408485216d13d1000009", "name" : "Welcome" }, "template_data":{ "sender":"Cendyn CRM platform", "subject":"", "content":"", "reply_to":"" }, "channel_data":{ "3":"Jhon.doe@cendyn.com" }, "contact": { "_id": "584acff2f92ea1bcf7000012", "user_id": "jhon_doe", "name_first": "Jhon", "name_last": "doe", "email": "Jhon.doe@cendyn.com", "phone": "+346xxxxxxxx", "device_id": "5848408485216d13d1000009" }, "timestamp":1481297931, "token":"mcnwldwmullbg4wkcx33ewirm4kmi5vn1i9k30hob5vagdk69w", "account_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
Bulk contacts
Parameter | Description |
---|---|
contacts_valid_count | Number of contacts saved in Cendyn CRM |
contacts_failed_count | Number of contacts failed to save in Cendyn CRM |
failed_contacts | Array that contains failed contacts |
failed_contacts[contact] | Contact params of a particular failed contact |
failed_contacts[error] | Description because contact save failed |
valid_contacts | Array that contains a valid contacts with basic fields: _id, user_id, email, phone_countrycode , phone_number |
valid_contacts[_id] | Pushtech id of the contact |
valid_contacts[user_id] | User id of the contact |
valid_contacts[email] | Email of the contact |
valid_contacts[phone_countrycode] | Phone country code of the contact |
valid_contacts[phone_number] | Phone number of the contact |
Example of bulk json:
{ "contacts_valid_count":3, "contacts_failed_count":1, "failed_contacts":[ { "contact": { "name_first":"Doria", "name_last":"Leppiwell", "city":"Shajia’ao", "gender":"Female", "email":"badformat", }, "errors":["Email format not recognised"] } ], "valid_contacts":[ { "_id":"599bf99af70366f2be000001", "user_id":"1", "email":"dleppingwell0@mydomain.com", "phone_countrycode":"34", "phone_number":866666666 }, { "_id":"599bf99af70366f2be000002", "user_id":"3", "email":"kschapiro1@domain.gov", "phone_countrycode":34, "phone_number":566678888 }, { "_id":"599bf99af70366f2be000003", "user_id":"2", "email":"acasazza2@domainmarket.com", "phone_countrycode":34, "phone_number":877777777 } ], "timestamp":1503394216, "token":"2m93z8xw1ofoiy890xx23ql9ah0gz60t85nuc9wyshu5apjxtt", "account_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
Incoming SMS
Parameter | Description |
---|---|
id | The incoming sms identificator |
received_at | Date of received sms |
text | Message text |
from | Phone number that send this text message |
Example of incoming sms json:
{ "id": "599bf99af70366f2be000001", "received_at":"2018-01-23T15:38:37Z", "text":"This simple message text", "from":"346xxxxxxxx", "timestamp":1503394216, "token":"2m93z8xw1ofoiy890xx23ql9ah0gz60t85nuc9wyshu5apjxtt", "account_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
Contact Events
Parameter | Description |
---|---|
action | Define the action of contact event. Values: create, channel_subscription, update, destroy |
origin | Origin of event, Values: sdk, platform_individual, platform_bulk, validation, campaign |
origin_sdk | type of device (ios, android or web), only available if origin is sdk |
contact | Contact information like GET request, if action is create and origin is platform_individual |
contact[id] | Pushtech id of the contact |
contact[user_id] | User id of the contact |
contact[changes] | A JSON with keys of the changed field and the new value. Only available for the action update and origin platform_individual or sdk |
contact[contact_url] | An url to Get the full contact information by API. Only available for the action update and origin platform_individual or sdk |
contacts_ids | An array of contact_ids, only available if origin is platform_bulk |
user_ids | An array of user_ids, only available if origin is platform_bulk |
channel_subscription | Contact subscription information, if action is subscription |
channel_subscription[channel] | Channel name of subscription status |
channel_subscription[blacklisted] | If true this channel is blacklisted |
channel_subscription[origin] | origin of the event |
channel_subscription[date] | Date and Time when this event occured |
Example when a contact is created on the platform
{ "action": "create", "origin": "platform_individual", "contact": { "id": "5b6d50651a7e4ef63e000005", "name_first": "Jhon", "list_subscriptions": [], "name_last": "Doe", "phone_countrycode": "xx", "phone_number": "xxxxxxxxx", "user_id": xxx, "city": xxx, "gender": xxx, "country": xxx, "language": xxx, "facebook_id": xxx, "facebook_friends": xxx, "google_id": xxx, "twitter_id": xxx, "twitter_followers": xxx, "born_date": xxx, "email": "jhon.do3@cendyn.com", "gdpr_marketing_consent": true, "gdpr_accept_terms": true, "gdpr_date": 2018-07-09T15:28:28Z, "gdpr_remote_ip": xxxxxx, "gdpr_link_terms": xxxxxx, "gdpr_link_privacy": xxxxxx, "tags": [], "company_id": xxxx, "company_name": xxxx }, "timestamp": 1533890854, "token": "dtz2gbeqb556ayg2z9hwe4mgdn1or1qw7utaigiiaf8b9t5f1a", "account_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
Example when a contact changed subscription email channel by api
{ "action": "channel_subscription", "origin": "api", "contact_id": "5b6d96991a7e4e8ac8000128", "user_id":"6712", "subscription":{ "channel":"email", "blacklisted":true, "origin":"api" } "timestamp": 1533909631, "token": "gvqmo9vm671pf8cnp5iwnqiwtxw7csc6u8v1p8uukn23g4yjxc", "account_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
Example when a contact is updated on the platform
{ "action": "update", "origin": "platform_individual", "contact": { "id": "5b6d96991a7e4e8ac8000128", "user_id": "6712", "changes": { "city": "New York" }, "contact_url": "https://api.eu.cendyncrm.com/v2/account/5a9eb2cd1a7e4e6b6f000007/contact/5b6d96991a7e4e8ac8000128" }, "timestamp": 1533909631, "token": "gvqmo9vm671pf8cnp5iwnqiwtxw7csc6u8v1p8uukn23g4yjxc", "account_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
Example bulk contacts destroy on the platform
{ "action": "destroy", "origin": "platform_bulk", "contacts_ids": [ "5b6d96991a7e4e8ac8000002", "5b6d96991a7e4e8ac8000003" ], "users_ids": [ "9673", "8086" ], "timestamp": 1533908635, "token": "a8uau26zd3gqtkbh3m5wrp9ipac1fxjnsg4wsbg9xam6loadu9", "account_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }