Creating Destinations
This guide shows you how to create Destinations in Hooklistener - the endpoints where your webhooks are forwarded. You'll learn how to configure different destination types, add authentication, and test your setup.
What You'll Learn
- How to create HTTP/HTTPS destinations
- How to configure Slack, Discord, and Telegram destinations
- How to add authentication headers and API keys
- How to test destinations before going live
- Common configurations for popular services
Prerequisites
- A Hooklistener account
- A Source already created
- Basic understanding of Destinations
- (Optional) API credentials for your destination service
Creating an HTTP Destination
HTTP destinations are the most flexible - you can send webhooks to any HTTP/HTTPS endpoint.
Via Dashboard
Step 1: Create or Edit a Bridge
- Navigate to Bridges
- Either:
- Create a new Bridge, OR
- Edit an existing Bridge
Step 2: Add Destination
- In the Bridge configuration, click "Add Destination"
- Select "HTTP/HTTPS" as the destination type
Step 3: Configure Destination
Name:
Production API Endpoint
Use a descriptive name that indicates purpose and environment.
URL:
https://api.example.com/webhooks
The full URL where webhooks should be sent.
Method:
- POST (most common)
- PUT
- PATCH
- GET (less common for webhooks)
Step 4: Add Headers (Optional but Recommended)
Click "Add Header" to include authentication or custom headers:
Authentication examples:
Bearer Token:
Header: Authorization
Value: Bearer {{API_TOKEN}}
API Key:
Header: X-API-Key
Value: `{{API_KEY}}`
Basic Auth:
Header: Authorization
Value: Basic {{BASE64_CREDENTIALS}}
Custom headers:
Header: Content-Type
Value: application/json
Header: X-Webhook-Source
Value: hooklistener
Header: X-Event-ID
Value: {{EVENT_ID}}
Using Secrets: Reference secrets with {{SECRET_NAME}} syntax for secure credential storage.
Step 5: Configure Retries
Set the maximum number of retry attempts:
- Critical endpoints: 15 retries (default)
- Non-critical: 5-10 retries
- Best effort: 0-3 retries
Step 6: Save
Click "Save Destination" to add it to your Bridge.
Via API
curl -X POST https://api.hooklistener.com/api/v1/bridges \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "My Bridge",
"source": {
"name": "Webhook Source",
"type": "webhook"
},
"destinations": [
{
"name": "Production API",
"type": "http",
"url": "https://api.example.com/webhooks",
"method": "POST",
"headers": {
"Authorization": "Bearer {{API_TOKEN}}",
"Content-Type": "application/json"
},
"max_retries": 15
}
]
}'
Creating a Slack Destination
Send formatted messages directly to Slack channels.
Step 1: Get Slack Webhook URL
- Go to api.slack.com/apps
- Create a new app or select existing
- Navigate to Incoming Webhooks
- Click "Add New Webhook to Workspace"
- Select the channel
- Copy the webhook URL (looks like
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXX)
Step 2: Store in Secrets
- Go to Organization Settings → Secrets
- Click "Create Secret"
- Name:
SLACK_WEBHOOK_URL - Value: Paste the webhook URL
- Save
Step 3: Create Slack Destination
Via Dashboard:
- Add Destination to your Bridge
- Select "Slack" type
- Name:
Slack Alerts Channel - Webhook URL:
{{SLACK_WEBHOOK_URL}} - Save
Via API:
curl -X POST https://api.hooklistener.com/api/v1/bridges/{bridge_id}/destinations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Slack Alerts",
"type": "slack",
"webhook_url": "{{SLACK_WEBHOOK_URL}}"
}'
Step 4: Format Messages (Optional)
Use a Transformation to format Slack messages:
addHandler('transform', async (request) => {
return {
...request,
body: {
text: `New webhook received: ${request.body.event_type}`,
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `*Event:* ${request.body.event_type}\n*Time:* ${new Date().toISOString()}`
}
}
]
}
};
});
Creating a Discord Destination
Post messages to Discord channels via webhooks.
Step 1: Get Discord Webhook URL
- Open Discord and go to your server
- Right-click the channel → Edit Channel
- Go to Integrations → Webhooks
- Click "New Webhook"
- Customize name and avatar (optional)
- Click "Copy Webhook URL"
Step 2: Store in Secrets
- Organization Settings → Secrets → Create Secret
- Name:
DISCORD_WEBHOOK_URL - Value: Paste webhook URL
- Save
Step 3: Create Discord Destination
Via Dashboard:
- Add Destination
- Type: "Discord"
- Name:
Discord Notifications - Webhook URL:
{{DISCORD_WEBHOOK_URL}} - Save
Via API:
curl -X POST https://api.hooklistener.com/api/v1/bridges/{bridge_id}/destinations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Discord Notifications",
"type": "discord",
"webhook_url": "{{DISCORD_WEBHOOK_URL}}"
}'
Creating a Telegram Destination
Send messages to Telegram chats or channels.
Step 1: Create a Telegram Bot
- Open Telegram and search for @BotFather
- Send
/newbotcommand - Follow prompts to name your bot
- Copy the bot token (looks like
123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
Step 2: Get Chat ID
To send messages to a specific chat/channel, you need the chat ID:
For private chat:
- Send a message to your bot
- Visit:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates - Find
"chat":{"id":123456789}in the response - Copy the chat ID
For channel:
- Add your bot to the channel as administrator
- Post a message in the channel
- Visit:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates - Find the channel chat ID (usually negative number like
-1001234567890)
Step 3: Store Credentials
Create two secrets:
TELEGRAM_BOT_TOKEN= Your bot tokenTELEGRAM_CHAT_ID= Your chat/channel ID
Step 4: Create Telegram Destination
Via Dashboard:
- Add Destination
- Type: "Telegram"
- Name:
Telegram Admin Alerts - Bot Token:
{{TELEGRAM_BOT_TOKEN}} - Chat ID:
{{TELEGRAM_CHAT_ID}} - Save
Via API:
curl -X POST https://api.hooklistener.com/api/v1/bridges/{bridge_id}/destinations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Telegram Alerts",
"type": "telegram",
"bot_token": "{{TELEGRAM_BOT_TOKEN}}",
"chat_id": "{{TELEGRAM_CHAT_ID}}"
}'
Common Destination Patterns
Internal API with Authentication
{
"name": "Internal Service",
"type": "http",
"url": "https://internal-api.company.com/webhooks",
"method": "POST",
"headers": {
"Authorization": "Bearer {{INTERNAL_API_TOKEN}}",
"Content-Type": "application/json",
"X-Source": "hooklistener"
},
"max_retries": 15
}
AWS Lambda Function
{
"name": "Lambda Webhook Processor",
"type": "http",
"url": "https://abc123.execute-api.us-east-1.amazonaws.com/prod/webhook",
"method": "POST",
"headers": {
"X-API-Key": "{{AWS_API_KEY}}",
"Content-Type": "application/json"
},
"max_retries": 10
}
Google Cloud Function
{
"name": "GCP Function",
"type": "http",
"url": "https://us-central1-project-id.cloudfunctions.net/webhook-handler",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"max_retries": 10
}
Zapier Webhook
{
"name": "Zapier Automation",
"type": "http",
"url": "https://hooks.zapier.com/hooks/catch/123456/abcdef/",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"max_retries": 5
}
Make (Integromat) Webhook
{
"name": "Make Scenario",
"type": "http",
"url": "https://hook.us1.make.com/abcdefghijklmnop",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"max_retries": 5
}
Testing Your Destination
Test 1: Endpoint Availability
Before adding to Hooklistener, test the endpoint independently:
curl -X POST https://api.example.com/webhooks \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"test": true,
"message": "Test webhook"
}'
Expected: 2xx response indicating endpoint is reachable and accepts webhooks.
Test 2: Hooklistener Delivery
After adding the destination to your Bridge:
- Send a test webhook to your Source
- Navigate to Events → Outgoing
- Find the delivery attempt
- Check:
- Status code (should be 2xx)
- Response body
- Latency
- Any errors
Test 3: Authentication
Verify authentication is working:
With valid credentials:
- Should receive 200/201/202 response
- Destination should process webhook
With invalid credentials (test separately):
- Should receive 401/403 response
- Update credentials if needed
Test 4: Transformations (if used)
If you added a transformation:
- Check transformation logs in the outgoing event
- Verify output payload matches expectations
- Confirm destination receives transformed data
Test 5: Filters (if used)
If you added filters:
- Send webhooks that should match filters
- Verify they're delivered
- Send webhooks that shouldn't match
- Verify they're skipped (not errors)
Troubleshooting
Destination Not Receiving Webhooks
Check Bridge Status:
- Ensure Bridge is activated
- Verify Source is receiving webhooks
- Check if filters are excluding webhooks
Check Destination Configuration:
- Verify URL is correct
- Check HTTP method (POST vs PUT)
- Ensure headers are properly configured
Check Events:
- Look at outgoing events for error details
- Check response codes
- Review error messages
Authentication Failures
401 Unauthorized:
- Verify API key/token is correct
- Check token hasn't expired
- Ensure secret name is correct (
{{API_KEY}}not{{API_TOKEN}}) - Review header format (Bearer, Basic, custom)
403 Forbidden:
- Check API key permissions/scopes
- Verify account has necessary access
- Review IP allowlists if applicable
Timeouts
Connection Timeout:
- Verify destination endpoint is reachable
- Check firewall rules
- Ensure DNS is resolving correctly
- Test endpoint outside Hooklistener
Response Timeout:
- Destination taking too long to respond (>30s)
- Optimize destination endpoint performance
- Consider async processing on destination side
Rate Limiting
429 Too Many Requests:
- Destination has rate limits
- Review webhook volume
- Implement throttling if needed
- Contact destination provider for limit increase
Best Practices
Security
-
Always use HTTPS
- Never use HTTP for production destinations
- Verify SSL certificates are valid
- Monitor certificate expiration
-
Use secrets for credentials
- Store all API keys and tokens in Secrets
- Reference with
{{SECRET_NAME}} - Never hardcode sensitive data
-
Minimize exposed data
- Use transformations to remove sensitive fields
- Only send necessary data
- Consider data privacy regulations
Reliability
-
Configure appropriate retries
- Critical: 15 retries
- Important: 10 retries
- Best-effort: 3-5 retries
-
Monitor destination health
- Watch success rates
- Set up alerts for failures
- Track circuit breaker status
-
Design idempotent endpoints
- Handle duplicate deliveries gracefully
- Use unique identifiers
- Implement deduplication on receiver
Performance
-
Optimize destination response time
- Return 200 OK quickly
- Process webhooks asynchronously if needed
- Keep response under 5 seconds
-
Monitor latency
- Track response times
- Investigate slow destinations
- Optimize as needed
-
Handle high volume
- Ensure destination can handle webhook rate
- Implement queuing if necessary
- Scale destination infrastructure
Organization
-
Use clear names
- Include purpose: "Payment Notifications"
- Include environment: "Production API"
- Make searchable and identifiable
-
Document destinations
- Note purpose and owner
- Link to destination service docs
- Track configuration changes
-
Separate environments
- Different destinations for dev/staging/prod
- Use different credentials per environment
- Test in staging first
Advanced Configuration
Multiple Destinations
Send webhooks to multiple endpoints from one Source:
{
"name": "Multi-Destination Bridge",
"source": {...},
"destinations": [
{
"name": "Primary API",
"type": "http",
"url": "https://api.example.com/webhooks"
},
{
"name": "Backup API",
"type": "http",
"url": "https://backup.example.com/webhooks"
},
{
"name": "Slack Notifications",
"type": "slack",
"webhook_url": "{{SLACK_WEBHOOK_URL}}"
}
]
}
Conditional Routing with Filters
Send to different destinations based on webhook content:
{
"destinations": [
{
"name": "High Priority Queue",
"url": "https://api.example.com/high-priority",
"filters": [
{"body.priority": {"$eq": "high"}}
]
},
{
"name": "Normal Queue",
"url": "https://api.example.com/normal"
}
]
}
Transformation per Destination
Apply different transformations to different destinations:
{
"destinations": [
{
"name": "Internal API",
"url": "https://internal.example.com/webhooks",
"transformation_id": "internal-format"
},
{
"name": "Partner API",
"url": "https://partner.example.com/webhooks",
"transformation_id": "partner-format"
}
]
}
Next Steps
Now that you've created destinations, you can:
- Build a Complete Bridge connecting Sources to Destinations
- Set up Filters for conditional routing
- Use Transformations to customize payloads
- Monitor Events to track webhook deliveries
- Manage Issues when problems occur
Your destinations are ready to receive webhooks! Continue to the Bridge building guide to connect everything together.