of 3

Documentation

Unblu 7 (latest)

This article provides technical information for using webhooks with Unblu.

Webhooks are HTTP requests sent to a URL you specify when a particular event occurs. The request contains a JSON payload with information you can then use to react to that event.

For information on how to configure webhooks in the Account Configuration interface, see the relevant section of the Account Configuration interface guide.

The Web API and a complete list of webhooks are fully documented in the Web API reference.

Webhook registration

The Unblu collaboration server provides each account with the possibility to add webhook registrations. A new registration can be added via either the user interface or a REST call.

Each registration consists of:

  • A name

  • A description

  • An endpoint

  • The Web API version

  • The events to receive

  • An optional secret

Bots and external messengers can also be thought of like webhook registrations. They share the same attributes, and their implementation also consists of sending webhook events.

Endpoint

The endpoint is the full destination address that Unblu will send webhook events to, for example, https://my.endpoint.com/unblu-webhooks. You must ensure that the endpoint is reachable from the Unblu collaboration server. The endpoint must support the POST method. If a proxy is required to access the endpoint, you must set the configuration property com.unblu.webhook.proxyUrl accordingly.

Web API version

Some event types are present in multiple versions of the Web API. The structure of the message body can change between API versions. For example, attributes may be added or removed.

For webhook events defined in multiple API versions, you should specify which version of the Web API to use when you register the webhook. This can be useful to ensure backward compatibility.

Event types

Unblu allows you to specify which events should be delivered to the endpoint. For more information, see the Unblu web API.

Secret key

To ensure that any webhook event is really sent by Unblu, you can configure a secret key.

If you include a secret key in your webhook registration, Unblu generates an SHA1 HMAC of the outgoing body content using this secret key and adds it as the custom x-unblu-signature header of the webhook event it’s pushing.

You can verify a push came from the Unblu server by applying the SHA1 HMAC to the received raw request body and comparing it with the contents of the x-unblu-signature header. See Checking the signature for example code.

Using a secret key to verify the origin of a webhook’s origin is optional.

Status

The status of a webhook registration allows you to enable or disable webhook events being pushed to the endpoint.

The possible statuses are specified in the ERegistrationStatus enumeration. In the Account Configuration interface, the three statuses are displayed as

  • Enabled

  • Disabled

  • Auto disabled (unavailable)

Additionally, if an endpoint is not reachable for a specific amount of time (see auto inactivate timeout below), the Unblu server will automatically change the webhook status to Auto disabled (unavailable) to avoid trying to push events to dead endpoints.

When a webhook is deactivated, it must be reactivated by an admin via the UI or the Web API.

Realtime webhooks

Some webhooks require a quicker reaction from the system and are relevant only for a short period of time. Those events are considered "realtime" webhook events and use different configuration properties. At the moment, the realtime webhook events are the ones sent during onboarding, offboarding, and reboarding.

Webhook delivery

When a webhook event is triggered in the Unblu collaboration server, every webhook registration is checked to confirm that:

  1. The registration has subscribed to the triggered event.

  2. The registration status is active.

If both conditions are met, a new webhook event is generated for the configured endpoint and added to the outbound queue.

Delivery order

The outbound webhook queue is processed by several webhook workers. The number of workers is configurable.

For each webhook registration, webhooks are guaranteed to be delivered sequentially. Webhook events are delivered in the same order as they were generated to avoid concurrency issues. For example, you don’t want to receive a conversation change before the conversation is created.

You should therefore not receive more than one webhook push at a time.

If the delivery of a webhook fails (see the next section), subsequent events for the same webhook registration remain in the queue until the event is delivered successfully or becomes obsolete.

Delivery failures

A webhook delivery is considered successful only if the endpoint server answers with an HTTP 2XX status code within the request timeout (configurable with com.unblu.webhook.webhookRequestTimeout or com.unblu.webhook.realtimeRequestTimeout).

The HTTP response status codes 301, 302, 307, and 308 mean the request should be redirected to another endpoint.

