Webhooks Overview

Last Edit: Jan 14 2021

By using webhooks, you can tightly integrate your server application with Stream Chat. The platform supports three kinds of webhooks: Push, Before-Message-Send, and Custom Commands. All of them follow the common set of rules:

  • Webhook should be reachable from the public internet. Tunneling services like Ngrok are supported

  • Webhook should accept HTTP POST requests with JSON payload

  • Webhook should respond with response codes from 200 to 299

  • Webhook should respond as fast as possible. The exact time given for the response varies between webhook types

  • Webhook should be ready to accept the same call multiple times: in case of network or remote server failure Stream Chat could retry the request (behavior varies between webhook types)

All webhook requests contain these headers:

Name Description Example
X-Webhook-Id Unique ID of the webhook call. This value in consistent between retries and could be used to deduplicate retry calls 123e4567-e89b-12d3-a456-426614174000
X-Webhook-Attempt Number of webhook request attempt starting from 1 1
X-Api-Key Your application’s API key. Should be used to validate request signature a1b23cdefgh4
X-Signature HMAC signature of the request body. See Signature section ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb

Security and Performance

We highly recommend following common security guidelines to make you webhook integration safe and blazing fast:

  • Use HTTPS with a certificate from a trusted authority (eg. Let's Encrypt)

  • Verify the "X-Signature" header

  • Support HTTP Keep-Alive

  • Be highly available

  • Offload the processing of the message if possible (read, store, and forget)

Webhook types

Stream Chat supports several webhook types:

Type Description
Push Push webhook is useful when you want your server application to receive all important events happening in the Stream Chat
Before Message Send This webhook allows you to modify or moderate message content before sending it to the chat for everyone to see
Custom Commands This webhook reacts to custom /slash commands
Please consult with corresponding pages to choose the webhook type that best fits your needs


All HTTP requests can be verified as coming from Stream (and not tampered by a 3rd party) by analyzing the signature attached to the request. Every request includes an HTTP header called "X-Signature" containing a cryptographic signature of the message. Your webhook endpoint can validate that payload and signature match:

// first argument is the request body as a string, second the signature header
const valid = client.verifyWebhook(req.rawBody, req.headers['x-signature']);

import stream_chat

client = StreamChat(api_key="STREAM_KEY", api_secret="STREAM_SECRET")

# Django request
valid = client.verify_webhook(request.body, request.META['HTTP_X_SIGNATURE'])

# Flask request
valid = client.verify_webhook(request.data, request.headers['X-SIGNATURE'])

require 'stream-chat'

client = StreamChat::Client.new(api_key='STREAM_KEY', api_secret='STREAM_SECRET')

// signature comes from the HTTP header x-signature
valid = client.verify_webhook(request_body, signature)

$client = new GetStream\StreamChat\Client("STREAM_API_KEY", "STREAM_API_SECRET");

// signature comes from the HTTP header x-signature
$valid = $client->verifyWebhook($requestBody, $signature);

client, _ := stream.NewClient(APIKey, []byte(APISecret))

// signature comes from the HTTP header x-signature
isValid := client.VerifyWebhook(body, signature)

using StreamChat;

var client = new Client("API KEY", "API SECRET");

// signature comes from the HTTP header x-signature 
client.VerifyWebhook(requestBody, signature);
If your application uses more than one API Key, you can use the HTTP Header X-Api-Key to match the signature to the correct secret. Stream will always use the most recently created API Key to sign payloads.


You can configure your webhook endpoints in the Stream Chat Dashboard or by using server-side SDK client:

// update webhook URLs
await client.updateAppSettings({
  webhook_url: "https://example.com/webhooks/stream/push", // sets Push webhook address
  before_message_send_hook_url: "https://example.com/webhooks/stream/before-message-send", // sets Before Message Send webhook address
  custom_action_handler_url: "https://example.com/webhooks/stream/custom-commands?type={type}", // sets Custom Commands webhook address

Also, webhooks could be configured using our CLI client:

stream chat:webhook:push --url 'https://example.com/webhooks/stream/push'
stream chat:webhook:before-message-send --url 'https://example.com/webhooks/stream/before-message-send'
stream chat:webhook:custom-commands --url 'https://example.com/webhooks/stream/custom-commands?type={type}'
See the CLI introduction for more information on the Stream CLI.