Webhooks enable Help Scout to call a script on your server when one or more events have happened. Webhooks can be thought of as event listeners or push notifications.

Configuring webhooks can be done through the Help Scout user interface. Simply log in, click on Manage > Apps in the top header bar, then select the Webhooks app.

Available Events

Each request body uses the object format linked in the table below. All webhooks use the v2 payload unless otherwise specified in the webhook settings.

Since 1st May 2021 the v1 payload is deprecated and integrations should be migrated to use the new v2 payload.

Type Event Name Request Header v1 Request Body v2 Request Body
Conversation Assigned convo.assigned v1 Conversation object v2 Conversation object
Created convo.created v1 Conversation object v2 Conversation object
Deleted convo.deleted {id: id-of-convo-that-was-deleted} {id: id-of-convo-that-was-deleted}
Merged convo.merged v1 Conversation object v2 Conversation object
Moved convo.moved v1 Conversation object v2 Conversation object
Status Updated convo.status v1 Conversation object v2 Conversation object
Tags Updated convo.tags v1 Conversation object v2 Conversation object
Customer Reply convo.customer.reply.created v1 Conversation object v2 Conversation object
Agent Reply convo.agent.reply.created v1 Conversation object v2 Conversation object
Note Created convo.note.created v1 Conversation object v2 Conversation object
Customer Created customer.created v1 Customer object v2 Customer object
Updated customer.updated v1 Customer object v2 Customer object
Ratings Rating Received satisfaction.ratings v1 Rating object v2 Rating object
Beacon Chat Created beacon.chat.created Unsupported Chat object
Customer Replied beacon.chat.customer.replied Unsupported Chat object


Each webhook includes two Help Scout headers:

  • X-HelpScout-Event: Lists the event name for which this webhook event is being generated
  • X-HelpScout-Signature: The computed signature generated by Help Scout. Used to know if the request is valid or not.


Webhooks can be verified as coming from Help Scout by calculating a digital signature. Each webhook request contains an X-HelpScout-Signature header, which is generated using the given secret key, along with the json encoded payload data sent in the request.

To verify if the request came from Help Scout, compute the HMAC hash and compare it to the header value sent in the request. If the computed signatures match, you can be sure the request was sent from Help Scout.

Signatures are calculated based on the raw request body passed to your servers by Help Scout. This means that if non-ASCII characters are contained in the payload, you will need to calculate the signature based on the escaped, transliterated string passed to you by Help Scout. We recommend this as best practice in general, even for those primarily working with ASCII data.


define('WEBHOOK_SECRET_KEY', 'my-secret-key');

function isFromHelpScout($data, $signature) {
	$calculated = base64_encode(hash_hmac('sha1', $data, WEBHOOK_SECRET_KEY, true));
	return $signature == $calculated;

$data = file_get_contents('php://input');
if (isFromHelpScout($data, $signature)) {
	// do something

When using the Help Scout PHP library, this validation is automatically handled for you.


Thanks to our friends at Parse.com for the Ruby example below.

Thanks to Leo Arnold at Givve for sending us a nice Gist with a Ruby vulnerability fix.

#!/usr/bin/ruby -rrubygems
require 'base64'
require 'hmac-sha1' # gem install ruby-hmac
require 'rack/utils' # gem install rack

WEBHOOK_SECRET_KEY = "your secret key"

# Returns true if the webhook request is verified to have come from Help Scout.
# data       String  The data posted by Help Scout to the webhook.
# signature  String  Value for the http-x-helpscout-signature header.
def is_from_help_scout(data, signature)
  Rack::Utils.secure_compare(Base64.encode64("#{hmac.digest}").strip, signature.strip)

# Usage Example
signature = "+oNIxipGoqx4t2BmkBHbXKc6VHM="
data = '{"ticket":{"id":"1","number":"2"},"customer":{"id":"1","fname":"Jackie","lname":"Chan","email":"jackie.chan@somewhere.com","emails":["jackie.chan@somewhere.com"]}}'

puts "This request came from Help Scout:"
puts is_from_help_scout(data, signature)

And an updated ruby example using openssl (instead of hmac-sha1):

#!/usr/bin/ruby -rrubygems

require 'openssl'
require 'base64'
require 'rack/utils'

WEBHOOK_SECRET_KEY = "your secret key"

def is_from_help_scout?(data, signature)
  return false if data.nil? || signature.nil?
  digest = OpenSSL::HMAC.digest('sha1', WEBHOOK_SECRET_KEY, data)
  Rack::Utils.secure_compare(Base64.encode64("#{digest}").strip, signature.strip)

data = '{"ticket":{"id":"1","number":"2"},"customer":{"id":"1","fname":"Jackie","lname":"Chan","email":"jackie.chan@somewhere.com","emails":["jackie.chan@somewhere.com"]}}'
signature = request.headers['X-Helpscout-Signature'] # or use signature = 'I1KlvGppYqvFTJgJ9jezdQMDiyI=' which is an actual signature of the data above

puts "This request came from Help Scout:"
puts is_from_help_scout?(data, signature)


Thanks to one of our Help Scout customers for the following Node.js example.

/*jshint node: true */
'use strict';

var crypto = require('crypto'),
config = require('../lib/config').config;

module.exports = function(secret) {
    return function(req, res, next) {
        req.isHelpScout = false;

        var hsSignature = req.header('X-HelpScout-Signature');
        if (hsSignature) {
            req.hsHasher = crypto.createHmac('sha1', secret);
            req.on('data', function (chunk) {
            req.on('end', function() {
                var hash = req.hsHasher.digest('base64');
                req.isHelpScout = hash === hsSignature ? true : false;


A java example can be found in the Webhook.java class in the Help Scout Java library.


Anything returned in the body of the response will be discarded. In order to know the webhook was successful, an HTTP status code between 200 and 299 must be returned.

A status code of 410 will cause the webhook to get deactivated/deleted.

Any status code other than something between 200 and 299 or 410 is a failure of some kind. A failed event is retried up to 10 times (with an increasing timeout period in between each retry). If the event fails all 10 retries, it is discarded.

Webhooks are automatically deactivated if three or more events get discarded.

Note: The Agent Reply event will only return data for User-generated threads. Auto Reply messages are not included in this event.