Skip to content

Webhook Filtering — Complete Guide to Selective Delivery

DodaTech Updated 2026-06-28 4 min read

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

  1. Why is webhook filtering important for consumers?
  2. What are two common filter dimensions for webhooks?
  3. How does filtering improve webhook delivery reliability?
  4. Why should filtering happen before queuing the delivery?
  5. What is the wildcard event type and how is it used?

Answers:

  1. It reduces irrelevant traffic, lowers processing load, and simplifies integration.
  2. Event type (order.created) and content attributes (severity: high).
  3. Less irrelevant traffic means fewer queue backlogs and lower delivery failure rates.
  4. Filtering before queuing prevents wasted storage and processing for undelivered events.
  5. 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

Can webhook filtering be done at the API Gateway?

: Yes, gateways can filter by event type. Content-based filtering typically requires application-level logic.

How does webhook filtering affect delivery guarantees?

: Filtering does not affect guarantees; once matched, delivery follows standard retry and guarantee policies.

What is the performance impact of filtering?

: Minimal for type-based filtering. Content-based filtering requires payload Parsing but is still fast.

Can subscribers update their filters dynamically?

: Yes, provide an API endpoint for subscribers to update their filter preferences.

How do you handle filter validation errors?

: Return clear error messages during subscription setup; test filter rules with sample events.

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