Webhooks
Build custom integrations with APIAssert. Webhooks send HTTP POST requests to your endpoint whenever monitors fail, recover, or trigger other events.
Why Webhooks?
- Build anything — connect to any system that accepts HTTP
- Full control — process alerts your way
- Automation — trigger workflows, scripts, or CI/CD pipelines
- Custom dashboards — feed data to your internal tools
What You'll Get
- JSON payloads with complete monitor and alert data
- Retry logic for failed deliveries
- Signature verification for secure webhooks
- Custom headers for authentication
Setup Guide
Step 1: Create Your Endpoint
Set up an HTTP endpoint to receive POST requests:
// Express.js example
app.post('/webhooks/pingpost', (req, res) => {
const payload = req.body;
console.log('Alert received:', payload.event);
console.log('Monitor:', payload.monitor.name);
// Process the alert...
res.status(200).send('OK');
});
Step 2: Add Webhook in APIAssert
- Go to Alerts → Channels in your APIAssert dashboard
- Click Add Channel → Webhook
- Enter your endpoint URL
- (Optional) Add authentication headers
- Click Save
Step 3: Test the Webhook
Click Send Test to verify your endpoint receives payloads correctly.
Step 4: Assign to Monitors
Edit your monitors and add the webhook channel under Alert Channels.
Payload Format
APIAssert sends JSON payloads with this structure:
{
"event": "monitor.failed",
"timestamp": "2024-12-11T14:34:00Z",
"monitor": {
"id": "mon_abc123",
"name": "Production API",
"url": "https://api.example.com/health",
"method": "GET",
"interval": 60
},
"check": {
"id": "chk_xyz789",
"status_code": 500,
"response_time_ms": 2340,
"region": "us-east",
"checked_at": "2024-12-11T14:34:00Z"
},
"failure": {
"type": "assertion",
"message": "$.status expected 'success', got 'error'",
"assertion": {
"path": "$.status",
"operator": "equals",
"expected": "success",
"actual": "error"
}
},
"alert": {
"id": "alt_def456",
"state": "triggered",
"consecutive_failures": 3
}
}
Event Types
| Event | Description |
|---|---|
monitor.failed |
Monitor detected a failure |
monitor.recovered |
Monitor returned to healthy state |
monitor.degraded |
Response time exceeded threshold |
test |
Test webhook from dashboard |
Authentication
Bearer Token
Add a Bearer token header:
Header: Authorization
Value: Bearer your-secret-token
Custom Headers
Add any custom headers your endpoint requires:
X-API-Key: your-api-key
X-Webhook-Source: pingpost
Signature Verification
APIAssert signs webhook payloads with HMAC-SHA256. Verify signatures to ensure requests are authentic:
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your handler:
const signature = req.headers['x-pingpost-signature'];
if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
Use Cases
Trigger CI/CD Pipeline
Restart services when health checks fail:
# GitHub Actions workflow
on:
repository_dispatch:
types: [pingpost-alert]
jobs:
restart:
runs-on: ubuntu-latest
steps:
- run: ./scripts/restart-service.sh
Update Status Page
Post to your status page when monitors fail:
app.post('/webhooks/pingpost', async (req, res) => {
if (req.body.event === 'monitor.failed') {
await statusPage.createIncident({
name: `${req.body.monitor.name} is down`,
status: 'investigating'
});
}
res.send('OK');
});
Send to Custom Slack Format
Transform and forward to Slack with custom formatting:
app.post('/webhooks/pingpost', async (req, res) => {
const { monitor, check, failure } = req.body;
await fetch(process.env.SLACK_WEBHOOK, {
method: 'POST',
body: JSON.stringify({
blocks: [
{
type: 'header',
text: { type: 'plain_text', text: `🚨 ${monitor.name}` }
},
{
type: 'section',
text: { type: 'mrkdwn', text: failure.message }
}
]
})
});
res.send('OK');
});
Retry Policy
APIAssert retries failed webhook deliveries:
- 3 attempts total
- Exponential backoff: 10s, 30s, 90s
- Timeout: 10 seconds per request
- Success: Any 2xx response code
Troubleshooting
Not receiving webhooks?
- Ensure your endpoint is publicly accessible
- Check firewall rules allow incoming POST requests
- Verify the URL is correct (no typos, correct protocol)
Getting 4xx/5xx errors?
- Check your endpoint logs for errors
- Verify authentication headers are correct
- Ensure your endpoint returns 2xx on success
Payloads look different than expected?
- Use the Send Test feature to see exact payload format
- Check our API changelog for any recent changes
Next Steps
- Set up Slack for team notifications
- Configure PagerDuty for on-call escalation
- Explore response validation