Application level webhooks

In addition to setting webhooks at the user level, you can set webhooks at the application level, meaning all of the users under your developer key will be covered under the same webhook. This means the same webhook rule will apply to all the users in your application.

FAQ

What is the difference between webhooks set at the user level vs. at the application level?

Webhooks set at the user level will only monitor that user, whereas webhooks set at the application level will take care of all of the users in the application's user base.

How do application level webhooks work?

With application level webhooks, you don't have to set a webhook for each of the users in your user base. If all webhooks for your users are going to be the same, setting a webhook at the application level will take care of your use case.

How long does it take for application level webhooks to come into effect?

Any users added after an application level webhook is set-up will be covered by the webhook immediately. It can take up to 24 hours for changes to take effect for users that were created before an application level webhook was set.

Supported methods

List methods:GETPOST

Instance methods:GETPOSTDELETE

Webhooks list

GET: Listing of webhooks

GET https://api.context.io/lite/webhookstest it

Response body

{
    "developerId": stringyour developer ID,
    "version": stringthe verison of the API this webhook applies to.,
    "callback_url": stringYour callback URL to which we'll POST message data,
    "failure_notif_url": stringYour callback URL for failure notifications,
    "active": booleanWhether this webhook is currently applied to new messages,
    "failure": booleantrue means we had issues connecting to the user and gave up after a couple retries. The failure_notif_url is called when a webhook's failure property becomes true.,
    "webhook_id": stringId of the webhook,
    "resource_url": stringComplete URL of the webhook,
    filter_*: stringValue of a filter assigned to this webhook when created
    ...
  },
  ...

POST: Create a new application level webhook

POST https://api.context.io/lite/webhookstest it

REMEMBER: webhooks set at the application level can take up to 24 hours to take effect for users created before the webhook was set.

Parameters

nametypedescription
required:
callback_urlstring
(url)
A valid URL Context.IO calls when a matching message is found.

The callback URL is called with an HTTP POST with message information in request body, see receiving webhook callbacks.
optional:
failure_notif_urlstring
(url)
A valid URL Context.IO calls if the WebHooks fails and will no longer be active. That may happen if, for example, the server becomes unreachable or if it closes an IDLE connection and we can't re-establish it.

The callback URL is called with an HTTP POST with more information in request body, see receiving failure notifications.
filter_tostringCheck for new messages sent to a given name or email address. Also accepts a comma delimited list of email addresses.
filter_fromstringCheck for new messages received from a given name or email address. Also accepts a comma delimited list of email addresses.
filter_ccstringCheck for new messages where a given name or email address is cc'ed. Also accepts a comma delimited list of email addresses.
filter_subjectstringCheck for new messages with a subject matching a given string or regular expression
filter_threadstringCheck for new messages in a given thread. Value must be a email_message_id of an existing message currently in the thread.
filter_file_namestringCheck for new messages where a file whose name matches the given string is attached. You can filter names using typical shell wildcards such as *, ? and [] or regular expressions by enclosing the search expression in a leading / and trailing /. For example, *.pdf would give you all PDF files while /\.jpe?g$/ would return all files whose name ends with .jpg or .jpeg
filter_folder_addedstringCheck for messages filed in a given folder. On Gmail, this is equivalent to having a label applied to a message. The value should be the complete name (including parents if applicable) of the folder you want to track.
filter_to_domainstringCheck for new messages sent to a given domain. Also accepts a comma delimited list of domains.
filter_from_domainstringCheck for new messages sent from a given domain. Also accepts a comma delimited list of domains.
include_bodyintegerSet to 1 to include message bodies in the result.
body_typestringUsed when include_body is set to get only body parts of a given MIME-type (for example text/html)
include_headermixedSet to 1 or raw to include message headers in the result.
receive_all_changesintegerSet to 1 to include all changes. A webhook with no filters will postback when a message first arrives. Use this parameter instead to send a postback for all message changes.
receive_historicalintegerSet to 1 to receive messages prior to account creation via a webhook. NOTE: Historical messages can only be received via webhook at account creation.

Response body

{
  "success": booleanWhether the operation worked,
  "webhook_id": stringId of the webhook that has been created,
  "resource_url": stringComplete URL of the new webhook
}

webhooks instance

GET: Properties of a given webhook

GET https://api.context.io/lite/webhooks/webhook_idtest it
webhook_idUnique id of the webhook instance.

Response body

{
    "developerId": stringyour developer ID,
    "version": stringthe verison of the API this webhook applies to.,
    "callback_url": stringYour callback URL to which we'll POST message data,
    "failure_notif_url": stringYour callback URL for failure notifications,
    "active": booleanWhether this webhook is currently applied to new messages,
    "failure": booleantrue means we had issues connecting to the user and gave up after a couple retries. The failure_notif_url is called when a webhook's failure property becomes true.,
    "webhook_id": stringId of the webhook,
    "resource_url": stringComplete URL of the webhook,
    filter_*: stringValue of a filter assigned to this webhook when created
    ...
  },
  ...

POST: Edit an existing webhook

POST https://api.context.io/lite/webhooks/webhook_idtest it
webhook_idUnique id of the webhook instance.

Parameters

