Notify & Webhook setup
Webhook notify channel: URL, optional HMAC signing, request contract, and binding/test send in ops and console.
Both ops System Notify and console Notifications can enable Webhook delivery to your HTTPS/HTTP endpoint. Use it alone or together with Telegram.
When to use it
- Forward alerts into your own service, a message gateway, low-code automation (e.g. n8n), or another IM
- Keep bot credentials on your side and let your service re-dispatch
Ops and account configs are independent. When Webhook is on for a side, each notify issues one POST to that URL (and also Telegram if that channel is enabled).
Fields
| Field | Required | Notes |
|---|---|---|
| Webhook switch | — | Off = no delivery |
| Webhook URL | Required when enabled | Must start with http:// or https:// |
| Signing secret | Optional | When set, HMAC-SHA256 over the body is sent in a signature header |
| Signature header | Optional | Used when a secret is set; default X-Adswds-Signature |
Where to configure
Console (this account)
- Admin opens System → Notifications → Channels → Webhook
- Enable and paste the URL; add secret/header if you verify signatures
- Save, then Test send and confirm JSON on your receiver
Ops console
- Open System Notify → Channels → Webhook
- Same URL / optional signing fields
- Save and test
Request contract
The platform calls your URL with:
- Method:
POST - Content-Type:
application/json - User-Agent:
Adswds-Notify-Webhook/1.0 - Timeout: about 15 seconds; redirects are not followed (3xx is not success)
- Success: HTTP status in the 2xx range; anything else is a delivery failure
Body
JSON with two fields (title/body already rendered in the current notify language):
{
"title": "Notification title",
"body": "Notification body"
}Template placeholders (e.g. {{client_name}}) are rendered server-side before send. The Webhook does not include a raw event id or an unrendered variable map.
Optional signing (recommended)
When a signing secret is configured, the platform computes over the raw body bytes:
HMAC-SHA256(secret, raw_body) → lowercase hexand sets the header (default name X-Adswds-Signature):
X-Adswds-Signature: sha256=<hex>Your receiver should recompute with the same secret and compare the value after sha256= in constant time. With no secret, no signature header is sent.
Pseudo-code:
expected = "sha256=" + hex(hmac_sha256(secret, raw_body))
assert header["X-Adswds-Signature"] == expectedReceiver example
A temporary public tunnel or a small HTTP server is enough to verify. Minimal Node sample:
import http from 'node:http'
import crypto from 'node:crypto'
const SECRET = process.env.HOOK_SECRET || ''
http.createServer((req, res) => {
const chunks = []
req.on('data', (c) => chunks.push(c))
req.on('end', () => {
const raw = Buffer.concat(chunks)
if (SECRET) {
const sig = req.headers['x-adswds-signature'] || ''
const expected =
'sha256=' + crypto.createHmac('sha256', SECRET).update(raw).digest('hex')
if (sig !== expected) {
res.writeHead(401)
res.end('bad signature')
return
}
}
console.log(JSON.parse(raw.toString('utf8')))
res.writeHead(200)
res.end('ok')
})
}).listen(8080)Point the product Webhook URL at that public address, match the secret, then click Test send.
Test send and troubleshooting
| Symptom | Check |
|---|---|
| Invalid URL | Must start with http:// / https:// |
| Non-2xx HTTP | Receiver must return 200–299; do not rely on redirects (platform does not follow) |
| Signature mismatch | Hash raw body bytes; same secret; header name matches (default X-Adswds-Signature) |
| Test OK but no live alerts | Event toggles, master switch, account in service |
| Timeout | Respond within ~15s; ACK first, process async if needed |
Related: Notify & Telegram setup · System & Account · FAQ.