Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.tallwatch.com/llms.txt

Use this file to discover all available pages before exploring further.

The webhook channel is the escape hatch for anything not in the native list. Accept an HTTPS POST and you can route Tallwatch incidents into your own systems. Every request is signed with HMAC-SHA256 over the raw body, so you can prove it came from us. This page covers setup. Three companion pages go deeper:
  • Build a receiver for complete, verified endpoints in Express, Next.js, FastAPI, Go, Rails, Laravel, and the edge
  • Payload reference for the exact JSON, field by field
  • Signing for the signature math and per-language verification snippets

Before you start

  • An HTTPS endpoint that accepts a POST. Plain HTTP is rejected; Tallwatch won’t send credentials over an unencrypted connection.
  • The ability to read a request header and the raw request body. Verification happens server-side.

1. Generate a signing secret

Make a random secret of at least 16 characters. Both Tallwatch and your receiver hold it; both need it to compute the signature.
openssl rand -base64 32
Save the output. You’ll paste it into Tallwatch and into your receiver’s config.

2. Add the channel in Tallwatch

1

Open the channels page

Go to Settings → Alerts → Channels and click Add channel.
2

Pick Webhook

Choose the Webhook kind and name it for the receiver, like Datadog incidents or Internal ticketing.
3

Paste the URL and secret

Put your HTTPS endpoint in Webhook URL and the secret in Signing secret. Tallwatch won’t show the secret again after save, so keep your own copy.
4

Optionally template the body

Leave Payload template blank for the canonical JSON, or paste a Handlebars template to reshape it.
5

Save and test

Click Save, then Send test alert. Your receiver should log one POST with a sample payload.

What gets POSTed

Every dispatch is a POST with these headers:
HeaderValue
Content-Typeapplication/json, or text/plain if your template renders a non-JSON body
User-AgentTallwatch-Webhook/1.0
X-Tallwatch-EventThe event type: incident.opened, incident.resolved, or test
X-Tallwatch-TimestampUnix seconds at signing time, also embedded in the signature
X-Tallwatch-Signaturet=<timestamp>,v1=<hmac>, the HMAC-SHA256 covering the timestamp and raw body
The body is the canonical payload, or your rendered template if you set one.
Verify the signature before processing the body. A spoofed POST is indistinguishable from a real one if you skip verification. The Signing page has copy-paste snippets and explains the exact string that’s signed.

What Tallwatch expects back

Return any 2xx. Anything else is a delivery failure.
  • 2xx: marked sent, response body discarded.
  • 5xx, 429, network error, or timeout: retried in place, up to 3 attempts (500 ms then 2 s between them). If all three miss, the dispatch is failed and shows on the incident.
  • Other 4xx: marked failed and not retried. A 4xx means your receiver rejected the request, so retrying won’t help.
Redirects are followed by the underlying HTTP client, so point the channel at a URL that responds directly rather than relying on a 3xx hop. The per-request timeout is 10 seconds; if your receiver needs longer, return 202 Accepted immediately and process the event asynchronously.

Reshape the body

The canonical payload is verbose. If your receiver expects a specific shape, paste a Handlebars template into the channel form. Here’s a minimal Slack-style body:
Webhook payload template
{
  "text": "{{monitor.name}} is {{incident.status}}",
  "channel": "#alerts"
}
The full variable set and more examples live on the Templates page.

Troubleshooting

Most often the signature doesn’t match because the secret differs. Confirm the receiver’s secret is byte-for-byte the one in Tallwatch, with no stray whitespace or newline.Next most often, you’re verifying against the parsed JSON instead of the raw bytes. Always verify the raw body. See Signing.
The request never reached your receiver. Usual causes: a wrong URL (typo, dead domain, DNS failure), a firewall blocking Tallwatch’s egress, or a TLS handshake failure from a self-signed or expired certificate.
A 5xx is retried up to 3 times in the same pass, then left failed. There’s no queue: the only re-send is that bounded inline retry. Fix the receiver and the next new event delivers fine. Past failures stay failed until you resend them from the incident.
The canonical payload sets every field. When a value is genuinely unknown (like resolved_at on an open incident) it’s null, not omitted, so check your receiver isn’t dropping nullable fields. If you templated the body, your template controls the shape.

Reference

PropertyValue
Channel kindwebhook
Required configurl (HTTPS), signing_secret (16+ chars)
Optional configpayload_template (Handlebars)
MethodPOST
Signature headerX-Tallwatch-Signature: t=<ts>,v1=<hmac>
Timeout10 seconds
RetryUp to 3 inline attempts on 5xx, 429, network, or timeout, then failed
DeliveryImmediate, no proactive rate limit
User-AgentTallwatch-Webhook/1.0