Agent skill
Stream Webhooks Skill
Receive and verify Stream (getstream.io) webhooks for Chat, Feeds and Video. Use when setting up Stream webhook handlers, debugging X-Signature verification, or handling events like message.new, message.updated, reaction.new, channel.created, user.updated, and member.added.
Install this skill
npx skills add hookdeck/webhook-skills --skill stream-webhooks
Stream here means Stream (getstream.io): Chat, Activity Feeds, Video and Moderation. It is not Bunny Stream (see bunny-stream-webhooks) or any other "Stream" product.
When to Use This Skill
- How do I receive Stream webhooks?
- How do I verify the Stream
X-Signatureheader? - How do I handle
message.new,reaction.newormember.addedevents? - Why is my Stream webhook signature verification failing?
- Why do Stream webhooks fail verification when Payload Compression is on?
Verification (core)
Stream signs the raw request body with HMAC-SHA256, keyed with your app's API secret (the full secret, used as a UTF-8 string), and sends the lowercase hex digest in X-Signature. There is no timestamp and no prefix in the header. Compare timing-safe.
const crypto = require('crypto');
function verifyStreamWebhook(rawBody, signature, apiSecret) {
if (!signature) return false;
const expected = crypto.createHmac('sha256', apiSecret).update(rawBody).digest('hex');
try {
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
} catch {
return false; // different lengths
}
}
import hmac, hashlib
def verify_stream_webhook(raw_body: bytes, signature: str, api_secret: str) -> bool:
expected = hmac.new(api_secret.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(signature or "", expected)
SDK option: every Stream server SDK can do this for you, e.g. client.verifyAndParseWebhook(rawBody, signature) (Node stream-chat / @stream-io/node-sdk) or verify_ (Python getstream). Keep a manual check like the above when you need to verify without a client, or in an edge function.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Payload Compression must be OFF (Hookdeck)
Stream's enable_ app setting gzips payloads (over 256 bytes). The signature is computed over the uncompressed bytes, so a verifier that sees the gzipped body fails, and Hookdeck's Stream source cannot verify compressed payloads. Apps created after May 7, 2026 have it on by default, so turn it off before pointing Stream at Hookdeck:
await client.updateAppSettings({ enable_hook_payload_compression: false });
If you receive webhooks directly and keep compression on, gunzip the body first (gzip magic bytes 1f 8b), then verify the HMAC on the decompressed bytes. The examples do this.
Common Event Types
| Event | Description |
|---|---|
message.new | A new message is added |
message.updated | A message is updated |
message.deleted | A message is deleted |
reaction.new | A reaction is added to a message |
channel.created | A channel is created |
user.updated | A user is updated |
member.added | A user is added to a channel |
For the full event list, see Stream webhook events.
Important Headers
| Header | Description |
|---|---|
X-Signature | Hex HMAC-SHA256 of the raw body, keyed with the app API secret |
X-Webhook-Id | Unique ID of the call; identical across retries, use it to dedupe |
X-Api-Key | Your app's API key (not the secret); check it matches your app |
X-Webhook-Attempt | Attempt number, starting at 1 |
Respond with a 2xx quickly. Stream retries immediately on network errors, 408, 429 and 5xx responses (up to 5 attempts within 15 seconds); other non-2xx responses are not retried.
Environment Variables
STREAM_API_SECRET=your_stream_app_api_secret # Dashboard > your app > API secret
STREAM_API_KEY=your_stream_app_api_key # Optional: checked against X-Api-Key
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 stream --path /webhooks/stream
Reference Materials
- references/overview.md - Stream webhook concepts and events
- references/setup.md - Configure the webhook URL and event types
- references/verification.md - Signature verification details and gotchas