Generic Webhook
Send TSDProxy status alerts to any HTTP endpoint that accepts JSON. This works with custom scripts, automation platforms (n8n, Zapier, Home Assistant), or any service that ingests JSON webhooks.
Configuration
webhooks:
- url: "https://example.com/webhook"
type: generic
events:
- Running
- Stopped
- ErrorOmit type entirely — generic is the default when no type is specified.
JSON Payload
TSDProxy sends a POST request with Content-Type: application/json:
{
"proxy": "myapp",
"status": "Running",
"previous_status": "Starting",
"timestamp": "2026-05-15T10:00:00Z",
"message": "Proxy 'myapp' status changed from Starting to Running"
}| Field | Type | Description |
|---|---|---|
proxy | string | Proxy hostname |
status | string | Current status (e.g., Running, Error) |
previous_status | string | Previous status |
timestamp | string | UTC timestamp in RFC 3339 format |
message | string | Human-readable status change description |
Custom Payload Template
Set template to render a custom request body with Go text/template. The template receives the webhook event fields as .ProxyName, .Status, .OldStatus, .Timestamp, and .Message. When template is set and parses successfully, it takes precedence over type.
webhooks:
- url: "https://hooks.slack.com/services/your/webhook/url"
type: slack
template: |
{"text":"TSDProxy: Proxy `{{.ProxyName}}` changed from `{{.OldStatus}}` to `{{.Status}}`"}Template Functions
The following functions are available in templates:
| Function | Description | Example |
|---|---|---|
toUpper | Converts string to uppercase | {{toUpper .Status}} → RUNNING |
toLower | Converts string to lowercase | {{toLower .ProxyName}} → myapp |
title | Converts string to title case | {{title .Status}} → Running |
trim | Strips leading and trailing whitespace | {{trim .Message}} |
sprintf | Formats a string with fmt.Sprintf verbs | {{sprintf "%s: %s" .ProxyName .Status}} |
Template Content Type
By default, template output is sent with Content-Type: application/json. Use templateContentType to override:
webhooks:
- url: "https://example.com/webhook"
template: |
status={{.Status}}
templateContentType: "text/plain"When no template is set, templateContentType has no effect — the content type is determined by the webhook type instead.
Sanitization
Template rendering outputs the raw field values without sanitization. If your endpoint interprets @ mentions (e.g. Discord, Slack), consider handling them in your template body or using the built-in type formatters instead.
With Custom Headers
webhooks:
- url: "https://example.com/webhook"
headers:
Authorization: "Bearer your-token"
X-Custom-Header: "custom-value"
events:
- ErrorCustom headers are applied after Content-Type, so you can override it if your endpoint expects a different content type.
Examples
Home Assistant
Send events to a REST sensor or automation trigger:
webhooks:
- url: "https://homeassistant.local:8123/api/webhook/tsdproxy"
type: generic
headers:
Authorization: "Bearer long-lived-access-token"n8n
Use the Webhook node to receive TSDProxy events:
webhooks:
- url: "https://n8n.example.com/webhook/tsdproxy"
type: genericCustom Script
Point the webhook at any HTTP server:
webhooks:
- url: "http://localhost:3000/tsdproxy-events"
type: genericNotes
- Default type. If you omit
type, TSDProxy sends generic JSON. You only needtype: genericfor clarity. - Response handling. TSDProxy considers the webhook successful when the response status is below 300. Any status code 300 or above triggers a retry (up to 3 attempts with exponential backoff).
- Timeout. Each request has a 10-second timeout. If your endpoint is slow, consider putting a queue in front of it.