Skip to main content

Building Bridges

This guide walks you through creating your first complete webhook automation workflow in Hooklistener. You'll learn how to connect a Source to Destinations using Bridges, creating an end-to-end webhook pipeline.

What You'll Learn

  • How to create a complete Bridge from scratch
  • How to use the visual Bridge Builder
  • How to connect Sources to multiple Destinations
  • How to test your Bridge before going live
  • Real-world Bridge examples

Prerequisites

Quick Start: Your First Bridge

Let's build a simple Bridge that receives webhooks from GitHub and sends them to Slack.

Step 1: Create the Bridge

  1. Log in to app.hooklistener.com
  2. Click "Bridges" in the sidebar
  3. Click "Create Bridge" button

Step 2: Name Your Bridge

GitHub to Slack Notifications

Use a name that describes the workflow: [Source] to [Destination] or [Purpose].

Step 3: Configure Source

Name: GitHub Events Type: Webhook

The Source URL will be generated automatically. You'll use this in GitHub webhook settings.

Step 4: Add Destination

Click "Add Destination":

Type: Slack Name: Slack #engineering Channel Webhook URL: {{SLACK_WEBHOOK_URL}}

(Make sure you've stored your Slack webhook URL in Secrets first)

Step 5: Save and Activate

  1. Click "Save Bridge"
  2. Copy the Source URL
  3. Configure it in GitHub (Repository → Settings → Webhooks)
  4. The Bridge is now active!

Step 6: Test

  1. Make a commit or open a PR in your GitHub repository
  2. Check EventsIncoming to see the webhook arrive
  3. Check EventsOutgoing to see delivery to Slack
  4. Verify message appears in your Slack channel

Congratulations! You've built your first Bridge.

Using the Visual Bridge Builder

The Bridge Builder provides a visual, drag-and-drop interface for creating complex workflows.

Accessing Bridge Builder

  1. Navigate to Bridges
  2. Click "Create Bridge"
  3. Select "Use Bridge Builder"

Bridge Builder Interface

Canvas: Main area where you design your workflow Components Panel: Available nodes (Source, Destinations, Transformations) Properties Panel: Configure selected components Toolbar: Save, test, and deploy controls

Creating a Bridge Visually

Step 1: Add Source Node

  1. Drag a Source node onto the canvas
  2. Click the node to open properties
  3. Configure:
    • Name
    • Authentication settings
    • Deduplication options

Step 2: Add Destination Nodes

  1. Drag Destination nodes onto the canvas
  2. Connect Source to each Destination by dragging from Source's output port
  3. Click each Destination to configure:
    • Name and type
    • URL and headers
    • Retry settings

Step 3: Add Filters (Optional)

  1. Click on a connection line (edge)
  2. Click "Add Filter"
  3. Configure filter conditions
  4. Webhook will only flow to that Destination if filters match

Step 4: Add Transformations (Optional)

  1. Click on a connection line (edge)
  2. Click "Add Transformation"
  3. Write JavaScript transformation code
  4. Test with sample payload

Step 5: Save and Deploy

  1. Click "Save" to save as draft
  2. Click "Test" to validate configuration
  3. Click "Activate" to start processing webhooks

Building a Multi-Destination Bridge

Let's build a more complex Bridge that routes webhooks to multiple destinations.

Scenario

Route payment webhooks from Stripe to:

  • Internal API (all payments)
  • Slack (high-value payments only)
  • Email alerts (failed payments only)

Bridge Configuration

{
"name": "Stripe Payment Router",
"source": {
"name": "Stripe Webhooks",
"type": "webhook",
"auth_type": "hmac_sha256",
"secret_header": "Stripe-Signature",
"secret_key": "{{STRIPE_WEBHOOK_SECRET}}"
},
"destinations": [
{
"name": "Internal API - All Payments",
"type": "http",
"url": "https://api.company.com/payments/webhook",
"headers": {
"Authorization": "Bearer {{INTERNAL_API_TOKEN}}"
},
"max_retries": 15
},
{
"name": "Slack - High Value Alerts",
"type": "slack",
"webhook_url": "{{SLACK_WEBHOOK_URL}}",
"filters": [
{
"body.type": { "$eq": "payment_intent.succeeded" }
},
{
"body.data.object.amount": { "$gte": 100000 }
}
]
},
{
"name": "Email - Failed Payments",
"type": "http",
"url": "https://api.company.com/alerts/email",
"filters": [
{
"body.type": { "$in": ["charge.failed", "payment_intent.payment_failed"] }
}
]
}
]
}

Step-by-Step Setup

1. Create Bridge:

Name: Stripe Payment Router

2. Configure Source:

Name: Stripe Webhooks
Authentication: HMAC-SHA256
Header: Stripe-Signature
Secret: {{STRIPE_WEBHOOK_SECRET}}

3. Add First Destination (Internal API):

Name: Internal API - All Payments
Type: HTTP
URL: https://api.company.com/payments/webhook
Headers:
Authorization: Bearer {{INTERNAL_API_TOKEN}}
Retries: 15
Filters: None (receives all webhooks)

4. Add Second Destination (Slack):

Name: Slack - High Value Alerts
Type: Slack
Webhook URL: {{SLACK_WEBHOOK_URL}}
Filters:
- body.type equals "payment_intent.succeeded"
- body.data.object.amount >= 100000

5. Add Third Destination (Email Alerts):

Name: Email - Failed Payments
Type: HTTP
URL: https://api.company.com/alerts/email
Filters:
- body.type in ["charge.failed", "payment_intent.payment_failed"]

6. Test:

  • Use Stripe's webhook testing tool
  • Send test webhooks for different scenarios
  • Verify routing to correct destinations

Common Bridge Patterns

Fan-Out Pattern

One webhook sent to multiple destinations:

GitHub Webhook → [Internal API, Slack, Discord, Database]

Use case: Notify multiple systems about the same event.

Implementation:

  • One Source
  • Multiple Destinations (no filters)
  • All destinations receive every webhook

Conditional Routing

Different webhooks to different destinations based on content:

Payment Webhook → High Value → Premium API
→ Normal Value → Standard API
→ Failed → Error Handler

Use case: Route based on priority, type, or content.

Implementation:

  • One Source
  • Multiple Destinations with different filters
  • Each destination receives matching webhooks only

Transformation Pipeline

Modify webhook format before delivery:

GitHub Webhook → Transform → Format for Jira → Jira API

Use case: Adapt webhook format between incompatible services.

Implementation:

  • One Source
  • Transformation on connection
  • Destination receives transformed payload

Aggregation Pattern

Combine notifications to different channels:

Build Status → Slack (all builds)
→ Discord (failures only)
→ Email (critical failures)
→ Telegram (personal alerts)

Use case: Multi-channel notifications with different filtering.

Implementation:

  • One Source
  • Multiple chat/notification Destinations
  • Different filters per channel

Testing Your Bridge

Pre-Deployment Testing

1. Validate Configuration

✓ Source URL is configured in webhook provider
✓ Authentication is set up correctly
✓ All destination URLs are valid
✓ Headers include required authentication
✓ Filters are tested with sample payloads
✓ Transformations produce expected output

2. Test Source

Send a test webhook:

curl -X POST https://api.hooklistener.com/api/v1/s/{source_id}/webhook \
-H "Content-Type: application/json" \
-d '{
"test": true,
"type": "test_event"
}'

Check Incoming Events to confirm receipt.

3. Test Destinations Independently

Before connecting to Bridge, test each destination:

curl -X POST https://api.example.com/webhooks \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"test": true}'

4. Test End-to-End

  1. Send real webhook from your service
  2. Monitor Events dashboard in real-time
  3. Verify:
    • Incoming Event appears
    • Outgoing Events created for each destination
    • All deliveries succeed
    • Filters work as expected
    • Transformations applied correctly

Testing Checklist

□ Source receives webhooks
□ Authentication works (if configured)
□ Deduplication works (if enabled)
□ Filters route correctly
□ Transformations produce expected output
□ All destinations receive webhooks
□ Response codes are 2xx
□ Retries work for failures
□ Circuit breakers respond to issues
□ Events are logged correctly

Monitoring Your Bridge

Real-Time Monitoring

Events Dashboard:

  • Watch incoming webhooks arrive
  • See outgoing deliveries in real-time
  • Filter by status (delivered, failed, pending)
  • Search event payloads

Bridge Health:

  • Overall success rate
  • Active circuit breakers
  • Retry queue depth
  • Average latency

Alerts

Set up alerts for:

  • High failure rate (>5%)
  • Circuit breaker opened
  • Unusual traffic patterns
  • Destination timeouts
  • Authentication failures

Key Metrics

Monitor these metrics:

  • Volume: Webhooks per hour/day
  • Success Rate: % delivered successfully (target: >99%)
  • Latency: Time from receipt to delivery (target: <2s)
  • Retry Rate: % requiring retries (target: <10%)
  • Failure Rate: % permanently failed (target: <1%)

Troubleshooting

Webhooks Not Being Received

Check Source:

  • Is the Source URL configured correctly in webhook provider?
  • Is the Bridge activated?
  • Check authentication settings
  • Review Incoming Events for rejected webhooks