All other HTTP response codes, as well as no response, are treated as delivery failures. In such cases, Unblu will try to deliver the event again using an exponential back off strategy:

  1. Retry after the initial retry interval (10s by default).

  2. If the retry fails, double the last retry time and retry again.

  3. Repeat step 2 until the max retry interval (3h by default) is reached and use this as the retry interval from now on.

  4. Repeat step 3 until the obsolete timeout (48h by default) is reached.

There will be no further attempts to deliver the event once a webhook request is obsolete.
webhook request retries

In addition to the obsolete timeout, there is an auto inactive timeout. When the latter timeout is reached, the status of the corresponding webhook registration is changed to Auto disabled (unavailable). All of the events pending for the webhook registration are removed. Nothing will be sent to the endpoint until an admin enables the webhook registration again.

webhook auto inactivate

During the attempts to recover from a delivery failure, subsequent events for the same webhook registration remain in the webhook queue. Once the delivery was successful, Unblu will resume processing the queued events, provided they haven’t already hit their obsolete timeout.

Change active webhook registrations

If one of the following properties of an active webhook registration is changed, all webhook events that were placed in the outbound queue for that registration before the change will be removed from the queue:

  • The endpoint

  • The event type (Note that this only holds true for webhook events in the outbound queue with event types that are no longer contained in the changed registration’s event types.)

  • The secret

Receiving Unblu webhooks

Headers

Each webhook delivery has the following headers:

  • User-Agent 'Unblu-Hookshot' by default, but configurable via the configuration property com.unblu.webhook.webhookRequestUserAgent

  • x-unblu-event The event type. Use this to filter and dispatch the incoming events.

  • x-unblu-version The Web API version (v2, v3). This defines what information is present in the body of the message. Attributes may change from one API version to the next.

  • x-unblu-event-id A unique ID for this webhook event. The ID stays the same for delivery retries of the same event.

  • x-unblu-retry-no In the case of retried deliveries, this indicates the retry number. This header is not present when an event is sent for the first time.

  • x-unblu-delivery A unique ID for this delivery. You should never receive two requests with the same delivery ID.

  • x-unblu-signature The SHA1 HMAC of the outgoing body content using the configured secret key as password. If no secret is defined this header is not present.

    For more information, see Checking the Signature.

Payload

The payload of all Unblu webhook events is in JSON format.

As a rule, all webhook events of one event type always contain the same data structure.

Some properties are common to every webhook event and to the individual data for each event type:

{
    "timestamp": 1494485391283,             // Unix time in ms when the event was generated
    "eventType": "chat_request.created",    // The event type
    "accountId": "wZvcAnbBSpOps9oteH-Oxw",  // The ID of the account the event originated from.
    ...                                     // individual event properties
}

For more information on the various event types and their payloads, see the Unblu web API.

Checking the signature

If your webhook registration included a secret key, you can compute the SHA1 HMAC signature of the delivery. This allows you to verify that the webhook delivery you received was sent by the Unblu collaboration server.

There are a lot of methods to compute the SHA1 HMAC signature. Choose the one best suited to your context, depending on the language and framework you are using.

The following example is written in Java using the commons-codec:commons-codec:1.14 library:

Listing 1. Checking a webhook
import java.util.Objects;

import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;

public class Check {

    /**
     * Checks the signature of the received message is correct or not
     * @param headerValue the value of the X-Unblu-Signature header
     * @param body the content of the POST request
     * @param secret the value of the secret configured in the Unblu server
     * @return if the signature is matching the expected one or not
     */
    public static boolean isSignatureCorrect(String headerValue, String body, String secret) {
        String signature = new HmacUtils(HmacAlgorithms.HMAC_SHA_1, secret).hmacHex(body);
        return Objects.equals(headerValue, signature);
    }
}

Here is an example with Node.js:

import { createHmac } from 'crypto';

// Given 'secret' containing configured value in the Unblu server
// Given 'req' the http-request object:
const signature = createHmac('sha1', secret).update(req.rawBody).digest('hex');
const isSignatureValid = (req.headers['x-unblu-signature'] != signature);

Best practices

There are several best practices you should adhere to when dealing with webhooks.

Think about which events you want to group together in one registration: All the events for a single registration are delivered sequentially. If you don’t need events to be delivered in order, you can also create several registrations for one endpoint. This allows you to group together the events you need delivered sequentially and handle other events in parallel.

Do the heavy lifting asynchronously: Try to keep the response time of your server as short as possible. Ensure that all heavy computation and I/O access is handled asynchronously. This allows Unblu to deliver its webhooks in a timely fashion and avoids the delivery being marked as failed due to a timeout.

Check the event type before accessing data: Make sure the event type of the push you received is the one you are expecting. This prevents your code from breaking if, for some reason, you receive an unexpected event.

Disable your webhook registration if you have planned downtime: If you know your server will be unavailable, disable the webhook registration. This ensures that the server doesn’t run into one failed delivery after another filling up the queue, It also prevents your server being flooded with events once it’s up again.

Check your webhook registration when you restart an endpoint system: When you restart a system that’s registered as the endpoint of a webhook, check that the webhook registration is active. If that’s not the case, either update the webhook registration or register a new webhook.

Once you have updated or created the webhook registration, check that the webhook works by sending a ping event.

Check whether you already received the webhook: To avoid processing a webhook event more than once, create a list of the last n calls and drop all requests with the same delivery id.

Think about when you want to fail a webhook delivery: If you require Unblu to retry delivering a webhook, don’t send a response with a 2xx status code. As long as the webhook endpoint doesn’t return a 2xx status code Unblu considers the delivery as failed and will retry sending it as described in the Delivery failures section.

If it’s okay to drop the webhook in your integration, make sure you catch any errors and return a 2xx status code.

Create a restore strategy that doesn’t rely on webhooks: If the system is down and Unblu can’t deliver a webhook, all the webhooks are cached and re-sent when the system is available again. The duration of the cache depends on the obsolete timeout configuration property: com.unblu.webhook.webhookObsoleteTimeout (48h by default). However, caching thousands of webhooks and then delivering them all when the other system is back up again often isn’t the best approach. Some webhooks may get lost, for example, if the obsolete timeout is exceeded, or if your system returns 2xx status codes even though it couldn’t properly process requests.

This means you always need a restore strategy that doesn’t rely on webhooks. Unblu provides REST API services for every webhook we send. Make sure your integration can synchronize its state using the Unblu web API upon startup and doesn’t rely on every single webhook being cached.

Troubleshooting webhooks

There are a number of simple ways to troubleshoot problems involving webhooks.

Ping event

After configuring your webhook, check if everything works by sending a ping event. You can do this either in the webhook UI or via a REST call using the webhook registration service.

See the relevant section of the Account Configuration interface guide on how to send a ping from the webhook user interface.

Webhook delivery log

If you have problems receiving webhook events or want to track what the server sent out to your endpoint, you can check the webhook delivery log. The delivery log lists the details of each webhook delivery, including the headers and payloads of both the request and response.

The Collaboration Server periodically deletes old webhook delivery log entries. By default, delivery log entries are kept for 7 days. The default cleanup interval is 1 hour. Both the cleanup interval and the persistence duration are configurable.

Unblu server log

If an endpoint is not reachable for a specific amount of time, the Unblu server will automatically change the webhook status to Auto disabled (unavailable) to avoid trying to push events to dead endpoints.

When this occurs, a warning is written in the Unblu collaboration server logs:

Listing 2. Log entry on webhook delivery timeout
WARN Deactivating webhook registration with id '<id of the webhook registration>' (status is changed to INACTIVE_UNAVAILABLE)

These log entries can be used to monitor the health of webhook registrations.

The log entry feature is available in Unblu version 6.17.0 and newer.

Preventing misuse of webhooks

Unblu doesn’t maintain a whitelist of valid webhook endpoints. A malicious user with administrator or superadministrator privileges could therefore potentially use webhooks to send HTTP requests to any system on your network. In the worst case, webhooks could thus be used for the following purposes:

  • Scan internal ports

  • Identify internal hosts

  • Access internal resources

The easiest way to mitigate this risk is only to send webhook events via a forward proxy.

com.unblu.webhook.proxyUrl=http(s)\://<URL>\:<port>

The forward proxy should then be configured to filter the requests in such a way that webhooks can’t be abused for the purposes listed above.