Documentation Index
Fetch the complete documentation index at: https://docs.tryfltr.com/llms.txt
Use this file to discover all available pages before exploring further.
Webhook Security
FLTR signs every webhook with HMAC-SHA256 to prove authenticity.
X-FLTR-Signature: <hex-encoded-signature>
Verification
Always verify signatures before processing webhooks.
Python
import hmac
import hashlib
def verify_webhook(secret, signature, body):
expected = hmac.new(
secret.encode(),
body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# Usage
if not verify_webhook(WEBHOOK_SECRET, signature, request.body):
return {"error": "Invalid signature"}, 401
JavaScript
const crypto = require('crypto');
function verifyWebhook(secret, signature, body) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
if (!verifyWebhook(WEBHOOK_SECRET, signature, body)) {
return res.status(401).json({ error: 'Invalid signature' });
}
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
func verifyWebhook(secret, signature string, body []byte) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
expected := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(signature), []byte(expected))
}
Best Practices
Use HTTPS
FLTR only sends webhooks to HTTPS endpoints in production.
Verify Every Request
Never trust webhook payloads without signature verification.
Use Raw Body
Verify against the raw request body, not parsed JSON.
# ✅ Good
body = request.get_data()
verify_webhook(secret, signature, body)
# ❌ Bad
body = json.dumps(request.json) # May not match
Rotate Secrets
Rotate webhook secrets periodically (every 90 days).
Return 200 Quickly
Process webhooks asynchronously:
@app.route('/webhooks', methods=['POST'])
def webhook():
# Verify
if not verify_webhook(...):
return {}, 401
# Queue for processing
queue.enqueue(process_webhook, request.json)
# Return immediately
return {}, 200
Testing
Generate Test Signature
import hmac
import hashlib
import json
payload = {"event": "document.processed", "data": {}}
body = json.dumps(payload)
signature = hmac.new(
b'whsec_test_secret',
body.encode(),
hashlib.sha256
).hexdigest()
print(f"X-FLTR-Signature: {signature}")
Send Test Webhook
curl -X POST http://localhost:5000/webhooks \
-H "Content-Type: application/json" \
-H "X-FLTR-Signature: abc123..." \
-d '{"event":"document.processed","data":{}}'
Troubleshooting
Signature Mismatch
Common causes:
- Using parsed JSON instead of raw body
- Wrong secret
- Extra whitespace in body
- Character encoding issues
Debugging
Log both signatures:
print(f"Received: {signature}")
print(f"Expected: {expected}")
Compare byte-by-byte to find discrepancies.