Generic Webhook Notifications
The generic webhook channel POSTs a JSON body to any HTTPS URL you control. Use it to drive custom automation: auto-rollback on deploy failure, create Jira tickets on incidents, update Grafana annotations, write to a data warehouse, or fan out to a tool Reoclo doesn’t natively support.
Prerequisites
Section titled “Prerequisites”- An HTTPS endpoint that accepts
POSTrequests withContent-Type: application/json - (Optional but recommended) A shared secret you’ll use to verify Reoclo signed each request
Step 1 — Build or pick your receiver
Section titled “Step 1 — Build or pick your receiver”The receiver just needs to:
- Accept
POSTrequests at a fixed URL - Read the JSON body
- (Optional) Verify the
X-Reoclo-Signatureheader - Return any 2xx response (
200,201,202,204all work)
Treat non-2xx responses as failures — Reoclo will retry (1s, 2s, 4s backoff) before dropping the delivery.
Step 2 — Create the channel in Reoclo
Section titled “Step 2 — Create the channel in Reoclo”Dashboard
Section titled “Dashboard”-
Open Settings → Notification Channels.
-
Click Add Channel → Generic Webhook.
-
Give it a name (e.g.,
data-warehouse). -
Fill in the form:
Field Required Description URL Yes https://...— HTTP isn’t supportedHeaders No Custom request headers as a JSON object (e.g., {"Authorization": "Bearer xyz"})HMAC Algorithm No sha256orsha1— leave blank to disable signingSecret No Required if HMAC algorithm is set; used to compute the signature -
Click Send Test — Reoclo POSTs a test payload and the channel cannot save until your endpoint returns 2xx.
-
Pick which events this channel receives.
-
Save.
For anything with special characters (URLs with query strings, headers with :), use --from-file:
kind: generic_webhookname: data-warehouseconfig: url: https://ingest.example.com/reoclo headers: Authorization: Bearer ${env:DW_TOKEN} X-Tenant: yourcompany hmac_alg: sha256secret: ${env:DW_HMAC_SECRET}events: deploy_succeeded: true deploy_failed: true monitoring_uptime_down: true monitoring_uptime_recovered: true incident_created: true incident_resolved: trueDW_TOKEN=... DW_HMAC_SECRET=... \ reoclo channels create generic_webhook --from-file dw-webhook.yamlPayload
Section titled “Payload”Every request is a JSON POST:
POST /reoclo HTTP/1.1Host: ingest.example.comContent-Type: application/jsonAuthorization: Bearer xyzX-Reoclo-Signature: sha256=8f3c...{ "subject": "Deployment succeeded", "body": "Deployment of MyApp to prod-1 succeeded.", "payload": { "tenant_id": "550e8400-e29b-41d4-a716-446655440000", "event": "deploy_succeeded", "deployment_id": "dep-abc123", "application_id": "app-xyz789", "application_name": "MyApp", "timestamp": "2026-04-10T15:30:45.123456+00:00" }}The payload object’s exact shape depends on the event type — it includes the relevant resource IDs and context for each event.
Verifying signatures
Section titled “Verifying signatures”If you set an HMAC algorithm and secret on the channel, Reoclo signs the raw request body with HMAC and sends the hex digest in X-Reoclo-Signature as <alg>=<hex>:
X-Reoclo-Signature: sha256=8f3c2a91...Compute the same HMAC over the raw body using your shared secret and compare with a constant-time comparison.
Python
Section titled “Python”import hashlibimport hmac
def verify(raw_body: bytes, secret: str, signature_header: str, algo: str = "sha256") -> bool: digest = hashlib.sha256 if algo == "sha256" else hashlib.sha1 expected = f"{algo}=" + hmac.new(secret.encode(), raw_body, digest).hexdigest() return hmac.compare_digest(expected, signature_header)Node.js
Section titled “Node.js”const crypto = require('crypto');
function verify(rawBody, secret, signatureHeader, algo = 'sha256') { const expected = `${algo}=` + crypto.createHmac(algo, secret).update(rawBody).digest('hex'); const a = Buffer.from(expected); const b = Buffer.from(signatureHeader); return a.length === b.length && crypto.timingSafeEqual(a, b);}package webhook
import ( "crypto/hmac" "crypto/sha1" "crypto/sha256" "encoding/hex" "hash")
func Verify(rawBody []byte, secret, signatureHeader, algo string) bool { var h hash.Hash if algo == "sha1" { h = hmac.New(sha1.New, []byte(secret)) } else { h = hmac.New(sha256.New, []byte(secret)) } h.Write(rawBody) expected := algo + "=" + hex.EncodeToString(h.Sum(nil)) return hmac.Equal([]byte(expected), []byte(signatureHeader))}Custom headers
Section titled “Custom headers”Use the headers config to inject bearer tokens, tenant identifiers, or routing hints:
config: url: https://api.example.com/hooks headers: Authorization: Bearer ${env:API_TOKEN} X-Source: reoclo X-Env: productionHeader names are case-insensitive; the receiver sees them as sent. Don’t override Content-Type — Reoclo always sends application/json and your receiver will misparse anything else.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Fix |
|---|---|---|
| Channel won’t save: connection refused | Receiver isn’t running or wrong URL | Check the URL is reachable from the public internet (Reoclo runs from our hosted control plane) |
403 Forbidden from receiver | Auth header missing or wrong | Confirm the bearer token / auth scheme your receiver expects, set it in the channel headers |
| Signature verification fails | Receiver hashed re-serialized JSON, not the raw body | Hash the raw bytes of the request body before any parsing |
| All deliveries 200 but receiver gets nothing | Receiver is responding before processing | Process synchronously, or write to a queue and return 200 only after enqueue succeeds |
| Webhook hits rate limit | Too many events flowing through one endpoint | Filter events on the channel to only what you need, or split into multiple channels |
Use case patterns
Section titled “Use case patterns”Auto-rollback — receiver subscribes to deploy_failed and calls your CI to re-run the previous green deploy.
Audit logging — fan out all events to a SIEM or data warehouse with no event filter set.
Custom paging — subscribe to monitoring_uptime_down and incident_created and hit your own pager (Twilio SMS, custom on-call).
Status page automation — subscribe to incident_created, incident_updated, incident_resolved and update Atlassian Statuspage or your own.
Ticket creation — subscribe to monitoring_ssl_expiring/monitoring_domain_expiring and create Jira/Linear tickets for renewal.
Next Steps
Section titled “Next Steps”- Status Pages — Reoclo’s built-in status page if you don’t want to build a custom integration
- Alert Rules — wire monitor thresholds into your custom webhook