A webhook allows you to be automatically notified when something happens in Front without having to constantly poll the API. For each event happening in Front, your webhook will receive a POST HTTP request with the event JSON representation in the request body.

Front offers two methods for configuring webhooks:

If you are building a partner integration available to all Front users, you should use application webhooks. The primary benefit of this method is that users of your integration will not have to configure the webhook themselves when they install your app. There is also less risk of disruption when using application webhooks, because rules can be accidentally deleted or re-arranged by other teammates. Application webhooks have access to events that occur in shared inboxes.

If you are not building a partner integration, you can choose whether to use application webhooks or rule webhooks. Front recommends using application webhooks whenever possible, but setting up rule webhooks can sometimes be all you need. Application webhooks require that you have a server ready to respond to the webhook event at the time of configuration. This is not required when you set up a webhook through rules, so you can get up and running without first setting up a server. In addition, rule webhooks have access to the scope in which the rule was created. If the rule was created in a private inbox, then the rule webhook will have access to events in that private inbox.

The following table summarizes the differences between application webhooks and rule webhooks:

Webhook typeRecommended for partner integrationsRecommended for intial testingBenefitsScope
Application webhooksYesOnce you have a server set up to respond to webhook eventsDoes not require the end user to configure the webhook through a rule when installing your app

Sends the full event payload
Shared inboxes
Rule webhooksNoYesAllows you to set up a webhook without having a server ready to respond during configuration, but would require users to configure the rule themselves if your app is ported to other Front instances

Sends an event preview. You can make a subsequent API call to retrieve the full event.
Private or shared inboxes (the scope applies to the specific inbox the rule is created in)

What events are not included in webhooks?

Webhooks alert you about most important events in Front. However, there are some events that webhooks do not apply to.

Webhooks exclude “mass action” events, such as:

  • Moving inbox content to another team
  • Mass updating inbox conversation statuses
  • Importing historical messages to a channel
  • Etc.

Configure Application Webhooks

Setup

Application webhooks are configured as features on the apps you create on the Developers page in Front. Refer to the Create, manage, and publish apps topic to learn how to create application webhooks.

📘

OAuth is required for published apps

If your webhook is part of an app that you are publishing on our App Store, you must add OAuth to the app so that customers can authorize that Front events be sent to your webhook from their instance.

Application webhook validation

In order to configure application webhooks in the Developer Settings as described in the Setup section, you need to have a server running which is able to respond to requests. When you attempt to save your webhook configuration (both on initial creation and on future updates), we will send the following notification to your webhook URL.

Header:

{
  'x-front-signature': <built from your application signing key>,
  'x-front-request-timestamp': <timestamp in milliseconds>,
  `x-front-challenge`: <random string>
}

Body:

{
  type: 'sync',
  authorization: {
    id: "cmp_abc" // company id you would see from /me
  }
}

Verifying integrity

These steps will allow you to verify that the incoming application webhook originated from Front:

  1. Concatenate the stringified timestamp from the x-front-request-timestamp header with a colon
  2. Convert the string from step 1 to a buffer
  3. Take the buffer from step 2 and concat it with the raw request body
    1. IMPORTANT: always operate on the raw request body to ensure signature stability
  4. Convert the concatenated buffer from step 3 to a string.
  5. Apply the hmac SHA256 algorithm using the token provided during webhook configuration as the key [output in base 64].
  6. Compare the result from step 5 to the string provided in the x-front-signature header.

Example implementations:

const baseString = Buffer.concat([Buffer.from(`${timestamp}:`, 'utf8'), buf]).toString();
const hmac = crypto.createHmac('sha256', token)
        .update(baseString)
        .digest('base64');
const fromFront = (hmac === signature);
from flask import Flask, request, abort
import hashlib
import hmac
from base64 import b64encode

@app.route('/appwebhook', methods=['POST'])
def handle_webhook():
    
    application_secret = 'YOUR_APPLICATION_SECRET_HERE'
    raw_body = request.data
    signature = request.headers.get("x-front-signature")
    x_front_challenge = request.headers.get('x-front-challenge')
    
    #Steps 1-5
    timestamp = request.headers.get("x-front-request-timestamp") + ":"
    buffer = timestamp.encode()
    concatenated = buffer + raw_body
    hashed = b64encode(hmac.new(application_secret.encode(), concatenated, hashlib.sha256).digest()).decode()
    
    #Step 6 and responding to the validation request
    if hashed == signature:
        return x_front_challenge, 200, {'Content-Type': 'text/plain'}
    else:
        abort(400, "Bad Request: validation failed")

