Webhook Filtering — Complete Guide to Selective Delivery
In this tutorial, you will learn about Webhook Filtering. We cover key concepts, practical examples, and best practices to help you master this topic.
Webhook filtering selectively delivers events based on event type, payload content, or subscriber preferences, reducing unnecessary traffic and simplifying consumer integration.
What You'll Learn
- Filtering Webhooks by event type and payload
- Implementing subscriber-level filter preferences
- Using webhook filtering to reduce consumer load
Why It Matters
Without filtering, subscribers receive every event your system produces, overwhelming them with irrelevant data. Filtering lets consumers subscribe only to events that matter to them.
Real-World Use
Durga Antivirus Pro webhook system sends 50+ event types. Partners filter to receive only threat alerts relevant to their region and severity level, ignoring health checks and informational events.
flowchart LR
E["All Events"] --> F["Filter"]
F -->|"threat.identified"| S1["Security Partner"]
F -->|"scan.completed"| S2["Analytics Partner"]
F -->|"health.*"| S3["Monitoring"]
style F fill:#dbeafe,stroke:#2563eb
Code Examples
from flask import Flask, request, jsonify
app = Flask(__name__)
SUBSCRIBER_FILTERS = {
'partner_1': {'event_types': ['threat.identified', 'threat.updated'], 'severity': ['high', 'critical']},
'partner_2': {'event_types': ['scan.completed'], 'regions': ['us', 'eu']},
}
def should_deliver(subscriber_id, event):
filters = SUBSCRIBER_FILTERS.get(subscriber_id)
if not filters:
return False
if event['type'] not in filters.get('event_types', []):
return False
# Check content filters
severity = event.get('data', {}).get('severity')
if severity and severity not in filters.get('severity', [severity]):
return False
return True
def process_event(event):
for subscriber_id in SUBSCRIBER_FILTERS:
if should_deliver(subscriber_id, event):
deliver_webhook(subscriber_id, event)
Expected output: Events are filtered per subscriber; only matching events are delivered.
// Event type filtering system
class WebhookFilter {
constructor(rules) {
this.rules = rules; // { subscriber: { include: [], exclude: [], conditions: {} } }
}
matches(subscriber, event) {
const rule = this.rules[subscriber];
if (!rule) return false;
// Include/exclude event types
if (rule.include && !rule.include.includes(event.type)) return false;
if (rule.exclude && rule.exclude.includes(event.type)) return false;
// Content-based conditions
if (rule.conditions) {
for (const [key, value] of Object.entries(rule.conditions)) {
const actual = event.data[key];
if (Array.isArray(value) && !value.includes(actual)) return false;
if (actual !== value) return false;
}
}
return true;
}
}
const filter = new WebhookFilter({
'security-app': { include: ['alert.*'], conditions: { priority: 'high' } },
});
Expected output: Filter matches subscriber rules against event type and content conditions.
# Server-side webhook subscription with filtering
from flask import Flask, request, jsonify
app = Flask(__name__)
subscriptions = {}
@app.route('/api/webhooks/subscribe', methods=['POST'])
def subscribe():
data = request.json
subscription = {
'url': data['url'],
'filters': {
'event_types': data.get('event_types', ['*']),
'properties': data.get('filters', {}),
},
'active': True,
}
sub_id = generate_id()
subscriptions[sub_id] = subscription
return jsonify({'subscription_id': sub_id}), 201
def dispatch_event(event):
for sub_id, sub in subscriptions.items():
if not sub['active']:
continue
filters = sub['filters']
if '*' not in filters['event_types'] and event['type'] not in filters['event_types']:
continue
for key, value in filters.get('properties', {}).items():
if event.get('data', {}).get(key) != value:
break
else:
post_webhook(sub['url'], event)
Expected output: Subscribers register with filter preferences; events are dispatched only to matching subscribers.
Common Mistakes
1. No Default Filters
Sending all events to all subscribers by default overwhelms consumers. Default to minimal event set.
2. Filtering After Delivery
Checking filters after sending the webhook is wasteful. Filter before queuing delivery.
3. Overly Complex Filter Rules
Nested conditional filters become unmaintainable. Keep filters to event type and simple content matching.
4. Not Validating Filter Expressions
User-submitted filter expressions can cause errors. Validate and sandbox filter execution.
5. No Filter Audit Trail
When a subscriber misses critical events, they ask why. Log filter matches and rejections.
Practice Questions
- Why is webhook filtering important for consumers?
- What are two common filter dimensions for webhooks?
- How does filtering improve webhook delivery reliability?
- Why should filtering happen before queuing the delivery?
- What is the wildcard event type and how is it used?
Answers:
- It reduces irrelevant traffic, lowers processing load, and simplifies integration.
- Event type (order.created) and content attributes (severity: high).
- Less irrelevant traffic means fewer queue backlogs and lower delivery failure rates.
- Filtering before queuing prevents wasted storage and processing for undelivered events.
- The wildcard (*) matches all event types, used when a subscriber wants everything.
Challenge: Build a webhook filtering system where subscribers can register filters by event type and content conditions (e.g., price > 100, region = US). Implement server-side filtering and delivery.
FAQ
Mini Project
Build a webhook subscription API where subscribers can register URLs with filter rules (event types, minimum severity, specific regions). The dispatcher filters before delivery, logs filter decisions, and provides filter testing via a dry-run endpoint.
What's Next
Explore Webhook delivery guarantees for reliable event delivery, or read about Webhook security for securing filtered webhook endpoints.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro