Webhook Integrations

Connect AstraNetmon with Slack, Discord, Microsoft Teams, and other services using webhooks

Overview

Webhooks allow you to receive real-time notifications when events occur in your network monitoring. Send alerts to Slack, Discord, Microsoft Teams, PagerDuty, or any custom HTTP endpoint.

ℹ️

Webhooks are configured from Dashboard → Settings → Alerts

Quick Setup

  1. Navigate to Dashboard → Settings → Alerts
  2. Click Add Webhook
  3. Enter a name and webhook URL
  4. Select which events to subscribe to
  5. (Optional) Enable webhook secret for signature verification
  6. Click Create Webhook

Available Events

agent.status_changed

Triggered when an agent goes online or offline

agent.registered

Triggered when a new agent registers

speedtest.completed

Triggered when a speed test finishes

traceroute.completed

Triggered when a traceroute finishes

service_test.failed

Triggered when a service test fails

alert.triggered

Triggered when a threshold alert fires

Webhook Payload Format

All webhooks receive a JSON payload:

json
{
  "event": "agent.status_changed",
  "timestamp": "2025-12-17T10:30:00Z",
  "data": {
    "agent_id": "agent-123",
    "hostname": "server-01",
    "previous_status": "online",
    "current_status": "offline",
    "tenant_id": "tenant-abc"
  }
}
ℹ️

The data object structure varies based on the event type.

Signature Verification

When you enable a webhook secret, AstraNetmon signs each request with an HMAC-SHA256 signature in the X-Webhook-Signature header.

Verify Signature in Node.js

javascript
const crypto = require('crypto');

function verifySignature(body, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(body))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-webhook-signature'];

  if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process webhook...
  res.json({ status: 'received' });
});

Verify Signature in Python

python
import hmac
import hashlib
import json

def verify_signature(request_data, signature, secret):
    expected_signature = hmac.new(
        secret.encode(),
        request_data,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected_signature)

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Webhook-Signature')

    if not verify_signature(request.data, signature, WEBHOOK_SECRET):
        return jsonify({'error': 'Invalid signature'}), 401

    # Process webhook...
    return jsonify({'status': 'received'}), 200

Integration Examples

Slack

To send alerts to Slack, you'll need a transformation middleware since Slack expects a different format. See our webhook examples repository for ready-to-use middleware.

ℹ️

For detailed Slack integration instructions, see the WEBHOOK_TEMPLATES.md file in the project repository.

Discord

Similar to Slack, Discord requires message transformation. Example middleware:

javascript
// discord-webhook-transformer.js
const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json());

const DISCORD_WEBHOOK_URL = 'YOUR_DISCORD_WEBHOOK_URL';

app.post('/webhook/discord', async (req, res) => {
  const { event, timestamp, data } = req.body;

  if (event === 'agent.status_changed') {
    const isOffline = data.current_status === 'offline';

    await axios.post(DISCORD_WEBHOOK_URL, {
      username: 'AstraNetmon',
      embeds: [{
        title: `${isOffline ? '🔴' : '🟢'} Agent Status Changed`,
        color: isOffline ? 0xdc2626 : 0x16a34a,
        fields: [
          { name: 'Agent', value: data.hostname, inline: true },
          { name: 'Status', value: data.current_status.toUpperCase(), inline: true }
        ],
        timestamp: timestamp
      }]
    });
  }

  res.status(200).send('OK');
});

app.listen(3000);

Microsoft Teams

Teams uses MessageCard format for incoming webhooks:

javascript
app.post('/webhook/teams', async (req, res) => {
  const { event, timestamp, data } = req.body;

  if (event === 'agent.status_changed') {
    const isOffline = data.current_status === 'offline';

    await axios.post(TEAMS_WEBHOOK_URL, {
      '@type': 'MessageCard',
      '@context': 'https://schema.org/extensions',
      summary: `Agent ${data.hostname} is ${data.current_status}`,
      themeColor: isOffline ? 'dc2626' : '16a34a',
      sections: [{
        activityTitle: `${isOffline ? '🔴' : '🟢'} Agent Status Changed`,
        facts: [
          { name: 'Agent:', value: data.hostname },
          { name: 'Status:', value: data.current_status.toUpperCase() }
        ]
      }]
    });
  }

  res.status(200).send('OK');
});

Custom HTTP Endpoint

For custom endpoints, you can receive webhooks directly:

python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    payload = request.json
    event = payload.get('event')
    data = payload.get('data')

    if event == 'agent.status_changed':
        if data.get('current_status') == 'offline':
            # Send alert, create ticket, etc.
            print(f"ALERT: {data['hostname']} is offline!")

    return jsonify({'status': 'received'}), 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Testing Webhooks

Test your webhook endpoints before deploying:

  1. Use webhook.site to inspect webhook payloads
  2. Configure AstraNetmon to send to the test URL
  3. Trigger an event (e.g., restart an agent)
  4. Review the received payload structure
  5. Update your webhook endpoint to handle the correct format

Best Practices

  • Always use HTTPS for webhook URLs in production
  • Enable signature verification for security-critical integrations
  • Return 2xx status codes quickly to avoid timeouts
  • Process webhooks asynchronously if needed
  • Monitor failure counts in the dashboard
  • Set up separate webhooks for different event types if needed

Troubleshooting

Webhook Not Receiving Events

  • Verify the webhook is enabled in the dashboard
  • Check that the correct events are subscribed
  • Ensure your endpoint is accessible from the internet
  • Review firewall rules and allow AstraNetmon's IP range
  • Check webhook failure count in the dashboard

Signature Verification Failing

  • Ensure you're using the exact secret from AstraNetmon
  • Verify you're hashing the raw JSON body (not parsed)
  • Use timing-safe comparison functions
  • Check the signature is in the X-Webhook-Signature header

High Failure Counts

  • Check that your endpoint returns 2xx status codes
  • Ensure responses are sent within 30 seconds
  • Review your webhook endpoint logs for errors
  • Test the webhook URL manually with curl

Next Steps