Webhooks
Webhooks ermöglichen Ihrer Anwendung den Empfang von Echtzeit-HTTP-Callbacks, wenn Ereignisse in Ihrer Gäld-Organisation auftreten. Wenn ein Ereignis ausgelöst wird, sendet Gäld eine POST-Anfrage an jede registrierte Webhook-URL.
Webhook einrichten
Erstellen Sie einen Webhook über die API:
curl -X POST https://app.gaeld.ch/api/v1/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/gaeld",
"events": ["invoice.created", "invoice.finalized", "customer.created"],
"is_active": true
}'
Die Antwort enthält ein secret — speichern Sie es sicher, Sie benötigen es zur Signaturprüfung.
Ereignisse
| Ereignis | Wird ausgelöst, wenn |
|---|---|
invoice.created | Eine neue Rechnung erstellt wird |
invoice.updated | Eine Rechnung geändert wird |
invoice.deleted | Eine Rechnung gelöscht wird |
invoice.finalized | Eine Rechnung finalisiert (zur Bearbeitung gesperrt) wird |
invoice.payment_recorded | Eine Zahlung für eine Rechnung erfasst wird |
customer.created | Ein neuer Kunde erstellt wird |
customer.updated | Ein Kunde geändert wird |
customer.deleted | Ein Kunde gelöscht wird |
expense.created | Eine neue Ausgabe erstellt wird |
expense.updated | Eine Ausgabe geändert wird |
expense.deleted | Eine Ausgabe gelöscht wird |
expense.approved | Eine Ausgabe im Workflow genehmigt wird |
Verwenden Sie GET /api/v1/meta/webhook-events, um diese Liste programmatisch abzurufen.
Payload-Format
Jede Webhook-Zustellung sendet eine JSON-POST-Anfrage:
{
"event": "invoice.finalized",
"timestamp": "2025-06-01T12:00:00Z",
"data": {
"id": "uuid",
"number": "INV-2025-042",
"status": "finalized",
"customer": { "id": "uuid", "name": "ACME GmbH" },
"total": "1081.00",
"currency": "CHF"
}
}
Das Feld data enthält die vollständige Ressourcendarstellung (gleiches Format wie die Antwort des entsprechenden API-Endpunkts).
Anfrage-Header
Jede Webhook-Anfrage enthält diese Header:
| Header | Beschreibung |
|---|---|
Content-Type | application/json |
X-Webhook-Signature | HMAC-SHA256-Hex-Digest des Anfragekörpers |
X-Webhook-Event | Ereignisname (z. B. invoice.created) |
X-Webhook-Id | Eindeutige Zustellungs-ID |
User-Agent | Gaeld-Webhook/1.0 |
Signaturprüfung
Jede Webhook-Anfrage wird mit HMAC-SHA256 und dem Webhook-Secret signiert. Überprüfen Sie immer die Signatur, bevor Sie den Payload verarbeiten.
PHP
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$computed = hash_hmac('sha256', $payload, $webhookSecret);
if (! hash_equals($computed, $signature)) {
http_response_code(400);
exit('Invalid signature');
}
$event = json_decode($payload, true);
// $event verarbeiten
Node.js
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const computed = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(computed),
Buffer.from(signature)
);
}
// In Ihrem Express-Handler:
app.post('/webhooks/gaeld', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'];
if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(400).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Ereignis verarbeiten
res.sendStatus(200);
});
Python
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
computed = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(computed, signature)
Zustellung & Wiederholungsversuche
| Eigenschaft | Wert |
|---|---|
| HTTP-Timeout | 10 Sekunden |
| Max. Versuche | 3 |
| Wiederholungs-Backoff | 30 Sekunden, 5 Minuten, 1 Stunde |
| Erwartete Antwort | Jeder 2xx-Statuscode |
Wenn Ihr Endpunkt einen Nicht-2xx-Status zurückgibt oder ein Timeout auftritt, wiederholt Gäld mit exponentiellem Backoff. Nach 3 fehlgeschlagenen Versuchen wird die Zustellung als fehlgeschlagen markiert. Sie können den Zustellungsstatus über die Webhook-API überprüfen.
Webhooks verwalten
| Aktion | Methode | Endpunkt |
|---|---|---|
| Alle auflisten | GET | /api/v1/webhooks |
| Details anzeigen | GET | /api/v1/webhooks/{id} |
| Erstellen | POST | /api/v1/webhooks |
| Ereignisse/URL aktualisieren | PUT | /api/v1/webhooks/{id} |
| Löschen | DELETE | /api/v1/webhooks/{id} |
| Secret erneuern | POST | /api/v1/webhooks/{id}/regenerate-secret |
Nach dem Aufruf von regenerate-secret aktualisieren Sie Ihre Anwendung sofort mit dem neuen Secret. Das alte Secret wird ungültig und alle nachfolgenden Zustellungen verwenden das neue.
Best Practices
- Überprüfen Sie immer Signaturen — vertrauen Sie niemals dem Payload-Inhalt, ohne die HMAC-Signatur zu prüfen
- Antworten Sie schnell — geben Sie sofort
200zurück und verarbeiten Sie das Ereignis asynchron (z. B. über eine Job-Queue) - Behandeln Sie Duplikate — verwenden Sie den
X-Webhook-Id-Header zur Deduplizierung, falls Ihr Endpunkt mehrfach aufgerufen wird - Verwenden Sie HTTPS — Webhook-URLs müssen in der Produktion HTTPS verwenden
- Überwachen Sie Fehler — überprüfen Sie regelmässig den Webhook-Zustellungsstatus und beheben Sie fehlerhafte Endpunkte