Custom Webhooks Quick Reference
Webhook URL Format
https://your-tobealert.com:9000/api/webhooks/custom/{webhook-id}
Inbound method: POST only.
Creating a Webhook
Omit fieldMappings or send {} for history-only receive. Omit enabled → disabled. enabled: true without covering resource, event, environment, type, text, severity (mapping or non-empty default) → 400. origin optional.
curl -X POST http://your-tobealert.com:9000/api/webhook_config \
-H "Content-Type: application/json" \
-H "Authorization: Key YOUR_API_KEY" \
-d '{
"id": "my-webhook",
"name": "My Monitoring Integration",
"authMode": "none",
"enabled": true,
"fieldMappings": {
"resource": "hostname",
"event": "check",
"severity": "severity",
"text": "message"
},
"defaultValues": {
"environment": "Production",
"type": "webhook",
"origin": "my-monitoring"
}
}'
Auth fields (create / update / GET)
| Field | Values / notes |
|---|---|
authMode | none | header | api_key (existing configs default to none) |
authHeaderScheme | static | generic | github | slack (header only) |
authHeaderName | Required for static / generic; server sets github/slack headers |
authSecret | Write-only shared secret; omit / "" / ****** on PUT keeps stored value |
authSecretSet | GET only: true / false |
authSecretPlaintext | GET only: decrypted secret for HMAC schemes (generic, github, slack); null for static |
authSecretStale | GET only: true when SECRET_KEY changed after the secret was saved |
apiKeyId | ToBeAlert API key id (write:alerts); never the key secret |
SECRET_KEY empty → cannot save authMode: header (400). Changing mode clears previous credentials.
Inbound api_key: Authorization: Key <key> or X-API-Key only (no ?api-key=).
Field mapping syntax
Mappings copy values as they are — no ${…} templates, expressions, or functions. Full details: Field Mapping Reference.
| Mapping value | Result |
|---|---|
"field" | Value of a top-level key |
"object.property" | Nested value (dot notation) |
"array[0]", "array[0].name" | Array element by index |
"array" / "array[]" | Whole array, as a list |
{"path": "array", "join": ", "} | Array joined into one string |
{"path": "array[]", "expand": true} | One alert per element; "other[N]" reads the same index |
{"path": "flag", "if_true": "critical", "if_false": "warning"} | Fixed value chosen by a boolean |
"attributes": {"key": "path", …} | Custom attributes, same syntax |
123, true | Literal number / boolean |
A string is always a path. Fixed text ("environment": "Production", "origin": "nagios") goes in defaultValues; a default also fills a field whose path is missing from the payload. arrayPath (for example alerts) makes one alert per element and reads every mapping inside it.
Required to enable: resource, event, environment, type, text, severity. severity must be a ToBeAlert severity (critical, major, minor, warning, …); service and tags must be lists.
Common Mappings
Severity from a boolean
"severity": { "path": "is_critical", "if_true": "critical", "if_false": "warning" }
Severity from another vocabulary (CRITICAL, ALARM, high)
"fieldMappings": { "attributes": { "source_status": "status" } },
"defaultValues": { "severity": "warning" }
Then a policy: attributes key source_status Equals CRITICAL → severity set critical. See Transforming values.
Links in Attributes
"attributes": {
"dashboard": "links.dashboard",
"runbook": "annotations.runbook"
}
The payload must carry the complete URL; mappings cannot build one from parts.
Tags
"tags": "labels_list"
Map an array from the payload, or set a fixed list in defaultValues ("tags": ["webhook"]).
Case, trim, thresholds
Not done by the mapping. Use a policy on receive: text transforms (upper, lower, capitalize, trim) and numeric comparisons on value.
Managing Webhooks
| Action | Command | Notes |
|---|---|---|
| List all | GET /api/webhook_configs | payloadHistoryCount, lastPayloadAt, errorHistoryCount, lastErrorAt (no bodies) |
| Get one | GET /api/webhook_config/{id} | Full payloadHistory + errorHistory (≤5 each); read:webhook_configs |
| Update | PUT /api/webhook_config/{id} | Client histories ignored; histories kept; auth secret keep rules apply |
| Delete | DELETE /api/webhook_config/{id} |
Inbound HTTP status codes
| Code | Meaning |
|---|---|
| 200 | Accepted; alerts created (or partial if some alerts failed — also logged in errorHistory) |
| 401 | Auth failed; no alerts. Keepable JSON → payloadHistory + errorHistory |
| 403 | Config disabled (auth OK); payload kept for mapping; errorHistory too |
| 400 | Invalid/empty JSON, mapping error, Array Path missing/empty, or every mapped alert rejected (not auth; disabled is 403) |
| 413 | Raw body over 256 KiB; errorHistory only (oversized: true); auth not checked |
| 404 | Unknown config id; no history written |
| 500 | Unexpected error; errorHistory (+ traceback when applicable) |
Histories (max 5 each, newest first)
| History | Includes | Excludes |
|---|---|---|
payloadHistory | Valid keepable JSON (success, disabled, mapping fail, 401 keep) | Oversized, invalid JSON, empty body |
errorHistory | 400 / 401 / 403 / 413 / 500 / partial | Successful posts with no failures |
Clients cannot write either history. Name/mapping updates do not clear them.
Testing
# Test webhook (add auth headers when configured)
curl -X POST https://your-tobealert.com:9000/api/webhooks/custom/my-webhook \
-H "Content-Type: application/json" \
-d '{"hostname": "web-01", "check": "cpu", "severity": "warning", "message": "High CPU"}'
Response: {"status": "ok", "webhook_id": "my-webhook", "webhook_name": "…", "alerts_created": 1, "alerts": [{"id": "…", "resource": "web-01", "event": "cpu", "severity": "warning"}]}. Failed alerts are listed in errors (alert_data, error); status is then partial (200) or error (400).