Layer Webhooks Services
The Layer Webhooks services integrates with the Layer's services, allowing for event handling when messages and conversations are created, deleted and changed. This node module is designed to work with express servers to quickly register and listen for events.
Installation
npm install layer-webhooks-services
Usage
There are two types of services provided by this module:
- Registering webhooks
- Listening for webhooks
Registering webhooks is an optional step, webhooks can also be registered from the Developer Dashboard.
Setup
The Layer Webhooks Service depends upon Kue for managing jobs spawned by receiving a webhook. It is backed by Redis, which is also used by the Receipts service. Initialization therefore will looks something like:
var redis = require('redis').createClient(process.env.REDIS_URL);
var queue = require('kue').createQueue({
redis: process.env.REDIS_URL
});
var WebhooksServices = require('layer-webhooks-services');
var lws = new WebhooksServices({
token: process.env.LAYER_BEARER_TOKEN,
appId: process.env.LAYER_APP_ID,
redis: redis
});
Note that Kue's createQueue
function returns a singleton; this first call, and its parameters, define
the singleton that will be used throughout this module.
Registering a webhook
var webhook = {
name: 'Webhook Example',
path: '/webhook_example',
events: ['message.sent']
};
lws.register({
secret: 'my secret',
url: 'https://mydomain.com/webhook',
hooks: [webhook]
});
Running the above code will cause one of two results:
- A webhook will be registered on Layer's servers telling it what events are of interest,
and what url to send those events to.
- If a webhook with the specified name already exists, the call to register will verify that the
webhook is active, and will activate it if needed.
Listening for a webhook
var kue = require('kue');
var queue = kue.createQueue();
var express = require('express');
var app = express();
var webhook = {
name: 'Webhook Example',
path: '/webhook_example'
};
lws.listen({
expressApp: app,
secret: 'my secret',
hooks: [webhook]
});
queue.process(webhook.name, function(job, done) {
var webhookEvent = job.data;
var message = webhookEvent.message;
console.log('Message Received from: ' + message.sender.user_id);
done();
});
The code above does two things:
- It sets up an endpoint listening for GET requests used by Layer's services to validate an endpoint. Validation is requried before Layer will start sending events to this service.
- It sets up an endpoint listening for events, and setting up a Kue process for you to handle those events.
Notes:
- If you use the
listen
method, it requires an Express App. - It is required that your Express server listens to secure SSL request i.e. use
HTTPS
. - The
path
property of your webhook definition is used to specify the path that the server will listen for requests at.
Combined Usage
While you can register a webhook on Layer's Developer Dashboard and only use listen()
, you can also use
the following combined usage:
var webhook = {
name: 'Webhook Example',
events: ['message.sent'],
path: '/webhook_example'
};
var secret = 'my secret';
lws.register({
secret: secret,
url: 'https://mydomain.com/webhook',
hooks: [webhook]
});
lws.listen({
expressApp: app,
secret: secret,
hooks: [webhook]
});
queue.process(webhook.name, function(job, done) {
var webhookEvent = job.data;
var message = webhookEvent.message;
console.log('Message Received from: ' + message.sender.user_id);
done();
});
Listening for Unread or Undelivered Messages
A common use case is to listen for Messages that have been unread or undelivered for some period of time and then notifying people that they have a message waiting for them (or that their message could not be delivered to all participants).
The receipts
operation provides shorthand for this. It is basically the same as the listen
operation, but supports parameters specific managing delayed testing of receipt status.
var webhook = {
name: 'Inline Receipts Demo',
path: '/receipts',
events: ['message.sent', 'message.read', 'message.delivered', 'message.deleted'],
receipts: {
delay: '10 minutes',
reportForStatus: ['sent', 'delivered'],
identities: false
}
};
var secret = 'my secret';
lws.register({
secret: secret,
url: 'https://mydomain.com/webhook',
hooks: [webhook]
});
lws.receipts({
expressApp: app,
secret: secret,
hooks: [webhook]
});
queue.process(webhook.name, function(job, done) {
var message = job.data.message;
var recipients = job.data.recipients;
console.log('Receipts Sample: The following users didn\'t read message ' + message.id + ' (' + message.parts[0].body + '): ');
console.log('Receipts Sample: RECIPIENTS: ' + recipients.join(', '));
done();
});
The Hook Definition
Each hook can have the following properties:
name
: This can be an arbitrary string; the name will be used to help identify a webhook so that only a single instance of this webhook is ever created.events
: An array of events that are of interest to our webhook. Refer to documentation for a list of all events.path
: The path is used both to tell Layer's servers where to send webhook events to, and tells the listen()
method where to listen for incoming events.
Initialization
new WebhooksServices(config)
Layer Webhooks services constructor is initialized with the following configuration values:
token
- Layer Platform API token which can be obtained from Developer DashboardappId
- Layer application IDredis
- Redis client instance
lws.register(options)
Register your webhooks with Layer's servers.
secret
: An arbitrary string you provide used to validate that events received by your server come from Layer's Servers, and not some unknown source.url
: When registering a webhook with Layer's services, the url
+ each webhook's path
property is used to tell the server where to send each event.hooks
: An array of Hook Definitions.
lws.listen(options)
Listen for incoming events from Layer's servers.
expressApp
: An expressjs application instance.secret
: An arbitrary string you provide used to validate that events received by your server come from Layer's Servers, and not some unknown source.hooks
: An array of Hook Definitions.
lws.receipts(options)
Listen for incoming events from Layer's servers, and trigger a job if after
a specified delay, there are recipients whose state matches your states
parameter.
This call uses the listen
operation, but has an extra receipts
parameter:
expressApp
: An expressjs application instance.secret
: An arbitrary string you provide used to validate that events received by your server come from Layer's Servers, and not some unknown source.hooks
: An array of Hook Definitions.
Custom Hook Parameters:
receipts
: Parameters specific to the receipts operation:
delay
: If its a number, then its the number of milliseconds to wait before creating the job for you to process. If its a string, then see this utility for how this is processed.reportForStatus
: Array of strings; this call should report on all recipients whose state matches any of the states you list. Possible values are 'sent', 'delivered', 'read'. ['sent'] will report on all recipients who are still in 'sent' state for triggering 'undelivered' processing. ['sent', 'delivered'] will report on all users who are either 'sent' OR 'delivered' meaning anyone who hasn't read the Message.identities
: If false, no identity data is loaded. If true, then any identity data registered with Layer's Identity Servers are returned (this generates additional network requests and may have impact on your service). If a function is provided, then you can
provide your own means of providing Identity data.
The identities
callback
Your identities
function takes a userId and a callback:
var hook = {
delay: '30 min',
identities: function(userId, callback) {
request(myUrl + userId, function(err, res, body) {
callback(err, body);
});
}
}
Webhook Events
Your callbacks will be called with Events objects provided by Layer Services. Make sure you read the Layer Webhooks Documentation to get more information.
Examples
There are a number of examples in the examples folder. You can run them all with npm start
, or just run the basic examples with npm run basic
.
Contributing
Layer API is an Open Source project maintained by Layer. Feedback and contributions are always welcome and the maintainers try to process patches as quickly as possible. Feel free to open up a Pull Request or Issue on Github.