nametypedescription
optional:
callback_urlstring
(url)
A valid URL Context.IO calls when a matching message is found.

The callback URL is called with an HTTP POST with message information in request body, see receiving webhook callbacks.
failure_notif_urlstring
(url)
A valid URL Context.IO calls if the WebHooks fails and will no longer be active. That may happen if, for example, the server becomes unreachable or if it closes an IDLE connection and we can't re-establish it.

The callback URL is called with an HTTP POST with more information in request body, see receiving failure notifications.
activeintegerThe active property of a WebHook allows you to pause (set to 0) or resume (set to 1) it.
filter_tostringCheck for new messages sent to a given name or email address. Also accepts a comma delimited list of email addresses.
filter_fromstringCheck for new messages received from a given name or email address. Also accepts a comma delimited list of email addresses.
filter_ccstringCheck for new messages where a given name or email address is cc'ed. Also accepts a comma delimited list of email addresses.
filter_subjectstringCheck for new messages with a subject matching a given string or regular expression
filter_threadstringCheck for new messages in a given thread. Value must be a email_message_id of an existing message currently in the thread.
filter_file_namestringCheck for new messages where a file whose name matches the given string is attached. You can filter names using typical shell wildcards such as *, ? and [] or regular expressions by enclosing the search expression in a leading / and trailing /. For example, *.pdf would give you all PDF files while /\.jpe?g$/ would return all files whose name ends with .jpg or .jpeg
filter_folder_addedstringCheck for messages filed in a given folder. On Gmail, this is equivalent to having a label applied to a message. The value should be the complete name (including parents if applicable) of the folder you want to track.
filter_to_domainstringCheck for new messages sent to a given domain. Also accepts a comma delimited list of domains.
filter_from_domainstringCheck for new messages sent from a given domain. Also accepts a comma delimited list of domains.
include_bodyintegerSet to 1 to include message bodies in the result.
body_typestringUsed when include_body is set to get only body parts of a given MIME-type (for example text/html)
include_headermixedSet to 1 or raw to include message headers in the result.

Response body

{
  "success": booleanWhether the operation worked,
  "resource_url": stringComplete URL of the webhook
}

DELETE: Cancel a webhook

DELETE https://api.context.io/lite/webhooks/webhook_idtest it
webhook_idUnique id of the webhook instance.

Response body

{
    "success": booleanWhether the operation worked
}

Receiving webhook callbacks

When an event matching the filters set for your webhook occurs in the mailbox, we do an HTTP POST request to your callback_url.

When you receive the POST request from our servers, it is important to respond to it with a 200 before doing any additional processing.

Request body

The body of this request is a JSON object which includes information about the webhook, a token and signature to validate its origin and information about the message that matched your webhook:

{
    "account_id": stringAccount who owns the webhook,
    "webhook_id": stringId of the webhook that has been triggered,
    "timestamp": numberServer time for the request as a Unix timestamp,
    "message_data": {
      "message_id": stringThe id id that should use to retrieve more information about the message from the lite API,
      "email_message_id": stringValue of RFC-822 Message-ID header,
      "addresses": objectEmail addresses and names of sender and recipients (more details),
      "person_info": objectAdditional info about contacts on this message (more details),
      "references": arrayList of email_message_ids that are in the same message thread,
      "date": numberUnix timestamp of message date,
      "subject": stringSubject of the message,
      "folders": arrayList of folders (or Gmail labels) this message is found in,
    },
    "token": stringRandom string used to calculate signature,
    "signature": stringHMAC-SHA256 hash of the timestamp and token with your Context.IO secret as the hashing key
}
Authenticating requests to your callback URL

You can validate that a request to your callback URL is a valid request from Context.IO using the combination of the timestamp, token and signature properties in the body. The signature is the HMAC-SHA256 hash of the string formed by concatenating the timestamp and token using your Context.IO OAuth secret as the hashing key.

Here's an example in PHP of how you would authenticate a request to your callback url:

<?php
// decode request body
$body = json_decode(file_get_contents('php://input'), true);

if ($body['signature'] == hash_hmac('sha256', $body['timestamp'].$body['token'], YOUR_CONTEXTIO_CONSUMER_SECRET)) {  
  // request is authenticated
}
else {  
  // invalid request, you can ignore it 
}
?>
Issues with Apache and mod_security

The mod_security module for Apache decided application/json is an exotic Content-type for the body of a POST request and rejects them by default, typically with a 406 status code. To avoid having Apache reject webhook callbacks, you need to either change default mod_security configs or disable it for your domain.

Accepting POST requests with application/json Content-type in mod_security

Change:

SecFilterSelective HTTP_Content-Type \
"!(^$|^application/x-www-form-urlencoded$|^multipart/form-data;)"

to:

SecFilterSelective HTTP_Content-Type \
"!(^$|^application/x-www-form-urlencoded$|^multipart/form-data;|^application/json$)"

[reference]

Accepting POST requests with application/json Content-type in mod_security 2

Change:

SecRule HTTP_Content-Type \
"!(^application/x-www-form-urlencoded|^multipart/form-data;).*$"

to:

SecRule HTTP_Content-Type \
"!(^application/x-www-form-urlencoded|^multipart/form-data;|^application/json).*$"

[reference]