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
- A Hooklistener account
- Understanding of Bridges, Sources, and Destinations
- (Optional) API key for programmatic setup
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
- Log in to app.hooklistener.com
- Click "Bridges" in the sidebar
- 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
- Click "Save Bridge"
- Copy the Source URL
- Configure it in GitHub (Repository → Settings → Webhooks)
- The Bridge is now active!
Step 6: Test
- Make a commit or open a PR in your GitHub repository
- Check Events → Incoming to see the webhook arrive
- Check Events → Outgoing to see delivery to Slack
- 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
- Navigate to Bridges
- Click "Create Bridge"
- 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
- Drag a Source node onto the canvas
- Click the node to open properties
- Configure:
- Name
- Authentication settings
- Deduplication options
Step 2: Add Destination Nodes
- Drag Destination nodes onto the canvas
- Connect Source to each Destination by dragging from Source's output port
- Click each Destination to configure:
- Name and type
- URL and headers
- Retry settings
Step 3: Add Filters (Optional)
- Click on a connection line (edge)
- Click "Add Filter"
- Configure filter conditions
- Webhook will only flow to that Destination if filters match
Step 4: Add Transformations (Optional)
- Click on a connection line (edge)
- Click "Add Transformation"
- Write JavaScript transformation code
- Test with sample payload
Step 5: Save and Deploy
- Click "Save" to save as draft
- Click "Test" to validate configuration
- 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
- Send real webhook from your service
- Monitor Events dashboard in real-time
- 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
-
One workflow per Bridge
- Keep Bridges focused on single purpose
- Easier to manage and debug
- Clearer metrics and monitoring
-
Descriptive names
- Include source and purpose
- Specify environment
- Make it searchable
-
Separate environments
- Different Bridges for dev/staging/prod
- Prevent cross-contamination
- Test safely before production
Configuration
-
Test thoroughly
- Test each component independently
- Verify end-to-end flow
- Use real webhook data
- Test failure scenarios
-
Use filters strategically
- Filter early to reduce processing
- Keep conditions simple
- Document filter logic
-
Configure retries appropriately
- Critical: 15 retries
- Important: 10 retries
- Best-effort: 3-5 retries
Security
-
Enable authentication
- Always use signature verification in production
- Rotate secrets regularly
- Monitor auth failures
-
Use secrets
- Store all credentials in Secrets
- Reference with
{{SECRET_NAME}} - Never hardcode sensitive data
-
Minimize data exposure
- Use transformations to filter sensitive fields
- Only send necessary data
- Review what goes where
Reliability
-
Monitor continuously
- Set up alerts
- Review metrics regularly
- Track trends over time
-
Handle failures gracefully
- Let circuit breakers work
- Review Issues regularly
- Fix root causes, not symptoms
-
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:
- Set up Filters for advanced routing
- Use Transformations to customize payloads
- Monitor Events to track webhook activity
- Manage Issues when problems occur
- 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.