Configuring Webhooks

A developer tool for retrieving and storing data from a certain event.

A Webhook is a tool for retrieving and storing data from a certain event. They allow you to register an https:// endpoint where the event data can be stored in JSON. Webhooks allow developers to build apps that receive information, in near real-time, about events that happen in your Localize project. Webhooks require you to provide a URI endpoint where you want us to send information about the events that your application subscribes to. When the event happens we'll send a HTTPS POST request to your callback endpoint and your app can perform some action based on that event.

Configuration

Webhooks can be found in the Manage Project section of the dashboard.

Generate Key

First you'll need to generate a key for your webhook so that you will have a signature in the payload going to your endpoint.

  1. Click the Generate link.
  2. Your X-Localize-Signature key will be displayed, and you can copy the key for use in your code.
954

Add Webhook

  1. Navigate to the Webhooks page.
  2. Click the Add Webhook button.
  3. Enter the URL of your endpoint.
  4. Click Create webhook
299

Events

  • dictionary.update: This event is triggered whenever the active content in your account is modified. This means that whenever a phrase state changes, or a translation is added/removed, this event will fire. This event is not triggered when new phrases and content are found on your website, since this would not alter the contents of the dictionary file. If you move those phrases to active a new dictionary file may be generated, but it may not contain any content if those phrases do not yet have translations. The dictionary data which is sent via this webhook event is identical to what your website receives when translations are loaded.

Payload

The body of the request will depend on what event your application is listening for. The meta section will contain information about the event and the project.

{  
   "meta":{  
      "status":200,
      "success":true,
      "event":{  
         "time":"2015-11-21T00:18:03.776Z",
         "name":"dictionary.update"
      },
      "project":{  
         "key":"24Z63D69IuAe3",
         "name":"test2"
      }
   },
   "data":{  
      "dictionary":[  
         {  
            "_id":"gl",
            "source":"en",
            "pluralFn":"return n != 1 ? 1 : 0;",
            "dictionary":{  
               "#hello":"hieska"
            }
         },
         {  
            "_id":"ja",
            "source":"en",
            "pluralFn":"return 0;",
            "dictionary":{  
               "#hello":"origato mr robota"
            }
         },
         {  
            "_id":"en",
            "source":"en",
            "pluralFn":"return n != 1 ? 1 : 0;",
            "dictionary":{}
         },
         {  
            "_id":"outdated",
            "outdated":{}
         }
      ]
   }
}

Respond to a Webhook

Your application needs to respond with a 200 within 3 seconds in order to be marked as successful. Any response outside of the 200 range will let Localize know that you did not receive your webhook.

Security

All requests from Localize will have a signature header (X-Localize-Signature) which you can use to verify the validity of the request. The body of the request can be hashed with the webhooks key and then compared against the signature in the header.

Here are some examples of how you can verify the request in a few different languages.

// This key can be found in the webhooks section of the backend
  var WEBHOOK_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

  // The signature header that is accompanied with every webhook request
  var header = req.headers['x-localize-signature'];

  // If you are using a framework that parses the request body (i.e. expressjs)
  // you will need to call JSON.stringify() on the body, or use the raw body
  // via a middleware. For example,
  //
  // req.on('data', function(chunk) {
  //   req.rawBody += chunk;
  // });
  var data = req.rawBody || JSON.stringify(req.body);

  // Calculate the hmac
  var hmac = require('crypto').createHmac('sha1', WEBHOOK_KEY);

  hmac.setEncoding('hex');
  hmac.end(data, function() {
    var hash = new Buffer(hmac.read()).toString('base64');
    if (header === hash) {
      // The webhook is valid
    }
  });
<?php

  // This key can be found in the webhooks section of the backend
  define('WEBHOOK_KEY', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');

  // The signature header that is accompanied with every webhook request
  $header = $_SERVER['HTTP_X_LOCALIZE_SIGNATURE'];

  // The raw contents of the post body
  $data = file_get_contents('php://input');

  // Calculate the hmac
  $hmac = base64_encode(hash_hmac('sha1', $data, WEBHOOK_KEY, false));

  // Using a plain == operator is not advised. A method like hash_equals (PHP > 5.6) 
  // performs a "constant time" string comparison, which renders it safe 
  // from certain timing attacks against regular equality operators. 
  // If using a version of PHP less than 5.6, you can still 
  // implement a comparison function which mitigates timing attacks
  if (hash_equals($header, $hmac)) {
    // The webhook is valid
  }