Webhooks

Webhooks allow you to subscribe to certain events happening at W3C. When one of these events is triggered, we'll send a HTTP POST payload to the webhook's configured URL.

You can configure your webhooks from your profile.

Events

When configuring a webhook, you can choose which events you would like to receive payloads for. You can change the subscribed events through the UI anytime.

Each event corresponds to a certain set of actions that can happen. For example, if you subscribe to the publication event you'll receive detailed payloads every time a technical report is published.

The available events are:

Name Description
Publication (tr.published, tr.updated) Any time a technical report is published or its metadata are updated
Group Participation (group.participant_joined, group.participant_left) Any time someone joins or leaves a group
Connected Accounts (connected_account.created, connected_account.deleted) Any time someone connects their W3C account to an external service such as GitHub, or removes such a connection

This list of events will be progressively augmented.

Headers and Payloads

HTTP requests made to your webhook's configured URL endpoint will contain several special headers:

Header Description
X-W3C-Webhook Link to the webhook that triggered the delivery
X-W3C-Webhook-Id ID of the webhook that triggered the delivery
X-W3C-Webhook-Signature-256 Signature of the payload, if a secret token was set. See below for more information
X-W3C-Webhook-Signature-256-Base64 Signature of the payload encoded in base64, if a secret token was set. See below for more information

Payload of HTTP requests consists in a JSON fragment including the event that triggered the webhook, the exact time when the request was made, and one or several objects serialized in the same way as the API.

Example delivery

URL: http://example.org/my-webhook
Host: example.org
X-W3C-Webhook: https://www.w3.org/users/12345/webhooks/1
X-W3C-Webhook-Id: 1
{
    "event": "tr.published",
    "microtime": 1661495980.622211,
    "specVersion": {
        "status": "Working Draft",
        "uri": "http://www.w3.org/TR/2016/WD-preload-20160120/",
        "date": "2016-01-20",
        "informative": false,
        "title": "Preload",
        "shortlink": "http://www.w3.org/TR/preload/",
        "editor_draft": "http://w3c.github.io/preload/",
        "process_rules": "http://www.w3.org/2015/Process-20150901/",
        "_links": {
            "self": {
                "href": "https://api.w3.org/specifications/preload/versions/20160120"
            },
            "editors": {
                "href": "https://api.w3.org/specifications/preload/versions/20160120/editors"
            },
            "deliverers": {
                "href": "https://api.w3.org/specifications/preload/versions/20160120/deliverers"
            },
            "specification": {
                "href": "https://api.w3.org/specifications/preload"
            },
            "predecessor-version": {
                "href": "https://api.w3.org/specifications/preload/versions/20160120/predecessors"
            }
        }
    }
}

Securing your webhooks

For security reasons, you probably want to limit requests to those coming from W3C. To do so you can set up a secret token and validate the information received.

Setting your secret token

When creating or editing a webhook, you can fill out the Secret textbox. You should use a random key with high entropy, for example by taking the output of LC_ALL=C tr -dc '[:alnum:]' < /dev/urandom | head -c20 from the terminal (on a GNU/Linux system).

Beware that once set, you won't be able to see this secret anymore. If you forget it, you will have to change it, which can be done when editing a webhook.

Validating payloads

When your secret token is set, W3C uses it to create a hash signature with each payload. This hexadecimal hash signature is included with the headers of each request as X-W3C-Webhook-Signature-256. We also send a Base 64 version of the signature as X-W3C-Webhook-Signature-256-Base64.

To verify that this signature is correct, and thus that it indeed came from W3C, you need to compute hash using an HMAC hex digest, with the SHA-256 algorithm, and then compare this hash with the signature.

Here is a sample PHP code exhibiting how to verify the signature:

<?php
$body = file_get_contents('php://input');
$secret = $_ENV['SECRET_TOKEN'];
$signature = hash_hmac('sha256', $body, $secret);
if (hash_equals($signature, $_SERVER['HTTP_X_W3C_WEBHOOK_SIGNATURE_256'])) {
   echo 'ok';
} else {
  http_response_code(403);
}

Your language and server implementations may differ from this example code. However, there are a few important things to point out: