Webhooks

We can forward you events in real-time to a web page of your choosing, allowing you to integrate your own systems for processing or analytics. You can choose what events you are interested in, so you only receive the information you need.

Create a web page to receive data

Receive events

In order to setup a webhook registration, you must create a web page that the event data can be posted to. The web page has JSON data sent to it through HTTPS POST and is expected to return an appropriate HTTP status code such as an HTTP 200 - OK response if it successfully accepts the posted data.

The expected HTTP status codes are:

HTTP Status CodeTypeDescription
200, 201, 2XXOKData accepted.
401UnauthorizedIssue authenticating the sender, or HMAC not valid.
400Bad RequestCould not process the data sent; this will not be retried.
Any other-Failed to accept data, this will be retried.

Retry policy

If a failure occurs accepting data, or your server cannot be contacted, we use a gradual back off retry schema for up to 24 hours, and then move the event to the dead queue. This system ensures glitches and downtime do not result in data loss, though can cause delays.

The retry schedule is as follows:

  • 5 seconds
  • 5 seconds
  • 30 seconds
  • 30 seconds
  • 1 minute
  • 2 minutes
  • 5 minutes
  • 10 minutes
  • 15 minutes
  • 30 minutes
  • 1 hour
  • 2 hours
  • 4 hours
  • 4 hours
  • 4 hours
  • 4 hours
  • 4 hours

Event processing

Maximum permitted time

Your system is permitted 10 seconds to respond to a forwarded event before we consider the server unresponsive and the event send in error. We strongly recommend that your webhook reception page validates and then queues webhook events for processing, as the mechanism is designed for data exchange and 10 seconds is not enough time to reliably process events in.

Batch vs. single events

We can forward events either individually or as a batch of events. We strongly recommend that you design your webhook reception page to accept batches of events, as this greatly improves efficiency, especially during peak times.

Batches

Batches of events are a JSON array of individual webhook events.

1171

You can control the maximum amount of events in a batch as part of your webhook configuration, between 1—500, and the maximum amount of time we should wait before sending the batch of events, between 1—60 seconds.

We send the batch of events when either of the conditions below is met:

  • The batch is full; it hit the maximum number of events permitted.
  • The time since the last batch was sent has exceeded the batch timeout limit.

By tweaking the values for the batch timeout and maximum batch size you can finely tune the webhook between efficiency and responsiveness.

Single events

Each forwarded event is sent individually, and therefore at peak times your system must be able to accept many parallel calls.

{
  "eventId": "ca58832d-d67a-412e-9b28-e51b675ea142",
  "accountId": 123,
  "apiSpaceId": "c124df6e-4352-4b26-a32a-c3032bea7a01",
  "name": "message.sent",
  "payload": {
    "id": "ec7e182f-4d87-4135-b989-b26ab8d74f05",
    "details": {
      "channel": "sms",
      "additionalInfo": {
        "to": "441231123123",
        "successful": true
      },
      "channelStatus": {
        "sms": {
          "status": "sent",
          "details": {
            "to": "441231123123",
            "successful": true
          },
          "updatedOn": "2017-04-11T08:19:48.106Z"
        }
      }
    },
    "updatedOn": "2017-04-11T08:19:48.106Z"
  },
  "revision": 2,
  "etag": "\"2e-PNWSn3HlxaIB/CYz7LaR1XhMvDE\"",
  "timestamp": "2017-04-11T08:19:48.494Z"
}

[
  {
    "eventId": "ca58832d-d67a-412e-9b28-e51b675ea142",
    "accountId": 123,
    "apiSpaceId": "c124df6e-4352-4b26-a32a-c3032bea7a01",
    "name": "message.sent",
    "payload": {
      "id": "ec7e182f-4d87-4135-b989-b26ab8d74f05",
      "details": {
        "channel": "sms",
        "additionalInfo": {
          "to": "441231123123",
          "successful": true
        },
        "channelStatus": {
          "sms": {
            "status": "sent",
            "details": {
              "to": "441231123123",
              "successful": true
            },
            "updatedOn": "2021-04-11T08:19:48.106Z"
          }
        }
      },
      "updatedOn": "2021-04-11T08:19:48.106Z"
    },
    "revision": 2,
    "etag": "\"2e-PNWSn3HlxaIB/CYz7LaR1XhMvDE\"",
    "timestamp": "2021-04-11T08:19:48.494Z"
  },
  {
    "eventId": "1b4d4b5e-4176-4c91-a01c-3c927bd75a1a",
    "accountId": 123,
    "apiSpaceId": "c124df6e-4352-4b26-a32a-c3032bea7a01",
    "name": "message.sent",
    "payload": {
      "id": "fc1df0c5-35b8-4d34-bcc3-1994df7b6cdf",
      "details": {
        "channel": "sms",
        "additionalInfo": {
          "to": "44321321321",
          "successful": true
        },
        "channelStatus": {
          "sms": {
            "status": "sent",
            "details": {
              "to": "44321321321",
              "successful": true
            },
            "updatedOn": "2021-04-11T08:19:48.106Z"
          }
        }
      },
      "updatedOn": "2021-04-11T08:19:48.106Z"
    },
    "revision": 2,
    "etag": "\"2e-PNWSn3HlxaIB/CYz7LaR1XhMvDE\"",
    "timestamp": "2021-04-11T08:19:48.494Z"
  }
]

Event message structure

Each event is sent in a standard envelope message with a payload that is the actual event data.