Responding to the validation request

To successfully validate the request, your application webhook must reply:

  • Within 10s
  • With a status code 200
  • With one of the following content-type/body pairs:
    1. content-type=text/plain with the body being the value of x-front-challenge
    2. content-type=application/x-www-form-urlencoded with a challenge parameter: challenge=<x-front-challenge-value>
    3. content-type=application/json with the body: {"challenge": "<x-front-challenge-value>"}

If the response doesn’t meet the criteria above, the validation is considered failed. You cannot save your change to your webhookUrl if the validation fails.

Differentiating customer webhook requests

Application webhooks include an authorization object on the payload that allows you to determine the customer instance emitting the webhook. The ID of the customer is displayed in authorization.id. By recording this ID, you can map a Front company ID to your own customer ID. Every subsequent payload receive will continue to provide the authorization.id. All published webhooks require that your application define an OAuth client, which is where the customer ID is injected from.

👍

If you have an API token, you can request the ID of the customer using the API Token details endpoint.

Configure rule webhooks

Setup

For more information about how to enable and setup a rule webhook, please refer to our help center.

To quickly get started testing rule webhooks, you can use something like RequestBin or UltraHook to receive and explore webhook payloads.

Validating Data Integrity

For security reasons and since the rule webhook URL is open to the public, you should not trust any incoming requests that it receives. Each request we send to your rule webhook URLs will contain an X-Front-Signature header generated using the request body and your API Secret.

To validate that the data came from Front, you need to calculate the base64 encoded HMAC hash of the request body using the SHA1 algorithm and your API secret as the key. If the value matches the header's signature, you can be sure the request was sent from Front.

const crypto = require('crypto');
const apiSecret = 'YOUR_API_SECRET';

function validateFrontSignature(data, signature) {
    var hash = crypto.createHmac('sha1', apiSecret)
                     .update(JSON.stringify(data))
                     .digest('base64');

   return crypto.timingSafeEqual(Buffer.from(hash), Buffer.from(signature));
}
require 'openssl'
require 'Base64'

API_SECRET = 'YOUR_API_SECRET'

def validateFrontSignature(data, signature)
  Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), API_SECRET, data)).strip() == signature ? true : false
end
from flask import Flask, request, jsonify, abort
import hashlib
import hmac
import json
from base64 import b64encode

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    data = request.json
    signature = request.headers.get("x-front-signature")
    api_secret = "YOUR_API_SECRET_HERE"  
    computed_signature = b64encode(hmac.new(api_secret.encode(), json.dumps(data, separators=(",", ":"),ensure_ascii=False).encode(), hashlib.sha1).digest()).decode()
    if not hmac.compare_digest(computed_signature.encode(), signature.encode()):
        abort(400, "Bad Request: Signature verification failed")
    else:
        return jsonify({"status": "success"}), 200
        
if __name__ == '__main__':
    app.run(port=5000) 

You can get your API secret by completing the following steps:

  1. Click Settings in Front.
  2. Under Company, click App store.
  3. Search for the Webhooks app.
  4. On the Webhooks app details page, click Configure app.
  5. Click Copy underneath the API secret section to obtain your API secret.

Differentiating customer webhook requests

To determine which Front customer instance is emitting a rule webhook, provide each customer with a unique webhook address during setup.

Timeouts

Webhook requests issued by Front will time out after 5 seconds.

Retries

Application Webhooks

Application webhooks will retry up to 3 times when Front receives an error or otherwise unrecognized response from your server. If you suspect you missed data by sending a bad response and also missing the retry opportunities, consider polling the List events API endpoint to filter for Events which occurred during the time you missed data.

Rule Webhooks

At present, retries are not attempted in cases where Front is unable to send payloads to your rule webhook. If you suspect you missed data, consider polling the List events API endpoint to filter for Events which occurred during the time you missed data.