Integrate ChainRaven alerts with any system using custom webhooks
Webhooks let you receive ChainRaven alerts directly at your own HTTP endpoint. Use them to forward alerts to Slack or PagerDuty, store events in your own database, trigger custom workflows, or integrate with any system.
Tip: Use webhook.site to get an instant test URL and inspect exactly what ChainRaven sends before writing any code.
Your endpoint must:
POST requests with a JSON body200 status code on successMinimal Node.js example:
const express = require('express')
const app = express()
app.use(express.json())
app.post('/chainraven-webhook', (req, res) => {
console.log('Alert received:', req.body)
res.status(200).send('OK')
})
app.listen(3000)
Webhooks are configured per alert type, so you can route different alerts to different endpoints.
Repeat for each alert type you want to route via webhook.
ChainRaven sends POST requests with this structure:
Headers:
Content-Type: application/json
X-ChainRaven-Timestamp: 2026-01-05T10:30:00.000Z
X-ChainRaven-Signature: <hmac-sha256-hex> (if secret configured)
Body:
{
"event": "alert.sent",
"timestamp": "2026-01-05T10:30:00.000Z",
"data": {
"alertType": "OWNERSHIP_TRANSFER",
"severity": "critical",
"contractAddress": "0x1234...",
"chain": "ethereum",
"eventData": {
"previousOwner": "0xaaaa...",
"newOwner": "0xbbbb..."
},
"transactionHash": "0xabcdef...",
"blockNumber": 12345678,
"detectedAt": "2026-01-05T10:30:00.000Z",
"dashboardUrl": "https://chainraven.io/dashboard"
}
}
The eventData field varies by alert type:
| Alert Type | eventData Fields |
|---|---|
| Large Transfer | tokenSymbol, amount, amountUsd, from, to, thresholdMultiple |
| Ownership Transfer | previousOwner, newOwner |
| Proxy Upgrade | implementation |
| Admin Change | previousAdmin, newAdmin |
If you configure a webhook secret, ChainRaven includes an HMAC-SHA256 signature in the X-ChainRaven-Signature header. Verify it to confirm requests actually came from ChainRaven and weren't tampered with.
Node.js verification example:
const crypto = require('crypto')
function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex')
return signature === expected
}
// In your endpoint:
const signature = req.headers['x-chainraven-signature']
if (signature && !verifySignature(req.body, signature, 'your-secret')) {
return res.status(401).send('Invalid signature')
}
POST requestsDue to automatic retries, you may receive the same alert more than once. Deduplicate by tracking processed transaction hashes:
const processed = new Set()
app.post('/webhook', (req, res) => {
const id = req.body.data.transactionHash
if (processed.has(id)) {
return res.status(200).send('Already processed')
}
processed.add(id)
// Process the alert...
res.status(200).send('OK')
})
200 immediately if you need to do heavy processing, then handle it asynchronously in the backgroundeventData fields