Web Hooks
Give Feedback

Plugin Hooks

Updated on November 14, 2022

Plugin Hooks can be used by developers of integrations (also called plugins) to receive real-time events from all Crisp websites that installed the plugin. For instance, you may want to get your plugin notified of messages sent by your website visitors, in real-time.

This guide explains how Plugin Hooks work, and how to get them to work with your integration. Plugin Hooks are available to all integrations created on the Crisp Marketplace.

Building an automation for your own private use? You could use the simpler Website Hooks instead.

What do Web Hooks do?

Plugin Hooks can be used to integrate with Crisp, and receive real-time events from Crisp on a custom HTTP endpoint, ie. on your own servers. Your endpoint will receive real-time events for all Crisp websites that installed your plugin.

This can be used in the following scenarios:

  1. Build a custom chatbot answering to messages
  2. Connect Crisp to another messaging platform
  3. Synchronize contacts to a custom CRM platform
  4. Etc. (you may come up with other scenarios)

How to Setup Plugin Hooks?

Plugin Hooks are configured from the Crisp Marketplace. Before you start, make sure you have an active integration on the Crisp Marketplace. If you do not already have a plugin, follow our guide to create one.

1. Prepare the receiving endpoint

To setup Plugin Hooks, you first need to setup a public HTTP endpoint, handling HTTP POST payloads. The endpoint can listen on any domain name / URL and can be hosted on your own servers.

Web Hooks delivered to your endpoint will come with a signature header. It is recommended that you use this header to verify that Web Hooks sent to your endpoint are genuine (ie. coming from Crisp), as an attacker may manage to discover your endpoint URL and forge rogue Web Hooks. You can read more about how to verify signatures.

For the safety of your data, you must use HTTPS over HTTP. HTTPS usage is mandatory on Plugin Hooks. Note that Crisp performs a strict certificate check, thus you must ensure your SSL/TLS certificate is valid; otherwise Web Hooks calls will fail.

2. Add your endpoint to your plugin

Once the endpoint is ready, create the Plugin Hooks configuration in the Crisp Marketplace:

  1. Go to the Crisp Marketplace and open navigate to your plugin
  2. Click on the Settings tab, and scroll down to the Events section
  3. Paste the URL of your Web Hook endpoint in the Development or Production section (you should use different endpoints for each)
  4. Hit the Create Web Hook button (a modal will open)
  5. Pick the event namespaces that you wish to subscribe to (please only pick the ones you expect, and not all of them)
  6. Copy your signing secret and use it to verify Web Hook signatures (this is not mandatory, but heavily recommended)
  7. Confirm your changes and finish creating the Web Hook
Note that if you're creating a production Web Hook, then it may need to go through a manual approval process. Based on the event namespaces you wish to receive, the approval might either be automated or require our team to intervene.
Create your production Web Hook
Configure your Web Hook
Your production Web Hook is pending approval

3. Check your new Web Hook

Now that your Web Hook is created and running, it's time to confirm it works properly.

Note that if your Web Hook configuration needs to go through Marketplace submission process, then it will not be working immediately, you will need to wait for the submission to be approved first.

When Crisp forwards an event to your Web Hook endpoint, it considers any HTTP 200 to HTTP 299 reply as successful. Other status codes are considered as failed (even redirect statuses).

To make it easy for you to debug, Crisp logs the status of the last call to your Web Hook (whether it succeeded or failed). You can check it out by refreshing your plugin settings on the Marketplace (see examples below).

Your production Web Hook was not called yet
The last call to your production Web Hook failed, check your backend or code

How to Handle Web Hook Events?

Web Hooks events come when a real-time event occurs in your Crisp website. Event payloads have the same data format as the RTM API.

You can use the free Webhook.site service to test receiving Web Hooks and see the JSON format, while you implement the handler in your code.

Receiving Web Hook payloads

Web Hook general format

A Web Hook HTTP POST body is JSON-encoded and formatted as such:

{
  "website_id" : "website_id",  // The Website ID the event occured in
  "event"      : "event",       // The event namespace (see list of events below)
  "data"       : "payload",     // The Web Hook payload (format depends on event namespace)
  "timestamp"  : "timestamp"    // The UNIX timestamp of the event (in milliseconds)
}

Web Hook example

For instance, a Web Hook on a visitor text message (message:send) may come on URL https://endpoint.example.com/crisp/hooks with body:

{
  "website_id": "42286ab3-b29a-4fde-8538-da0ae501d825",
  "event": "message:send",

  "data": {
    "website_id": "42286ab3-b29a-4fde-8538-da0ae501d825",
    "session_id": "session_36ba3566-9651-4790-afc8-ffedbccc317f",
    "type": "text",
    "content": "Hey :)",
    "from": "user",
    "origin": "chat",
    "stamped": true,
    "timestamp": 1506985696616,
    "fingerprint": 150698569649423,

    "user": {
      "nickname": "visitor493603",
      "user_id": "session_36ba3566-9651-4790-afc8-ffedbccc317f"
    }
  },

  "timestamp": 1506985696616
}

Receiving Web Hooks using a library

The most convenient way to receive Web Hooks is to use a Web Hooks-compatible library that we provide. Read our API Libraries guide to find a library for your programming language.

Let's provide an example on how you can receive Web Hooks in your code.

As we recommend using JavaScript to build integrations with Crisp, the example that follows will use the node-crisp-api library.

1. Import and configure the library

const Crisp = require("crisp-api");

// Create the Crisp client (it lets you access both the REST API and RTM events)
var CrispClient = new Crisp();

