Webhooks
Erhalten Sie Echtzeit-Benachrichtigungen, wenn Ereignisse in Kanman auftreten. Vollständige Anleitung zur Webhook-Konfiguration, Ereignissen und Payloads.
Webhooks ermöglichen es Ihnen, Echtzeit-HTTP-Benachrichtigungen zu erhalten, wenn Ereignisse in Kanman auftreten. Anstatt ständig die API abzufragen, um nach Änderungen zu suchen, senden Webhooks Updates an Sie, sobald etwas passiert. Das macht sie perfekt für den Aufbau reaktionsschneller Integrationen, das Senden von Benachrichtigungen an Team-Chat-Apps, das Synchronisieren von Daten mit externen Systemen und das Auslösen automatisierter Workflows.
Wenn ein relevantes Ereignis auftritt – wie das Erstellen oder Abschließen einer Aufgabe – sendet Kanman sofort eine HTTP-POST-Anfrage an Ihren angegebenen Endpunkt mit allen Details. Ihr Server kann diese Informationen dann nach Bedarf verarbeiten: eine externe Datenbank aktualisieren, eine Slack-Nachricht senden, eine CI/CD-Pipeline auslösen oder alles andere, was Sie sich vorstellen können.
Übersicht
Wenn Sie einen Webhook konfigurieren:
- Sie geben eine URL-Endpunkt an
- Sie wählen, welche Ereignisse Sie empfangen möchten
- Wenn diese Ereignisse auftreten, sendet Kanman einen HTTP POST an Ihre URL
- Ihr Server verarbeitet die Benachrichtigung
Webhook erstellen
- Gehen Sie zu Einstellungen > Integrationen > Webhooks
- Klicken Sie auf Webhook erstellen
- Konfigurieren Sie:
- Name: Beschreibender Name (z.B. “Slack Benachrichtigungen”)
- URL: Ihr Endpunkt (muss HTTPS sein)
- Ereignisse: Wählen Sie zu empfangende Ereignisse
- Secret: Auto-generiert oder benutzerdefiniert (für Signaturverifizierung)
- Klicken Sie auf Erstellen
Webhook-Eigenschaften
| Eigenschaft | Beschreibung |
|---|---|
name |
Beschreibender Name (1-100 Zeichen) |
url |
Endpunkt-URL (HTTPS erforderlich) |
secret |
Gemeinsames Geheimnis für HMAC-Signaturen |
events |
Array von zu empfangenden Ereignistypen |
is_active |
Webhook aktivieren/deaktivieren |
Webhook-Limits
| Tarif | Max. Webhooks | Zustellungen/Monat |
|---|---|---|
| Pro | 5 | 12.000 |
| Teams | 20 | 60.000 |
Ereignisse
Aufgaben-Ereignisse
task.created
Wird ausgelöst, wenn eine neue Aufgabe erstellt wird.
{
"event": "task.created",
"timestamp": "2024-01-21T10:30:45Z",
"data": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"label": "Landingpage gestalten",
"status": 0,
"project_id": "660e8400-e29b-41d4-a716-446655440000",
"description": null,
"created_at": "2024-01-21T10:30:45Z"
}
}
task.updated
Wird ausgelöst, wenn eine Aufgabe geändert wird (Name, Status, Beschreibung oder Projekt).
{
"event": "task.updated",
"timestamp": "2024-01-21T11:15:00Z",
"data": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"label": "Landingpage gestalten",
"status": 1,
"project_id": "660e8400-e29b-41d4-a716-446655440000",
"description": "Aktualisierte Beschreibung",
"updated_at": "2024-01-21T11:15:00Z",
"changes": {
"status": {
"old": 0,
"new": 1
}
}
}
}
task.deleted
Wird ausgelöst, wenn eine Aufgabe soft-gelöscht wird (in den Papierkorb verschoben).
{
"event": "task.deleted",
"timestamp": "2024-01-21T14:00:00Z",
"data": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"label": "Landingpage gestalten",
"project_id": "660e8400-e29b-41d4-a716-446655440000",
"deleted_at": "2024-01-21T14:00:00Z"
}
}
task.moved
Wird ausgelöst, wenn eine Aufgabe in ein anderes Projekt verschoben oder neu angeordnet wird.
{
"event": "task.moved",
"timestamp": "2024-01-21T12:00:00Z",
"data": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"label": "Landingpage gestalten",
"from_project_id": "660e8400-e29b-41d4-a716-446655440000",
"to_project_id": "660e8400-e29b-41d4-a716-446655440001",
"position": "aab"
}
}
Projekt-Ereignisse
project.created
{
"event": "project.created",
"timestamp": "2024-01-21T09:00:00Z",
"data": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"label": "Q1 Marketing-Kampagne",
"board_id": "550e8400-e29b-41d4-a716-446655440000",
"description": null,
"created_at": "2024-01-21T09:00:00Z"
}
}
project.updated
{
"event": "project.updated",
"timestamp": "2024-01-21T10:00:00Z",
"data": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"label": "Q1 Marketing-Kampagne - Aktualisiert",
"board_id": "550e8400-e29b-41d4-a716-446655440000",
"description": "Neue Beschreibung",
"updated_at": "2024-01-21T10:00:00Z",
"changes": {
"label": {
"old": "Q1 Marketing-Kampagne",
"new": "Q1 Marketing-Kampagne - Aktualisiert"
}
}
}
}
project.deleted
{
"event": "project.deleted",
"timestamp": "2024-01-21T15:00:00Z",
"data": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"label": "Q1 Marketing-Kampagne",
"board_id": "550e8400-e29b-41d4-a716-446655440000",
"deleted_at": "2024-01-21T15:00:00Z"
}
}
Board-Ereignisse
board.created
{
"event": "board.created",
"timestamp": "2024-01-21T08:00:00Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"label": "Marketing",
"description": null,
"icon_name": "megaphone",
"created_at": "2024-01-21T08:00:00Z"
}
}
board.updated
{
"event": "board.updated",
"timestamp": "2024-01-21T09:30:00Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"label": "Marketing & Kommunikation",
"description": "Alle Marketing-Aktivitäten",
"updated_at": "2024-01-21T09:30:00Z",
"changes": {
"label": {
"old": "Marketing",
"new": "Marketing & Kommunikation"
}
}
}
}
board.deleted
{
"event": "board.deleted",
"timestamp": "2024-01-21T16:00:00Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"label": "Marketing",
"deleted_at": "2024-01-21T16:00:00Z"
}
}
Notiz-Ereignisse
note.created
{
"event": "note.created",
"timestamp": "2024-01-21T11:00:00Z",
"data": {
"id": "990e8400-e29b-41d4-a716-446655440000",
"title": "Meeting-Notizen",
"board_id": "550e8400-e29b-41d4-a716-446655440000",
"created_at": "2024-01-21T11:00:00Z"
}
}
note.updated
{
"event": "note.updated",
"timestamp": "2024-01-21T11:30:00Z",
"data": {
"id": "990e8400-e29b-41d4-a716-446655440000",
"title": "Meeting-Notizen - Aktualisiert",
"board_id": "550e8400-e29b-41d4-a716-446655440000",
"updated_at": "2024-01-21T11:30:00Z"
}
}
note.deleted
{
"event": "note.deleted",
"timestamp": "2024-01-21T17:00:00Z",
"data": {
"id": "990e8400-e29b-41d4-a716-446655440000",
"title": "Meeting-Notizen",
"board_id": "550e8400-e29b-41d4-a716-446655440000",
"deleted_at": "2024-01-21T17:00:00Z"
}
}
HTTP-Anfrage
Header
Jede Webhook-Anfrage enthält diese Header:
| Header | Beschreibung |
|---|---|
Content-Type |
application/json |
X-Kanman-Event |
Ereignistyp (z.B. task.created) |
X-Kanman-Delivery |
Eindeutige Zustellungs-ID (UUID) |
X-Kanman-Timestamp |
Unix-Zeitstempel des Ereignisses |
X-Kanman-Signature |
HMAC-SHA256-Signatur |
Signatur-Verifizierung
Verifizieren Sie die Webhook-Authentizität mit der Signatur:
const crypto = require('crypto');
function verifySignature(payload, signature, secret, timestamp) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${JSON.stringify(payload)}`)
.digest('hex');
return `sha256=${expectedSignature}` === signature;
}
// In Ihrem Webhook-Handler
app.post('/webhook', (req, res) => {
const signature = req.headers['x-kanman-signature'];
const timestamp = req.headers['x-kanman-timestamp'];
if (!verifySignature(req.body, signature, WEBHOOK_SECRET, timestamp)) {
return res.status(401).send('Ungültige Signatur');
}
// Webhook verarbeiten
const { event, data } = req.body;
console.log(`Empfangen ${event}:`, data);
res.status(200).send('OK');
});
Python-Beispiel
import hmac
import hashlib
import json
from flask import Flask, request
app = Flask(__name__)
WEBHOOK_SECRET = 'ihr_webhook_secret'
def verify_signature(payload, signature, timestamp):
message = f"{timestamp}.{json.dumps(payload)}"
expected = 'sha256=' + hmac.new(
WEBHOOK_SECRET.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-Kanman-Signature')
timestamp = request.headers.get('X-Kanman-Timestamp')
if not verify_signature(request.json, signature, timestamp):
return 'Ungültige Signatur', 401
event = request.json.get('event')
data = request.json.get('data')
print(f"Empfangen {event}: {data}")
return 'OK', 200
Antwort-Anforderungen
Ihr Webhook-Endpunkt sollte:
- 2xx-Status zurückgeben innerhalb von 10 Sekunden
- Schnell antworten - schwere Verarbeitung asynchron durchführen
- Idempotent sein - doppelte Zustellungen elegant behandeln
Gute Antwort
HTTP/1.1 200 OK
Schlechte Antwort
HTTP/1.1 500 Internal Server Error
Fehlerbehandlung
Automatisches Deaktivieren
Fehlgeschlagene Zustellungen erhöhen einen Fehlerzähler. Nach 5 aufeinanderfolgenden Fehlern wird der Webhook automatisch deaktiviert.
Wieder aktivieren
- Gehen Sie zu Einstellungen > Webhooks
- Finden Sie den deaktivierten Webhook
- Beheben Sie das zugrunde liegende Problem
- Klicken Sie auf Aktivieren
Webhook löschen
- Gehen Sie zu Einstellungen > Webhooks
- Klicken Sie auf den Webhook, um ihn zu öffnen
- Klicken Sie auf Löschen
- Bestätigen Sie das Löschen
Zustellungsverlauf
Sehen Sie kürzliche Zustellungen ein:
- Gehen Sie zu Einstellungen > Webhooks
- Klicken Sie auf einen Webhook
- Sehen Sie Letzte Zustellungen
Jede Zustellung zeigt:
- Ereignistyp
- Zeitstempel
- Antwortstatus
- Antwortzeit
- Payload (erweiterbar)
Die letzten 100 Zustellungen werden aufbewahrt.
Webhooks testen
Test-Zustellung
- Gehen Sie zu Einstellungen > Webhooks
- Klicken Sie auf einen Webhook
- Klicken Sie auf Test senden
- Ein Test-
ping-Ereignis wird gesendet
Test-Payload
{
"event": "ping",
"timestamp": "2024-01-21T10:00:00Z",
"data": {
"message": "Webhook-Test von Kanman"
}
}
Lokale Entwicklung
Für lokale Tests verwenden Sie einen Tunnel-Dienst:
# Mit ngrok
ngrok http 3000
# Verwenden Sie die generierte URL als Ihren Webhook-Endpunkt
# https://abc123.ngrok.io/webhook
Anwendungsfälle
Slack-Benachrichtigungen
Aufgaben-Updates an Slack senden:
app.post('/webhook', async (req, res) => {
const { event, data } = req.body;
if (event === 'task.created') {
await fetch(SLACK_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: `Neue Aufgabe erstellt: ${data.label}`
})
});
}
res.sendStatus(200);
});
Mit externem System synchronisieren
Eine externe Datenbank synchron halten:
app.post('/webhook', async (req, res) => {
const { event, data } = req.body;
switch (event) {
case 'task.created':
await externDB.tasks.create(data);
break;
case 'task.updated':
await externDB.tasks.update(data.id, data);
break;
case 'task.deleted':
await externDB.tasks.delete(data.id);
break;
}
res.sendStatus(200);
});
Analytics-Tracking
Aufgabenabschlüsse verfolgen:
app.post('/webhook', async (req, res) => {
const { event, data } = req.body;
if (event === 'task.updated' && data.changes?.status?.new === 2) {
await analytics.track('task_completed', {
taskId: data.id,
projectId: data.project_id,
completedAt: data.updated_at
});
}
res.sendStatus(200);
});
Best Practices
- Signaturen verifizieren - Webhook-Authentizität immer validieren
- Schnell antworten - Sofort 200 zurückgeben, asynchron verarbeiten
- Duplikate behandeln - Zustellungs-ID für Idempotenz verwenden
- Zustellungen protokollieren - Aufzeichnungen für Debugging behalten
- Fehler überwachen - Bei wiederholten Fehlern alarmieren
- HTTPS verwenden - Niemals unverschlüsselte HTTP-Endpunkte verwenden
Verwandte Themen
- API-Referenz - REST-API-Dokumentation
- Rate-Limits - Zustellungskontingente
- Authentifizierung - API-Token
Zuletzt aktualisiert: January 1, 0001
Kanman testen