Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
api-webhooks [2016/03/04 13:47]
ben
api-webhooks [2017/07/26 08:24] (current)
Line 1: Line 1:
 +===== Sentori Webhooks =====
 +
 +When a Contact [[api-webhooks#​contact-subscribe-webhook|signs up]], [[api-webhooks#​contact-unsubscribe-webhook|unsubscribes]],​ [[api-webhooks#​email-bounce-webhook|has a bounce logged against them]] or [[api-webhooks#​interactions-webhook|performs an interaction with one of your Emails]], you can have Sentori pass this information on to an external system, such as your CRM system, to keep everything in sync.
 +
 +===== Contact Subscribe Webhook =====
 +
 +Sentori calls this Webhook when a Contact signs up by clicking the Opt In Confirmation Link after submitting a Sentori Form, or when a User manually adds a single Contact.
 +
 +To use this feature, set the Contact Subscribe Webhook for your account by signing in to Sentori then going to the Settings menu and choosing API.
 +
 +Note: This Webhook is //not// called when uploading Contacts.
 +
 +==== Request ====
 +
 +This is how Sentori structures its request to your external system when a Contact subscribes:
 +
 +===HTTP Method: POST===
 +
 +===HEADERS===
 +|Content-Type|application/​json|
 +
 +===BODY===
 +|AccountExternalID|The External ID of the Account the Contact has subscribed to.|
 +|EmailAddress|The email address of the Contact that has subscribed.|
 +|Type|The string "​subscribe"​.|
 +|Date|The date and time when the sign up occurred. ​ Formatted to ISO 8601, e.g. "​2016-02-01T14:​12:​59.1230000Z"​|
 +|Source|Indicates how the Contact was subscribed. ​ If they signed up through a Sentori Form this will be the URL where the Form was hosted. ​ If a Sentori User created the Contact this will be the word "​User"​.|
 +|vhash|A hashed value used to confirm it's a genuine notification from Sentori.|
 +|Description|A human-readable message containing the other values.|
 +
 +==== Example Request from Sentori ====
 +Note the Source value of "​User",​ indicating the Contact was created by a User within Sentori.
 +<​code>​
 +POST [your webhook url] HTTP/1.1
 +Content-Type:​ application/​json
 +User-Agent: Sentori API
 +Content-Length:​ 314
 +
 +{
 +  "​AccountExternalID"​ : "​1234ABCD",​
 +  "​EmailAddress"​ : "​user@example.com",​
 +  "​Type"​ : "​subscribe",​
 +  "​Date"​ : "​2016-10-28T14:​59:​43.6889402Z",​
 +  "​Source"​ : "​User",​
 +  "​vhash"​ : "​EC0A73A0091CF860DCBD0B572CD8042A9B702D7B",​
 +  "​Description"​ : "​\"​user@example.com\"​ logged \"​subscribe\"​ Event at \"Fri 28 Oct 2016 14:59 UTC\"​."​
 +}
 +</​code>​
 +
 +==== Confirm the Request is Genuine ====
 +To confirm the request isn't from another system impersonating Sentori, perform the following operation.
 +
 +  - Concatenate the //​AccountExternalID//,​ //​EmailAddress//,​ //Type//, //Date//, //Source// values from the request (so exclude //​Description//​ and //vhash//) and your //API Key//
 +  - Convert the result into bytes
 +  - Get the SHA1 hash of those bytes and remove any hyphen characters
 +
 +If the result matches the //vhash// value in the request, it's genuine.
 +
 +\\
 +\\
 +
 +Here's the example above being checked using C# code:
 +
 +The API Key of this Sentori Account is "​20011111-1111-1111-1111-111111111200"​.
 +
 +<​code>​
 +string values = "​1234ABCD"​ + "​user@example.com"​ + "​subscribe"​ + "​2016-10-28T14:​59:​43.6889402Z"​ + "​User"​ + "​20011111-1111-1111-1111-111111111200";​
 +byte[] bytes = System.Text.Encoding.Default.GetBytes(values);​
 +System.Security.Cryptography.SHA1Managed sha1 = new System.Security.Cryptography.SHA1Managed();​
 +string checkHash = BitConverter.ToString(sha1.ComputeHash(bytes));​
 +checkHash = checkHash.Replace("​-",​ string.Empty);​
 +// Output is "​true"​ if genuine, "​false"​ if not.
 +Console.WriteLine("​Is genuine? " + ("​EC0A73A0091CF860DCBD0B572CD8042A9B702D7B"​ == checkHash));​
 +</​code>​
 +
 +\\
 +\\
 +
 ===== Contact Unsubscribe Webhook ===== ===== Contact Unsubscribe Webhook =====
  
-When a Contact ​unsubscribesyou can have Sentori pass this information on to an external system, such as your CRM system, to keep everything ​in sync.+Sentori calls this Webhook when a Contact ​becomes unsubscribedeither by the Unsubscribe link in an Email being clicked or a User manually unsubscribing them in Sentori.
  
 To use this feature, set the Contact Unsubscribe Webhook for your account by signing in to Sentori then going to the Settings menu and choosing API. To use this feature, set the Contact Unsubscribe Webhook for your account by signing in to Sentori then going to the Settings menu and choosing API.
  
 +Note: This Webhook is //not// called when uploading a Suppression List.
 ==== Request ==== ==== Request ====
  
Line 67: Line 146:
 </​code>​ </​code>​
  
 +\\
 +\\
 +
 +===== Mailing List Subscribe Webhook =====
 +
 +Sentori calls this Webhook when a Contact is added to a Mailing List, whether by a Contact performing an action or a User through Sentori'​s interface.
 +
 +Note: This Webhook is //not// called when uploading Contacts.
 +
 +==== Request ====
 +
 +This is how Sentori structures its request to your external system when a Contact is added to a Mailing List:
 +
 +===HTTP Method: POST===
 +
 +===HEADERS===
 +|Content-Type|application/​json|
 +
 +===BODY===
 +|AccountExternalID|The External ID of the Account this relates to.|
 +|EmailAddress|The email address of the Contact that has subscribed.|
 +|MailingListExternalID|The External ID of the Mailing List subscribed to.|
 +|Type|The string "​subscribe"​.|
 +|Date|The date and time when the operation occurred. ​ Formatted to ISO 8601, e.g. "​2016-02-01T14:​12:​59.1230000Z"​|
 +|vhash|A hashed value used to confirm it's a genuine notification from Sentori.|
 +|Description|A human-readable message containing the other values.|
 +
 +==== Example Request from Sentori ====
 +<​code>​
 +POST [your webhook url] HTTP/1.1
 +Content-Type:​ application/​json
 +User-Agent: Sentori API
 +Content-Length:​ 410
 +
 +{
 +  "​AccountExternalID"​ : "​1234ABCD",​
 +  "​EmailAddress"​ : "​user@example.com",​
 +  "​MailingListExternalID"​ : "​ABCD1234",​
 +  "​Type"​ : "​subscribe",​
 +  "​Date"​ : "​2016-10-28T14:​59:​43.6889402Z",​
 +  "​vhash"​ : "​EC0A73A0091CF860DCBD0B572CD8042A9B702D7B",​
 +  "​Description"​ : "​\"​user@example.com\"​ logged \"​subscribe\"​ Event for Mailing List \"​Members Offers\"​ (ExternalID:​ ABCD1234) at \"Fri 28 Oct 2016 14:59 UTC\"​."​
 +}
 +</​code>​
 +
 +
 +==== Confirm the Request is Genuine ====
 +To confirm the request isn't from another system impersonating Sentori, perform the following operation.
 +
 +  - Concatenate the //​AccountExternalID//,​ //​EmailAddress//,​ //​MailingListExternalID//,​ //Type//, //Date// values from the request (so exclude //​Description//​ and //vhash//) and your //API Key//
 +  - Convert the result into bytes
 +  - Get the SHA1 hash of those bytes and remove any hyphen characters
 +
 +If the result matches the //vhash// value in the request, it's genuine.
  
 \\ \\
 \\ \\
 +
 +Here's the example above being checked using C# code:
 +
 +The API Key of this Sentori Account is "​20011111-1111-1111-1111-111111111200"​.
 +
 +<​code>​
 +string values = "​1234ABCD"​ + "​user@example.com"​ + "​ABCD1234"​ + "​subscribe"​ + "​2016-10-28T14:​59:​43.6889402Z"​ + "​20011111-1111-1111-1111-111111111200";​
 +byte[] bytes = System.Text.Encoding.Default.GetBytes(values);​
 +System.Security.Cryptography.SHA1Managed sha1 = new System.Security.Cryptography.SHA1Managed();​
 +string checkHash = BitConverter.ToString(sha1.ComputeHash(bytes));​
 +checkHash = checkHash.Replace("​-",​ string.Empty);​
 +// Output is "​true"​ if genuine, "​false"​ if not.
 +Console.WriteLine("​Is genuine? " + ("​0321B442144F3EF8663EF47D738E2EDEDEBDF73F"​ == checkHash));​
 +</​code>​
 +
 +\\
 +\\
 +
 +
 +===== Mailing List Unsubscribe Webhook =====
 +
 +Sentori calls this Webhook when a Contact is removed from a Mailing List, whether by a Contact performing an action (including Unsubscribing from the Account) or a User through Sentori'​s interface.
 +
 +Note: This Webhook is //not// called when uploading a Suppression List.
 +
 +==== Request ====
 +
 +This is how Sentori structures its request to your external system when a Contact is removed from a Mailing List:
 +
 +===HTTP Method: POST===
 +
 +===HEADERS===
 +|Content-Type|application/​json|
 +
 +===BODY===
 +|AccountExternalID|The External ID of the Account this relates to.|
 +|EmailAddress|The email address of the Contact that has unsubscribed.|
 +|MailingListExternalID|The External ID of the Mailing List unsubscribed from.|
 +|Type|The string "​unsubscribe"​.|
 +|Date|The date and time when the operation occurred. ​ Formatted to ISO 8601, e.g. "​2016-02-01T14:​12:​59.1230000Z"​|
 +|vhash|A hashed value used to confirm it's a genuine notification from Sentori.|
 +|Description|A human-readable message containing the other values.|
 +
 +==== Example Request from Sentori ====
 +<​code>​
 +POST [your webhook url] HTTP/1.1
 +Content-Type:​ application/​json
 +User-Agent: Sentori API
 +Content-Length:​ 414
 +
 +{
 +  "​AccountExternalID"​ : "​1234ABCD",​
 +  "​EmailAddress"​ : "​user@example.com",​
 +  "​MailingListExternalID"​ : "​ABCD1234",​
 +  "​Type"​ : "​unsubscribe",​
 +  "​Date"​ : "​2016-10-28T14:​59:​43.6889402Z",​
 +  "​vhash"​ : "​EC0A73A0091CF860DCBD0B572CD8042A9B702D7B",​
 +  "​Description"​ : "​\"​user@example.com\"​ logged \"​unsubscribe\"​ Event for Mailing List \"​Members Offers\"​ (ExternalID:​ ABCD1234) at \"Fri 28 Oct 2016 14:59 UTC\"​."​
 +}
 +</​code>​
 +
 +==== Confirm the Request is Genuine ====
 +To confirm the request isn't from another system impersonating Sentori, perform the following operation.
 +
 +  - Concatenate the //​AccountExternalID//,​ //​EmailAddress//,​ //​MailingListExternalID//,​ //Type//, //Date// values from the request (so exclude //​Description//​ and //vhash//) and your //API Key//
 +  - Convert the result into bytes
 +  - Get the SHA1 hash of those bytes and remove any hyphen characters
 +
 +If the result matches the //vhash// value in the request, it's genuine.
 +
 +\\
 +\\
 +
 +Here's the example above being checked using C# code:
 +
 +The API Key of this Sentori Account is "​20011111-1111-1111-1111-111111111200"​.
 +
 +<​code>​
 +string values = "​1234ABCD"​ + "​user@example.com"​ + "​ABCD1234"​ + "​unsubscribe"​ + "​2016-10-28T14:​59:​43.6889402Z"​ + "​20011111-1111-1111-1111-111111111200";​
 +byte[] bytes = System.Text.Encoding.Default.GetBytes(values);​
 +System.Security.Cryptography.SHA1Managed sha1 = new System.Security.Cryptography.SHA1Managed();​
 +string checkHash = BitConverter.ToString(sha1.ComputeHash(bytes));​
 +checkHash = checkHash.Replace("​-",​ string.Empty);​
 +// Output is "​true"​ if genuine, "​false"​ if not.
 +Console.WriteLine("​Is genuine? " + ("​6769BC487AB5F54FE2AA5858FB6260FBFB0DD7A2"​ == checkHash));​
 +</​code>​
 +
 +\\
 +\\
 +
  
 ===== Email Bounce Webhook ===== ===== Email Bounce Webhook =====
  
-When a bounce occurs as a result of attempting to send an email to a Contact, you can have Sentori pass this information on to an external system, such as your CRM system, to keep everything in sync.+Sentori calls this Webhook when a bounce occurs as a result of attempting to send an email to a Contact.
  
 To use this feature, set the Email Bounce Webhook for your account by signing in to Sentori then going to the Settings menu and choosing API. To use this feature, set the Email Bounce Webhook for your account by signing in to Sentori then going to the Settings menu and choosing API.
Line 94: Line 317:
 |EmailAddress|The email address of the Contact the bounce relates to.| |EmailAddress|The email address of the Contact the bounce relates to.|
 |ContactMarkedBad|A true or false value indicating whether this bounce resulted in the Contact being marked as "​Bad"​ or not.| |ContactMarkedBad|A true or false value indicating whether this bounce resulted in the Contact being marked as "​Bad"​ or not.|
-|BounceMessage|The bounce ​message ​received by Sentori.|+|BounceType|Whether the bounce ​was Hard (a permanent delivery problem), Soft (a temporary delivery problem), or Spam (the receiving mail server didn't accept it as it appeared to be spam). ​ Hard bounces immediately mark a Contact as "​Bad"​. ​ Soft and Spam bounces add to a Contact'​s overall Bounce count and when Sentori has received ​enough of these will result in them being marked as "​Bad"​.| 
 +|BounceReason|Text briefly describing the problem indicated ​by the received bounce.|
 |Date|The date and time when this bounce message was received by Sentori. ​ Formatted to ISO 8601, e.g. "​2016-02-01T14:​12:​59.1230000Z"​| |Date|The date and time when this bounce message was received by Sentori. ​ Formatted to ISO 8601, e.g. "​2016-02-01T14:​12:​59.1230000Z"​|
 |vhash|A hashed value used to confirm it's a genuine notification from Sentori.| |vhash|A hashed value used to confirm it's a genuine notification from Sentori.|
Line 110: Line 334:
     "​EmailAddress":"​user@example.com",​     "​EmailAddress":"​user@example.com",​
     "​ContactMarkedBad":​true,​     "​ContactMarkedBad":​true,​
-    "BounceMessage":"​550 Invalid Recipient user@example.com", +    "BounceType":"​Hard",​ 
-    "​Date":"​2016-02-01T14:12:59.1230000Z",​ +    "​BounceReason":"​Email address does not exist", 
-    "​vhash":"​7D1CB46C9EAACEE2880F717B0088ACB25AEE3B3E", +    "​Date":"​2016-03-01T15:51:00.1230000Z",​ 
-    "​Description":"​Bounce logged for email address \"​user@example.com\"​ at "​Tue ​23 Feb 2016 11:58 UTC"​.\\n\\nThe Contact ​has been marked as having a Bad Email Address ​as a result ​of this Bounce.\\n\\n\Bounce Message: \"550 Invalid Recipient user@example.com\""+    "​vhash":"​1485836BE3A0908DC50A42CC22BB76340EF263C0", 
 +    "​Description":"​Bounce logged for email address \"​user@example.com\"​ at \"​Tue ​01 Mar 2016 15:51 UTC\"​.\\n\\nThe Contact ​HAS been marked as having a Bad Email Address ​due to the total number ​of Bounces logged.\\n\\nBounce Details:\\nHard\\nEmail address does not exist"
 } }
 </​code>​ </​code>​
Line 120: Line 345:
 To confirm the request isn't from another system impersonating Sentori, perform the following operation. To confirm the request isn't from another system impersonating Sentori, perform the following operation.
  
-  - Concatenate the //​AccountExternalID//,​ //​EmailAddress//,​ //​ContactMarkedBad//​ (converting it to a lowercase string, e.g. "​true"​ or "​false"​),​ //BounceMessage//, //Date// values from the request (so exclude //vhash// and //​Description//​) and your //API Key//+  - Concatenate the //​AccountExternalID//,​ //​EmailAddress//,​ //​ContactMarkedBad//​ (converting it to a lowercase string, e.g. "​true"​ or "​false"​),​ //BounceType//,​ //​BounceReason//, //Date// values from the request (so exclude //vhash// and //​Description//​) and your //API Key//
   - Convert the result into bytes   - Convert the result into bytes
   - Get the SHA1 hash of those bytes and remove any hyphen characters   - Get the SHA1 hash of those bytes and remove any hyphen characters
Line 134: Line 359:
  
 <​code>​ <​code>​
-string values = "​1234ABCD"​ + "​user@example.com"​ + true.ToString().ToLower() + "550 Invalid Recipient user@example.com" + "2016-02-01T14:12:59.1230000Z"​ + "​20011111-1111-1111-1111-111111111200";​+string values = "​1234ABCD"​ + "​user@example.com"​ + true.ToString().ToLower() + "Hard" + "Email address does not exist" + "2016-03-01T15:51:00.1230000Z"​ + "​20011111-1111-1111-1111-111111111200";​
 byte[] bytes = System.Text.Encoding.Default.GetBytes(values);​ byte[] bytes = System.Text.Encoding.Default.GetBytes(values);​
 System.Security.Cryptography.SHA1Managed sha1 = new System.Security.Cryptography.SHA1Managed();​ System.Security.Cryptography.SHA1Managed sha1 = new System.Security.Cryptography.SHA1Managed();​
Line 142: Line 367:
  
 // Output is "​true"​ if genuine, "​false"​ if not. // Output is "​true"​ if genuine, "​false"​ if not.
-Console.WriteLine("​Is genuine? " + ("7D1CB46C9EAACEE2880F717B0088ACB25AEE3B3E" == checkHash));​+Console.WriteLine("​Is genuine? " + ("1485836BE3A0908DC50A42CC22BB76340EF263C0" == checkHash));​ 
 +</​code>​ 
 + 
 + 
 + 
 + 
 +\\ 
 +\\ 
 + 
 +===== Interactions Webhook ===== 
 + 
 +Sentori calls this Webhook when a Contact first performs certain interactions with an Email (e.g. opens the email or clicks a link) you can have Sentori pass this information on to an external system that may perform additional tasks. 
 + 
 +At present, this is limited to External Link Clicks only. 
 + 
 +NOTE: Sentori will only call your webhook URL the first time each of your Contacts performs one of your selected interactions,​ not every time.  So (once we've implemented this webhook for Opens) if a Contact Opens your email 5 times, it would only be called for the first Open.  Each link is considered a separate interaction so it would be called the first time a Contact clicks each link in an Email. 
 + 
 + 
 +==== Request ==== 
 + 
 +This is how Sentori structures its request to your external system when a selected interaction occurs: 
 + 
 +===HTTP Method: POST=== 
 + 
 +===HEADERS=== 
 +|Content-Type|application/​json| 
 + 
 +===BODY=== 
 +|AccountExternalID|The External ID of the Account the interaction relates to.| 
 +|AccountName|The name of that Sentori Account.| 
 +|EmailExternalID|The External ID of the Email the interaction relates to.| 
 +|EmailName|The name of that Email.| 
 +|Type|The type of interaction,​ e.g. ExternalLinkClick.| 
 +|Value|A value giving more information about the interaction. ​ For an ExternalLinkClick,​ this is the URL of the link.| 
 +|Name|The name given to the item interacted with.  For an ExternalLinkClick,​ this is the Name/Title of the link.| 
 +|ContactSystemID|The SystemID of the Contact that performed the interaction.| 
 +|ContactEmailAddress|The EmailAddress of the Contact that performted the interaction.| 
 +|Date|The date and time when the interaction occurred. ​ Formatted to ISO 8601, e.g. "​2016-02-01T14:​12:​59.1230000Z"​.| 
 + 
 + 
 +==== Example Request from Sentori ==== 
 +<​code>​ 
 +POST [your webhook url] HTTP/1.1 
 +Content-Type:​ application/​json 
 +User-Agent: Sentori API 
 +Content-Length:​ 376 
 + 
 +
 +  "​AccountExternalID"​ : "​1234ABCD",​ 
 +  "​AccountName"​ : "My Account",​ 
 +  "​EmailExternalID"​ : "​S8JE72AD",​ 
 +  "​EmailName"​ : "​Newsletter",​ 
 +  "​Type"​ : "​ExternalLinkClick",​ 
 +  "​Value"​ : "​http://​website.co.uk/​homepage/#​info",​ 
 +  "​Name"​ : "​Website Homepage",​ 
 +  "​ContactSystemID"​ : 5841, 
 +  "​ContactEmailAddress"​ : "​user@example.com",​ 
 +  "​Date"​ : "​2016-08-04T09:​15:​28.1744295Z"​ 
 +}
 </​code>​ </​code>​