// Configure your Crisp authentication tokens ('plugin' token)
CrispClient.authenticateTier("plugin", "<token_identifier>", "<token_key>");

// Set current RTM mode to Web Hooks
CrispClient.setRtmMode(Crisp.RTM_MODES.WebHooks);

2. Start listening for events

// <previous code eluded>

CrispClient.on("message:send", function(message) {
  // Filter on text messages
  if (message.type === "text") {
    console.info(
      "Got text message from visitor with content:", message.content
    );
  }
});

3. Pass Web Hooks coming from HTTP to the library

const express = require("express");
const bodyParser = require("body-parser");

// <previous code eluded>

// Context
const app = express();
const port = 3997;

app.use(bodyParser.json());

// Handlers
app.post("/", (request, response) => {
  response.sendStatus(200);

  console.log(
    `<-- ${request.protocol}://${request.get("host")}${request.originalUrl}\n`,
    request.body
  );

  // -- (you may want to verify the Web Hook signature before accepting it) --

  // Receive Web Hook payload
  var error = CrispClient.receiveHook(request.body);

  if (error !== null) {
    console.error("Web Hook processing error", error);
  }
});

// Initializers
app.listen(port, () => {
  console.log(`Hooks server listening at http://localhost:${port}`);
});

A full working code example can be found at: node-crisp-api/examples/events_webhooks.js.


Verifying if a Web Hook is genuine with its signature

Web Hooks that are receiving by your server should be verified before being processed. Whenever you create a Plugin Hook, you will obtain a secret that you need to keep secure. This secret can be used to verify received Web Hooks.

The verification algorithm is described in the Web Hooks Reference.

Verify using a library

The most convenient way to verify Web Hook signatures is to use a Web Hooks-compatible library that we provide. Read our API Libraries guide to find a library for your programming language.

Let's provide an example on how you can verify Web Hook signatures in your code.

As we recommend using JavaScript to build integrations with Crisp, the example that follows will use the node-crisp-api library.
const express = require("express");
const bodyParser = require("body-parser");
const Crisp = require("crisp-api");

// Configuration
const SECRET = "<your_web_hooks_secret_here>";

// Create the Crisp client (it lets you access both the REST API and RTM events)
var CrispClient = new Crisp();

// Configure your Crisp authentication tokens ('plugin' token)
CrispClient.authenticateTier("plugin", "<token_identifier>", "<token_key>");

// Set current RTM mode to Web Hooks
CrispClient.setRtmMode(Crisp.RTM_MODES.WebHooks);

// -- IMPORTANT: you need to bind to some RTM events here with \
//      CrispClient.on(), otherwise the verifyHook() method will always return \
//      that signatures do not match! (because you are not even expecting the \
//      events that you receive over HTTP) --

// Context
const app = express();
const port = 3997;

app.use(bodyParser.json());

// Handlers
app.post("/", (request, response) => {
  response.sendStatus(200);

  console.log(
    `<-- ${request.protocol}://${request.get("host")}${request.originalUrl}\n`,
    request.body
  );

  let _timestamp = request.headers["x-crisp-request-timestamp"],
      _signature = request.headers["x-crisp-signature"];

  // Verify signature
  let _verified = CrispClient.verifyHook(
    SECRET, request.body, _timestamp, _signature
  );

  console.log(
    `${_signature} |remote| <- SIGNATURE -> |local| (hidden)`, _verified
  );
});

// Initializers
app.listen(port, () => {
  console.log(`Hooks server listening at http://localhost:${port}`);
});

Direct verification (no library)

If you wish to verify a Web Hook request without using a library, please refer to the Web Hooks Reference, which describes the verification algorithm.


Never miss an event with redeliveries

In real-world situations, delivery failures happen. Web Hooks are made reliable by being lenient to failure.

A typical failure case would be a short downtime on your end, as you might be restarting your server or deploying an update to your code.

If a Web Hook delivery attempt gets rejected by your server, then Crisp will try again later, multiple times. It will only drop the event if all delivery attempts failed, or if your server is too slow to respond.

Also, make sure that your server responds with an HTTP 200 success code immediately upon receiving a Web Hook. Endpoints that are too slow to respond might be considered by Crisp as failing, leading to a new delivery attempt. If you already processed the previous delivery attempt, then this would result in duplicates on your end, which is obviously not desired.

Note that if all delivery attempts for an event fail, then we will pause all Web Hook deliveries to your endpoint for about a minute. Deliveries will then be resumed the next time that your endpoint responds with HTTP 200. In that case, some events will never be received, so make sure that your endpoint is always reliable.

Information about the current delivery attempt, and the maximum number of attempts that will be made for a delivery, can be obtained from request headers using the following HTTP headers:

  • X-Delivery-Attempt-Limit
  • X-Delivery-Attempt-Count

Which Events Can I Receive?

You can find a list of events that can be handled, as well as examples, in the Web Hooks Reference. Look for Plugin Hooks in the support matrix.


Troubleshooting

If the last call to your Web Hook failed, or if you don't receive Web Hooks events, check the following:

  • Is the event namespace that you expect enabled for the Web Hook?
  • Is the plugin installed on the website you want to receive the event from?
  • Is your SSL/TLS certificate valid? (not expired, and matching the domain name)
  • Does the receiving server reply with a 200 status code?
  • Does the receiving server reply fast enough? (ie. less than 1 second)

Feel free to chat with us if you have any question, or if you cannot solve your issue. We'll gladly help you.