Documentation & API

Event API

Overview

The Event API allows the users to setup web services that receive event notifications about their emails and their recipients from CritSend.

You can enable the Event API by specifying a target URL in the 'Event API' section under the 'Mail Settings' tab. In the same section, you will be able to choose which categories you want to enable (see the categories below).

An HTTP POST will be issued to the URL you've specified at a fixed interval (e.g. 5 minutes) with all the events we received in the meantime. The POST request payload describes the collection of events using the Webhooks model, and consists of a UTF8-encoded JSON array of JSON objects (events) in the following format:

[
    {
        "category": "hard_bounce",
        "date": "2011-09-02T14:39:53",
        "recipient": "recipient1@example.org",
        "mx": "example.com",
        "tags": ["default", "tag1"],
        "uid": "CC27F483098347ECB693EC7A1CAF45E9"
    },
    {
        "category": "blocked",
        "date": "2011-09-02T14:55:53",
        "recipient": "recipient2@example.org",
        "mx": "example.com",
        "tags": ["default", "tag2"],
        "uid": "A5DA637119D041BABAE316D3E908FF0A"
    },
    ...
]
					

While we will make a best effort to promptly deliver all the Webhooks events, messages may not arrive in order of commit. If we fail to reach the specified URL, we will retry several times over a 7-days period. This allows your services to be down for short maintenance windows and still receive all messages. Web services should respond to the POST request with a 2XX response code to indicate successful delivery. Redirects (3XX response codes) are not followed, and no further delivery attempts will be made. Server errors (5xx response codes) are treated as failures and will be retried. All other response codes are ignored.

Event API format

The payload's event JSON object contains the following items:

Field Type Description
category String The name of the event category. See the full list below.
date String The datetime the event happenned in ISO 8601 format (YYYY-MM-DDTHH:MM:SS).
diagnostic-code String The bounce's SMTP diagnostic code (e.g. 'x-unix; maildrop: maildir over quota.'). Only these categories include this field: bounce, blocked.
mx String The domain responsible for accepting the recipient's emails.
recipient String The recipient's email address.
status-code String The bounce's SMTP status code (e.g. '4.3.0'). Only these categories include this field: bounce, blocked.
tags Array An array containing the tags that the email is related with. Each tag's type is String.
uid String An alphanumeric string up to 100 characters containing the UID of the email (e.g. A650139AB25-4E13A10D349EF3712ACC).

The list of event categories is:

  • open: When the recipient opens an email. Counted only for HTML emails and image-view-enabled recipients.
  • click: When the recipient clicks a link in your email.
  • unsubscribed: When the recipient unsubscribed from your email traffic.
  • bounce: When we receive a bounce (either soft or hard) for an email of yours. Future emails to that address *will be* delivered.
  • hard_bounce: Deprecated in favor of 'bounce'.
  • soft_bounce: Deprecated in favor of 'bounce'.
  • blocked: When we receive a notification from a recipient's servers that an email of yours has been blocked for spam or content reasons. Future emails to that address *will be* delivered.
  • spam_report: When a user has reported an email of yours as Spam to an ISP within our Feedback Loop. Future emails to that address will *not* be delivered.
  • filtered: When we filter an email of yours and it is not sent out (due to various reasons like we have received too many permanent failures for the address or it has been unsubscribed or it has sent a spam report etc).
  • error: When there is an email's structure or other internal error.
  • new_failed_address: When we filter an email address after receiving too many permanent failures for it. Future emails to that address will *not* be delivered.
  • filtered_address: Deprecated in favor of 'new_failed_address'
  • blacklisted_address: When a user blacklists an address from here. Future emails to that address will *not* be delivered.
  • unblacklisted_address: When a user unblacklists an address from here. Future emails to that address *will be* delivered.
  • freed_address: When we remove an email address during our periodic failed addresses' assessment and cleanup procedure (failed addresses are those we have received too many permanent failures for). Future emails to that address *will be* delivered.
  • Note 1: The event's JSON representation fields should not be considered as fixed. Later on, new JSON fields may be added.

    Note 2: All deprecated events will stop being sent by 1st March 2013. Until then, we will send both the old (deprecated) and the new events.

    Errors: If there are errors decoding your tags or other you have returned you will recieve the following error in the form of JSON:

    [
        {
            "error": "Invalid Character",
        },
    ]
    			

Authentication

You will find your unique Webhooks 'secret key', in the 'Event API' section under the 'Mail Settings' tab. This key is used to seed the HMAC-SHA256 algorithm. Each POST request contains header called X-Critsend-Webhooks-Signature used to authenticate the payload. This header's value is a 64-character hexadecimal string. To verify the Webhook request is originating from CritSend you encode the payload with the HMAC-SHA256 algorithm (using your Webhooks 'secret key' as a key and SHA256 digest mode) and compare the resulting hexdigest to the X-Critsend-Webhooks-Signature header's value (signature).

Example in Python

import hmac, hashlib

def is_authenticated(your_webhooks_key, your_request_json_payload,
                    x_critsend_webhooks_signature):
    my_signature = hmac.new(key=your_webhooks_key,
                            msg=your_request_json_payload,
                            digestmod=hashlib.sha256).hexdigest()
    return x_critsend_webhooks_signature == my_signature
Authentication example in PHP:

function is_authenticated($your_webhooks_key, $your_request_json_payload,
            $x_critsend_webhooks_signature)
{
    $my_signature = hash_hmac("sha256", $your_request_json_payload, $your_webhooks_key);
    return $x_critsend_webhooks_signature == $my_signature;
}
				

Example in PHP

$our_webhooks_key = "xxxxxxxxxxxxxxx";
$critsend_signature = $_SERVER["HTTP_X_CRITSEND_WEBHOOKS_SIGNATURE"];
$json_payload = file_get_contents('php://input');

# Check if payload is valid
if($critsend_signature != hash_hmac("sha256", $json_payload, $our_webhooks_key))
  throw exception("Invalid payload according to our webhooks key");

$events = json_decode($json_payload);
foreach($events as $event)
{
  switch($event["category"])
  {
    case "open": event_open($event); break;
    case "click": event_click($event); break;
    case "unsubscribed": event_unsubscribe($event); break;
    case "hard_bounce": event_hard_bounce($event); break;
    case "soft_bounce": event_soft_bounce($event); break;
    case "blocked": event_blocked($event); break;
    case "spam_report": event_spam_report($event); break;
    case "filtered": event_filtered($event); break;
    case "error": event_error($event); break;
    default: throw exception("Invalid category");
  }
}