Webhooks¶
Webhooks ermöglichen es, externe Systeme automatisch über Ereignisse in enconf zu informieren. Bei jedem konfigurierten Ereignis sendet das Panel eine HTTP-POST-Anfrage mit den Ereignisdaten an Ihre URL.
Typische Anwendungsfälle:
- Automatische Deployment-Pipelines nach Website-Erstellung
- Benachrichtigungen an Chat-Systeme (Slack, Microsoft Teams, Discord)
- Synchronisierung mit Billing-Systemen
- Monitoring und Logging in externe Plattformen
Funktionsweise¶
Ereignis im Panel → Webhook-Service → HTTP POST an Ihre URL
↓
Signatur (HMAC-SHA256) im Header
↓
Ihr Server verifiziert und verarbeitet
- Ein Ereignis tritt im Panel auf (z. B. Website erstellt)
- Das Panel findet alle aktiven Webhook-Endpoints, die auf dieses Ereignis abonniert sind
- Für jeden Endpoint wird ein HTTP-POST mit dem JSON-Payload gesendet
- Der Payload wird mit HMAC-SHA256 signiert
- Bei Fehlschlag wird ein automatischer Retry durchgeführt
Webhook-Endpoint erstellen¶
Über die API¶
POST /api/v1/webhooks
Authorization: Bearer <token>
Content-Type: application/json
{
"url": "https://ihr-server.de/webhook",
"secret": "IhrGeheimesWebhookSecret",
"events": "site.created,site.deleted,backup.completed",
"active": true
}
| Feld | Pflicht | Beschreibung |
|---|---|---|
url |
Ja | Die URL, an die Ereignisse gesendet werden (muss HTTPS sein) |
secret |
Ja | Geheimer Schlüssel für die HMAC-SHA256-Signatur |
events |
Ja | Komma-getrennte Liste der gewünschten Ereignisse (oder * für alle) |
active |
Nein | Endpoint aktivieren/deaktivieren (Standard: true) |
Über das Panel¶
- Navigieren Sie zu Einstellungen → Webhooks
- Klicken Sie auf Webhook erstellen
- Füllen Sie URL, Secret und Ereignisse aus
- Klicken Sie auf Erstellen
Verfügbare Ereignisse¶
| Ereignis | Beschreibung | Payload-Daten |
|---|---|---|
site.created |
Website wurde erstellt | site_id, domain |
site.deleted |
Website wurde gelöscht | site_id, domain |
domain.created |
Domain wurde hinzugefügt | domain_id, name |
domain.deleted |
Domain wurde entfernt | domain_id, name |
database.created |
Datenbank wurde erstellt | database_id, name |
database.deleted |
Datenbank wurde gelöscht | database_id, name |
email.created |
E-Mail-Postfach wurde erstellt | mailbox_id, email |
ftp.created |
FTP-Konto wurde erstellt | ftp_account_id, username |
backup.completed |
Backup wurde abgeschlossen | schedule_id, name |
subscription.created |
Abonnement wurde erstellt | subscription_id, main_domain |
subscription.suspended |
Abonnement wurde gesperrt | subscription_id, main_domain |
webhook.test |
Test-Ereignis (manuell ausgelöst) | message |
Wildcard-Abonnement¶
Verwenden Sie * als Ereignis, um alle Ereignisse zu empfangen:
Payload-Format¶
Jeder Webhook-Aufruf sendet einen JSON-Body mit folgendem Format:
{
"event": "site.created",
"timestamp": "2026-03-31T14:30:00Z",
"data": {
"site_id": 42,
"domain": "meine-seite.de"
}
}
| Feld | Typ | Beschreibung |
|---|---|---|
event |
String | Name des Ereignisses |
timestamp |
String | Zeitpunkt des Ereignisses (RFC 3339, UTC) |
data |
Object | Ereignisspezifische Daten |
HTTP-Header¶
Jede Webhook-Anfrage enthält folgende Header:
| Header | Beschreibung |
|---|---|
Content-Type |
application/json |
User-Agent |
NetCell-WebPanel-Webhook/1.0 |
X-Webhook-Event |
Name des Ereignisses (z. B. site.created) |
X-Webhook-Signature |
HMAC-SHA256-Signatur (siehe unten) |
HMAC-Signaturverifizierung¶
Jede Webhook-Anfrage wird mit HMAC-SHA256 signiert, damit Sie die Authentizität und Integrität des Payloads verifizieren können.
Signatur-Format¶
Verifizierungsschritte¶
- Lesen Sie den rohen Request-Body (als Byte-Array)
- Berechnen Sie HMAC-SHA256 mit Ihrem Secret als Schlüssel
- Vergleichen Sie das Ergebnis mit dem Wert aus
X-Webhook-Signature - Akzeptieren Sie die Anfrage nur bei Übereinstimmung
Beispiel: PHP¶
<?php
$secret = 'IhrGeheimesWebhookSecret';
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
// Erwartete Signatur berechnen
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
// Timing-sichere Vergleichsfunktion verwenden
if (!hash_equals($expected, $signature)) {
http_response_code(403);
die('Invalid signature');
}
// Payload verarbeiten
$data = json_decode($payload, true);
$event = $data['event'];
switch ($event) {
case 'site.created':
// Website wurde erstellt
$siteId = $data['data']['site_id'];
$domain = $data['data']['domain'];
// Ihre Logik hier...
break;
case 'backup.completed':
// Backup abgeschlossen
break;
}
http_response_code(200);
echo json_encode(['status' => 'ok']);
Beispiel: Python¶
import hmac
import hashlib
import json
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = 'IhrGeheimesWebhookSecret'
@app.route('/webhook', methods=['POST'])
def handle_webhook():
# Signatur verifizieren
signature = request.headers.get('X-Webhook-Signature', '')
expected = 'sha256=' + hmac.new(
SECRET.encode(),
request.data,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
abort(403, 'Invalid signature')
# Payload verarbeiten
data = request.json
event = data['event']
if event == 'site.created':
site_id = data['data']['site_id']
domain = data['data']['domain']
# Ihre Logik hier...
return {'status': 'ok'}, 200
Beispiel: Node.js¶
const crypto = require('crypto');
const express = require('express');
const app = express();
const SECRET = 'IhrGeheimesWebhookSecret';
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'] || '';
const expected = 'sha256=' + crypto
.createHmac('sha256', SECRET)
.update(req.body)
.digest('hex');
if (!crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
)) {
return res.status(403).json({ error: 'Invalid signature' });
}
const data = JSON.parse(req.body);
console.log(`Event: ${data.event}`, data.data);
res.json({ status: 'ok' });
});
app.listen(3000);
Signatur immer prüfen
Verarbeiten Sie Webhook-Payloads niemals ohne Signaturprüfung. Ohne Verifizierung könnte ein Angreifer gefälschte Ereignisse an Ihre URL senden.
Timing-sichere Vergleiche
Verwenden Sie immer timing-sichere Vergleichsfunktionen (hash_equals in PHP, hmac.compare_digest in Python, crypto.timingSafeEqual in Node.js), um Timing-Angriffe zu verhindern.
Retry-Verhalten¶
Wenn Ihr Server nicht mit einem HTTP-Statuscode im Bereich 2xx antwortet, führt das Panel automatisch einen Retry durch:
| Versuch | Zeitpunkt |
|---|---|
| 1. Versuch | Sofort |
| 2. Versuch (Retry) | 2 Sekunden nach dem ersten Fehlschlag |
Nach zwei Fehlversuchen wird die Zustellung als fehlgeschlagen markiert und im Delivery-Log protokolliert.
Timeout
Ihr Server muss innerhalb von 10 Sekunden antworten. Anfragen, die länger dauern, werden als fehlgeschlagen gewertet.
Empfehlungen für Ihren Webhook-Server¶
- Antworten Sie sofort mit HTTP 200 und verarbeiten Sie den Payload asynchron
- Implementieren Sie Idempotenz — derselbe Event kann doppelt zugestellt werden
- Loggen Sie eingehende Webhooks für Debugging-Zwecke
Delivery-Logs¶
Das Panel speichert die letzten 100 Zustellversuche pro Webhook-Endpoint.
Logs abrufen¶
Log-Einträge¶
| Feld | Beschreibung |
|---|---|
id |
Eindeutige ID des Zustellversuchs |
event |
Ausgelöstes Ereignis |
payload |
Der gesendete JSON-Payload |
status_code |
HTTP-Statuscode der Antwort (0 bei Verbindungsfehler) |
response |
Antwort-Body Ihres Servers (max. 4 KB) |
success |
Ob die Zustellung erfolgreich war |
duration_ms |
Dauer der Anfrage in Millisekunden |
created_at |
Zeitpunkt des Zustellversuchs |
Logs im Panel einsehen¶
- Navigieren Sie zu Einstellungen → Webhooks
- Klicken Sie auf einen Webhook-Endpoint
- Im Tab Zustellungen sehen Sie den Verlauf aller Zustellversuche
Test-Webhook senden¶
Um Ihre Integration zu testen, können Sie ein Test-Ereignis manuell auslösen:
Dies sendet ein webhook.test-Ereignis mit Testdaten an die konfigurierte URL.
Oder im Panel:
- Öffnen Sie den Webhook-Endpoint
- Klicken Sie auf Test senden
- Prüfen Sie die Zustellung im Delivery-Log
Webhook verwalten¶
Endpoint aktualisieren¶
PUT /api/v1/webhooks/:id
Authorization: Bearer <token>
Content-Type: application/json
{
"url": "https://neue-url.de/webhook",
"events": "site.created,domain.created",
"active": true
}
Endpoint löschen¶
Endpoint deaktivieren¶
Setzen Sie active auf false, um einen Endpoint vorübergehend zu deaktivieren, ohne ihn zu löschen:
Best Practices¶
| Empfehlung | Beschreibung |
|---|---|
| HTTPS verwenden | Nutzen Sie immer HTTPS für Ihre Webhook-URL |
| Signatur prüfen | Verifizieren Sie jede Anfrage mit dem HMAC-Secret |
| Schnell antworten | Antworten Sie innerhalb von 2 Sekunden, verarbeiten Sie asynchron |
| Idempotenz | Rechnen Sie damit, dass Events doppelt zugestellt werden |
| Fehlertoleranz | Loggen und monitoren Sie fehlgeschlagene Zustellungen |
| Secret rotieren | Ändern Sie Ihr Webhook-Secret regelmäßig |
| IP-Whitelist | Beschränken Sie den Zugriff auf Ihre Webhook-URL auf die Panel-IP |