Check Webhook Provider:

  • Are webhooks enabled?
  • Is the URL correct?
  • Are necessary events selected?
  • Check provider's webhook logs

Deliveries Failing

Check Destination:

  • Is destination endpoint accessible?
  • Test destination independently
  • Verify authentication headers
  • Check for rate limiting

Check Events:

  • Review outgoing event details
  • Check response status codes
  • Read error messages
  • Verify transformation output

Check Circuit Breaker:

  • Is circuit open?
  • Check failure count
  • Review recent errors
  • Reset if destination is fixed

Filters Not Working

Test Filters:

  • Use filter test endpoint
  • Verify field paths are correct
  • Check data types match
  • Test with actual webhook payload

Common Issues:

  • Incorrect field path (body.data.id vs body.id)
  • Case sensitivity
  • Data type mismatch ("100" vs 100)
  • Missing fields in some webhooks

Transformations Failing

Check Logs:

  • View transformation execution logs
  • Look for JavaScript errors
  • Check for timeout errors
  • Verify return statement

Test Separately:

  • Test transformation with sample payload
  • Check syntax in code editor
  • Verify expected output
  • Simplify if too complex

Best Practices

Design

  1. One workflow per Bridge

    • Keep Bridges focused on single purpose
    • Easier to manage and debug
    • Clearer metrics and monitoring
  2. Descriptive names

    • Include source and purpose
    • Specify environment
    • Make it searchable
  3. Separate environments

    • Different Bridges for dev/staging/prod
    • Prevent cross-contamination
    • Test safely before production

Configuration

  1. Test thoroughly

    • Test each component independently
    • Verify end-to-end flow
    • Use real webhook data
    • Test failure scenarios
  2. Use filters strategically

    • Filter early to reduce processing
    • Keep conditions simple
    • Document filter logic
  3. Configure retries appropriately

    • Critical: 15 retries
    • Important: 10 retries
    • Best-effort: 3-5 retries

Security

  1. Enable authentication

    • Always use signature verification in production
    • Rotate secrets regularly
    • Monitor auth failures
  2. Use secrets

    • Store all credentials in Secrets
    • Reference with {{SECRET_NAME}}
    • Never hardcode sensitive data
  3. Minimize data exposure

    • Use transformations to filter sensitive fields
    • Only send necessary data
    • Review what goes where

Reliability

  1. Monitor continuously

    • Set up alerts
    • Review metrics regularly
    • Track trends over time
  2. Handle failures gracefully

    • Let circuit breakers work
    • Review Issues regularly
    • Fix root causes, not symptoms
  3. Plan for scale

    • Monitor webhook volume
    • Optimize slow destinations
    • Upgrade plan if needed

Advanced Bridge Configurations

Priority-Based Routing

{
"destinations": [
{
"name": "Critical Queue",
"url": "https://api.example.com/critical",
"filters": [
{"body.priority": {"$eq": "critical"}}
],
"max_retries": 20
},
{
"name": "High Priority Queue",
"url": "https://api.example.com/high",
"filters": [
{"body.priority": {"$eq": "high"}}
],
"max_retries": 15
},
{
"name": "Normal Queue",
"url": "https://api.example.com/normal",
"max_retries": 10
}
]
}

Geographic Routing

{
"destinations": [
{
"name": "US Region API",
"url": "https://us.api.example.com/webhook",
"filters": [
{"body.country": {"$eq": "US"}}
]
},
{
"name": "EU Region API",
"url": "https://eu.api.example.com/webhook",
"filters": [
{"body.country": {"$in": ["GB", "FR", "DE", "IT", "ES"]}}
]
},
{
"name": "APAC Region API",
"url": "https://apac.api.example.com/webhook",
"filters": [
{"body.country": {"$in": ["JP", "SG", "AU", "KR"]}}
]
}
]
}

Event Type Routing

{
"destinations": [
{
"name": "User Events Handler",
"url": "https://api.example.com/users",
"filters": [
{"body.type": {"$startsWith": "user."}}
]
},
{
"name": "Payment Events Handler",
"url": "https://api.example.com/payments",
"filters": [
{"body.type": {"$startsWith": "payment."}}
]
},
{
"name": "Order Events Handler",
"url": "https://api.example.com/orders",
"filters": [
{"body.type": {"$startsWith": "order."}}
]
}
]
}

Next Steps

Now that you've built your first Bridge, continue learning:

  1. Set up Filters for advanced routing
  2. Use Transformations to customize payloads
  3. Monitor Events to track webhook activity
  4. Manage Issues when problems occur
  5. Understand Circuit Breakers for reliability

Your Bridge is now operational! Monitor it regularly, respond to Issues, and optimize based on what you learn from the Events data.