The envelope format is:

PropertyTypeDescription
eventIdstringThe unique identifier for this event..
accountIdintThe account id the event is associated with
apiSpaceIdstringThe API space ID the event is from.
namestringThe name/type of the event being received.
payloadobjectThe specific event data.
revisionintThe revision number for the event which increments with each event.
etagstringThe ETag entity hash, commonly used for detecting change.
timestampdate timeThe UTC time the event occurred in ISO 8601 format.

The following is an example event you could receive:

{
  "eventId": "ca58832d-d67a-412e-9b28-e51b675ea142",
  "accountId": 123,
  "apiSpaceId": "c124df6e-4352-4b26-a32a-c3032bea7a01",
  "name": "message.sent",
  "payload": {
    "id": "ec7e182f-4d87-4135-b989-b26ab8d74f05",
    "details": {
      "channel": "sms",
      "additionalInfo": {
        "to": "441231123123",
        "successful": true
      },
      "channelStatus": {
        "sms": {
          "status": "sent",
          "details": {
            "to": "441231123123",
            "successful": true
          },
          "updatedOn": "2017-04-11T08:19:48.106Z"
        }
      }
    },
    "updatedOn": "2017-04-11T08:19:48.106Z"
  },
  "revision": 2,
  "etag": "\"2e-PNWSn3HlxaIB/CYz7LaR1XhMvDE\"",
  "timestamp": "2017-04-11T08:19:48.494Z"
}
{
  "eventId": "e8b015b0-dd11-4f2d-a4b8-52c20739e16b",
  "accountId": 123,
  "apiSpaceId": "c124cf6e-4352-4b26-a71a-c3032bea7a01",
  "name": "profile.create",
  "payload": {
    "id": "Bob Smith"
  },
  "revision": 0,
  "etag": "\"15-w27xhc3Oc4ZW/h3hpKppJQ88/rU\"",
  "timestamp": "2017-04-10T14:52:29.484Z"
}

📘

Testing

You can test receiving events by creating a request bin page for free, setting this as the URL for your webhook. Alternatively, if you want to receive the data to your development machine you can do this with NGROK.


Security

The following processing and guidance should be followed in order to ensure your webhook remains secure:

HTTPS recommended

We forward data to either HTTP or HTTPS URLs, but we recommend using HTTPS connections to ensure data privacy. Ensure your web page can accept HTTPS requests, and uses a certificate from a public certificate authority, as we cannot accept self-signed certificates.

Authenticating and verifying data

We use HMAC hashes to both authenticate and ensure the data has not been altered in transit.

We use the secret you configure on your webhook settings to create a hash of the event data (HTTP body) using the HMAC SHA-1 algorithm, and then store this in the request’s HTTP headers as X-Comapi-Signature.

When you receive data through your webhook page you must create a hash of the received request body using UTF-8 encoding with the SHA-1 algorithm and your secret, and then compare it against the received hash from the X-Comapi-Signature HTTP header. If they match you can trust the data, otherwise, you should reject the data and return a HTTP 401.

🚧

Ensure you calculate HMAC on the raw body

Many web frameworks give you access to a web request’s body data but after they have interpreted it, for example, created a object from JSON. Any change to the data at all causes the HMAC hash to differ, and therefore it is very important to calculate your HMAC on the raw HTTP body data.

Learn more in Receiving data using webhooks.

🚧

HMAC is not Base64 encoded

Some out of the box HMAC SHA-1 algorithms return the HMAC result Base64 encoded. You must be aware that we do not Base64 encode the HMAC result.

Revision processing

The Revision property increments for each message type, therefore giving you an indication of relative order. The sequence may not be contiguous, but always increments as more events are generated.

In some circumstances, the Revision property value can be used to recognise when it is safe to discard data, such as when you receive a message status update with a lower revision ID than the last one you processed for a message.

🚧

We do not guarantee events in the correct sequence

Due to the nature of large distributed systems, we cannot guarantee the order events are forwarded in exactly the chronological order they occurred in, which is why we provide the Revision property to help you sequence the events when you receive them.

Deduping

On rare occasions we can send an event more than once. This is called the at least once pattern. To avoid issues we recommend using the eventid to dedupe received events.


Receive data from a webhook

Configure forwarding

To setup or modify a webhook registration:

  1. Log in to the Portal.

  2. Go to Hub > Webhooks. Your configured webhooks are displayed.


  3. Select Add new Webhook.


    903

  4. In the popover, enter the following details:

    • Enter a Name for your webhook, for example, Analytics feed.
    • In the Target URL field, enter the URL for your webhook page.
    • Enter the Secret to be used to hash your events, so that you can verify that we sent the data and it hasn't been tampered with.
      Learn more in the section Security.
  5. Select the Send Batches of Events switch to send events in batches, or leave unselected to send individual events.


    We recommend batches. If enabled:

    • For Max Batch Size, enter the maximum number of events that can be in a batch.
    • For Batch Timeout (Seconds), enter the maximum time in seconds a batch waits before being sent.
  6. Select Next.


    907

  7. Select the checkbox for each event you want to receive. You can either choose one of the event templates such as Message events or select Advanced Options to configure your own event.

  8. Select Create.

🚧

Only take the events you need!

Only select the webhook events you need to maximise webhook performance and save your system having to process unnecessary events which take up resources.


👍

Quick starts

See our Receiving data using webhooks quick start for some example code for creating a webhook reception page.