Problem
Webhooks are already supported in TSDProxy — see internal/config/config.go for the WebhookConfig struct and internal/core/webhook for the sender implementation. Events are fired on proxy status changes (start, stop, error, etc.) via broadcastStatusEvents in internal/proxymanager/proxymanager.go.
However, webhook payloads are currently fixed-format. To integrate with Slack, Discord, PagerDuty, or custom systems, users need an intermediary webhook transformer. This adds operational complexity.
Proposed Solution
Add an optional template field to webhook configurations that uses Go text/template (or html/template for HTML-safe payloads) to render the HTTP request body. The template receives the webhook event data:
webhooks:
- url: "https://hooks.slack.com/services/xxx/yyy/zzz"
type: "slack"
events: ["error", "stopped"]
template: |
{
"text": "⚠️ Proxy {{.Name}} is now **{{.Status}}** (was {{.OldStatus}})",
"attachments": [{
"color": "danger",
"fields": [
{"title": "Proxy", "value": "{{.Name}}", "short": true},
{"title": "Status", "value": "{{.Status}}", "short": true}
]
}]
}
- url: "https://discord.com/api/webhooks/xxx/yyy"
type: "discord"
events: ["running", "error"]
template: |
{
"embeds": [{
"title": "Proxy {{.Name}}",
"description": "Status changed to {{.Status}}",
"color": {{if eq .Status "error"}}15158332{{else}}3066993{{end}}
}]
}
When no template is set, the existing default JSON payload is used (backward compatible).
Template Data Context
The template should have access to at minimum:
type WebhookEvent struct {
Name string // proxy hostname
Status string // current status (Running, Error, Stopped, etc.)
OldStatus string // previous status
TargetID string // container ID / target ID
Provider string // target provider name
Image string // container image (from TargetImage)
Timestamp time.Time
URL string // proxy URL
}
Implementation Notes
- The webhook sender lives at internal/core/webhook — parse and execute the template before the HTTP POST
- Templates should be pre-parsed at config load time and cached to avoid re-parsing on every event
- Template errors should be logged but not crash the event loop
- Standard Go template functions are available by default; consider adding
sprig functions for richer transformations
- Default (no template) = current behavior, fully backward compatible
Alternatives
- Template-less passthrough to n8n / Zapier / Pipedream (adds external dependency)
- Fixed payload formats per type (less flexible, more maintenance)
Problem
Webhooks are already supported in TSDProxy — see internal/config/config.go for the
WebhookConfigstruct and internal/core/webhook for the sender implementation. Events are fired on proxy status changes (start, stop, error, etc.) viabroadcastStatusEventsin internal/proxymanager/proxymanager.go.However, webhook payloads are currently fixed-format. To integrate with Slack, Discord, PagerDuty, or custom systems, users need an intermediary webhook transformer. This adds operational complexity.
Proposed Solution
Add an optional
templatefield to webhook configurations that uses Gotext/template(orhtml/templatefor HTML-safe payloads) to render the HTTP request body. The template receives the webhook event data:When no template is set, the existing default JSON payload is used (backward compatible).
Template Data Context
The template should have access to at minimum:
Implementation Notes
sprigfunctions for richer transformationsAlternatives