Webhooks Setup

LAST EDIT Mar 05 2021
This is an old version of the webhooks documentation. Please see Webhooks Overview page

By using webhooks, you can receive all events within your application. When configured, every event happening on Stream Chat will propagate to your webhook endpoint via an HTTP POST request.

Webhooks can help you migrate from a different chat provider to Stream without disruption, or to support complex notification mechanisms (e.g. sending an SMS to an offline user when a direct message is sent, etc.).

Webhook Requirements

Copied!

In order to use webhooks, the endpoint responding to the webhook event must:

  • Be reachable from public internet, tunneling services like Ngrok are supported
  • Respond with a 200 HTTP code in less than 3 seconds
  • Handle HTTP requests with POST body
  • Able to parse JSON payloads
  • Support HTTP/1.1

While not required, we recommend following these best-practices for production environments:

  • Use HTTPS with a certificate from a trusted authority (eg. Let's Encrypt)
  • Verify the "x-signature" header
  • Support Keep-Alive
  • Be highly available
  • Offload the processing of the message (read, store, and forget)

Configuration via CLI

Copied!
1
stream chat:push:webhook --url 'https://acme.com/my/awesome/webhook/handler/'
See the CLI introduction for more information on the Stream CLI.

Verify Events via X-Signature and X-Api-Key

Copied!

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.

1
2
// first argument is the request body as a string, second the signature header 
const valid = client.verifyWebhook(req.rawBody, req.headers['x-signature']);
1
2
3
4
5
6
7
8
9
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'])
1
2
3
4
5
6
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)
1
2
3
4
$client = new GetStream\StreamChat\Client("STREAM_API_KEY", "STREAM_API_SECRET"); 
 
// signature comes from the HTTP header x-signature 
$valid = $client->verifyWebhook($requestBody, $signature);
1
// at the moment we don't have a Java client for server side usage
1
2
3
4
client, _ := stream.NewClient(APIKey, []byte(APISecret)) 
 
// signature comes from the HTTP header x-signature 
isValid := client.VerifyWebhook(body, signature)
1
// at the moment we don't have a Swift client for server side usage
1
2
3
4
5
6
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.