Zum Hauptinhalt springen

Webhooks

Erhalten Sie Benachrichtigungen in Echtzeit, sobald Ereignisse eintreten

8 Min. Lesezeit

Leitfaden zu Webhooks

Die Ereigniszustellung ist noch nicht live. Sie können Webhook-Endpunkte heute bereits über das Entwicklerportal oder die unten beschriebene API anlegen und testen, und die Schaltfläche „Webhook testen“ stellt tatsächlich einen Test-Payload zu. Operate versendet echte Kontoereignisse (invoice.paid, payment.received usw.) jedoch noch nicht automatisch, sobald sie eintreten – dieser Teil des Leitfadens beschreibt das vorgesehene Verhalten nach dem Go-live der Ereigniszustellung, nicht den heutigen Stand.

Mit Webhooks erhalten Sie Benachrichtigungen in Echtzeit, sobald in Ihrem Operate-Konto Ereignisse eintreten. Statt die API laufend abzufragen, schieben Webhooks die Daten an Ihren Server, sobald ein Ereignis auftritt.

So funktionieren Webhooks

  1. Sie registrieren die URL eines Webhook-Endpunkts
  2. Sie wählen aus, welche Ereignisse Sie abonnieren möchten
  3. Tritt ein Ereignis ein, sendet Operate einen HTTP-POST an Ihre URL
  4. Ihr Server verarbeitet das Ereignis und antwortet mit 200 OK

Webhooks einrichten

Über das Dashboard

  1. Öffnen Sie Entwicklerportal > Webhooks (/developer/webhooks)
  2. Klicken Sie auf Webhook-Endpunkt erstellen
  3. Geben Sie die URL Ihres Endpunkts ein (im Produktivbetrieb zwingend HTTPS)
  4. Wählen Sie die Ereignisse aus, die Sie erhalten möchten
  5. Klicken Sie auf Erstellen

Über die API

const response = await fetch('https://operate.guru/api/v1/webhooks/endpoints', { method: 'POST', headers: { 'Authorization': 'Bearer op_live_your_api_key', 'Content-Type': 'application/json' }, body: JSON.stringify({ url: 'https://your-server.com/webhooks/operate', events: ['INVOICE_CREATED', 'INVOICE_PAID', 'PAYMENT_RECEIVED'], description: 'Production webhook' }) }); const { endpoint, secret } = await response.json(); // Save the secret securely - it's only shown once!

Ereignistypen

Ereignisse zu Ausgangsrechnungen

  • INVOICE_CREATED – neue Rechnung erstellt
  • INVOICE_SENT – Rechnung an Kundin oder Kunden versendet
  • INVOICE_PAID – Rechnung vollständig bezahlt
  • INVOICE_PARTIALLY_PAID – Teilzahlung eingegangen
  • INVOICE_OVERDUE – Rechnung überfällig
  • INVOICE_VOIDED – Rechnung storniert

Ereignisse zu Eingangsrechnungen

  • BILL_CREATED – neue Eingangsrechnung erhalten
  • BILL_APPROVED – Eingangsrechnung zur Zahlung freigegeben
  • BILL_PAID – Eingangsrechnung bezahlt
  • BILL_OVERDUE – Eingangsrechnung überfällig

Zahlungsereignisse

  • PAYMENT_RECEIVED – Zahlung eingegangen
  • PAYMENT_FAILED – Zahlung fehlgeschlagen

Ereignisse zu Kundinnen/Kunden und Lieferanten

  • CLIENT_CREATED – neue Kundin bzw. neuer Kunde angelegt
  • CLIENT_UPDATED – Kundendatensatz aktualisiert
  • VENDOR_CREATED – neuer Lieferant angelegt
  • VENDOR_UPDATED – Lieferantendatensatz aktualisiert

Bankereignisse

  • BANK_TRANSACTION_IMPORTED – neue Transaktion importiert
  • BANK_TRANSACTION_RECONCILED – Transaktion abgeglichen

Ereignisse zu Bestellungen

  • PURCHASE_ORDER_CREATED – neue Bestellung angelegt
  • PURCHASE_ORDER_APPROVED – Bestellung freigegeben
  • PURCHASE_ORDER_RECEIVED – Ware erhalten

Steuerereignisse

  • TAX_RETURN_DUE – Steuererklärung wird demnächst fällig
  • TAX_FILING_SUBMITTED – Steuererklärung übermittelt

Webhook-Payload

Alle Webhooks haben ein einheitliches Format:

{ "id": "evt_abc123", "type": "INVOICE_PAID", "created": "2024-01-15T10:30:00Z", "data": { "id": "inv_xyz789", "number": "INV-2024-001", "customerName": "Acme Corp", "totalAmount": 1500.00, "currency": "EUR", "paidAt": "2024-01-15T10:30:00Z" } }

Signaturen prüfen

Prüfen Sie Webhook-Signaturen immer, um sicherzustellen, dass die Anfragen tatsächlich von Operate stammen.

Signatur-Header

X-Webhook-Signature: sha256=abc123...
X-Webhook-Event: INVOICE_PAID
X-Webhook-Delivery-Id: del_xyz789

Prüfcode (Node.js)

const crypto = require('crypto'); function verifyWebhookSignature(payload, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(`sha256=${expectedSignature}`) ); } // Express.js example app.post('/webhooks/operate', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-webhook-signature']; const payload = req.body.toString(); if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(payload); switch (event.type) { case 'INVOICE_PAID': handleInvoicePaid(event.data); break; case 'PAYMENT_RECEIVED': handlePaymentReceived(event.data); break; } res.status(200).send('OK'); });

Prüfcode (Python)

import hmac import hashlib def verify_webhook_signature(payload, signature, secret): expected = hmac.new( secret.encode(), payload.encode(), hashlib.sha256 ).hexdigest() return hmac.compare_digest(f'sha256={expected}', signature)

Wiederholungsstrategie

Antwortet Ihr Endpunkt nicht innerhalb von 30 Sekunden mit einem 2xx-Status, wiederholen wir die Zustellung:

VersuchVerzögerung
1sofort
21 Minute
35 Minuten
430 Minuten

Nach 4 fehlgeschlagenen Versuchen gilt die Zustellung als gescheitert.

Webhooks testen

Über den Test-Endpunkt

// Send a test webhook await fetch('https://operate.guru/api/v1/webhooks/endpoints/wh_abc123/test', { method: 'POST', headers: { 'Authorization': 'Bearer op_live_your_api_key' } });

Mit ngrok in der lokalen Entwicklung

# Expose local server ngrok http 3000 # Use the ngrok URL for your webhook endpoint # https://abc123.ngrok.io/webhooks/operate

Mehrfachzustellungen behandeln

Webhooks können mehr als einmal zugestellt werden (Netzwerkprobleme, Wiederholungen usw.). Ihr Endpunkt muss daher idempotent sein.

Idempotenz-Muster

const processedEvents = new Set(); // Or use a database app.post('/webhooks/operate', async (req, res) => { const event = req.body; const eventId = event.id; // Check if already processed if (processedEvents.has(eventId)) { console.log(`Event ${eventId} already processed, skipping`); return res.status(200).send('OK'); } // Process event await processEvent(event); // Mark as processed processedEvents.add(eventId); // Store in DB for persistence across restarts res.status(200).send('OK'); });

Mit einer Datenbank

// Check if event already processed const existing = await db.webhookEvents.findUnique({ where: { eventId: event.id } }); if (existing) { return res.status(200).send('Already processed'); } // Process event await processEvent(event); // Mark as processed await db.webhookEvents.create({ data: { eventId: event.id, processedAt: new Date(), eventType: event.type } });

Muster für asynchrone Verarbeitung

Blockieren Sie die Webhook-Antwort nicht – verarbeiten Sie asynchron:

Mit einer Queue

const Queue = require('bull'); const webhookQueue = new Queue('webhooks'); app.post('/webhooks/operate', async (req, res) => { const signature = req.headers['x-webhook-signature']; const payload = req.body; // Verify signature (fast) if (!verifySignature(payload, signature, SECRET)) { return res.status(401).send('Invalid signature'); } // Add to queue (fast) await webhookQueue.add(payload); // Respond immediately res.status(200).send('Queued'); }); // Process queue in background webhookQueue.process(async (job) => { const event = job.data; await processEvent(event); });

Mit Workern

const { Worker } = require('worker_threads'); app.post('/webhooks/operate', async (req, res) => { // Verify signature // ... // Spawn worker const worker = new Worker('./webhook-processor.js', { workerData: req.body }); // Respond immediately res.status(200).send('Processing'); // Handle worker completion/error in background worker.on('message', (result) => { console.log('Worker completed:', result); }); });

Beispiele für Ereignisse

Ereignis INVOICE_PAID

{ "id": "evt_abc123", "type": "INVOICE_PAID", "created": "2024-01-15T10:30:00Z", "data": { "id": "inv_xyz789", "number": "INV-2024-001", "customerName": "Acme Corp", "customerId": "client_123", "totalAmount": 1500.00, "currency": "EUR", "paidAt": "2024-01-15T10:30:00Z", "paymentMethod": "BANK_TRANSFER", "transactionId": "txn_456" } }

Ereignis TRANSACTION_IMPORTED

{ "id": "evt_def456", "type": "BANK_TRANSACTION_IMPORTED", "created": "2024-01-15T08:00:00Z", "data": { "id": "txn_789", "accountId": "acc_123", "amount": -250.50, "currency": "EUR", "date": "2024-01-14", "description": "Office supplies", "category": "OFFICE_SUPPLIES", "vendor": "Staples", "matched": false } }

Ereignis PURCHASE_ORDER_RECEIVED

{ "id": "evt_ghi789", "type": "PURCHASE_ORDER_RECEIVED", "created": "2024-01-15T14:20:00Z", "data": { "id": "po_456", "vendorName": "Supplier Co", "totalAmount": 5000.00, "currency": "EUR", "status": "RECEIVED", "receivedAt": "2024-01-15T14:20:00Z", "receivedBy": "John Smith", "items": [ { "description": "Office Supplies", "quantityOrdered": 100, "quantityReceived": 95, "unitPrice": 5.50 } ] } }

Fehlersuche bei Webhooks

Protokollierung aktivieren

app.post('/webhooks/operate', (req, res) => { console.log('Webhook received:', { eventId: req.body.id, eventType: req.body.type, timestamp: new Date().toISOString(), signature: req.headers['x-webhook-signature'] }); // Process... });

Test mit curl

curl -X POST https://your-server.com/webhooks/operate \ -H "Content-Type: application/json" \ -H "X-Webhook-Signature: sha256=test123" \ -H "X-Webhook-Event: INVOICE_PAID" \ -d '{ "id": "evt_test", "type": "INVOICE_PAID", "created": "2024-01-15T10:30:00Z", "data": { "id": "inv_123" } }'

Zustellprotokolle ansehen

Den Zustellstatus Ihrer Webhooks finden Sie im Operate-Dashboard:

  1. Öffnen Sie Entwicklerportal > Webhooks (/developer/webhooks)
  2. Klicken Sie auf den Namen des Webhook-Endpunkts
  3. Öffnen Sie den Reiter Letzte Zustellungen

Angezeigt werden:

  • Zeitstempel der Zustellung
  • zurückgegebener HTTP-Statuscode
  • Antwortzeit
  • Wiederholungsversuche
  • Fehlermeldungen (bei Fehlschlag)

Sicherheits-Checkliste für Webhooks

✅ Signaturen prüfen – bei jeder Anfrage ✅ HTTPS verwenden – für Ihren Endpunkt (im Produktivbetrieb zwingend) ✅ 200 zurückgeben – innerhalb von 30 Sekunden ✅ Asynchron verarbeiten – die Antwort nicht blockieren ✅ Mehrfachzustellungen behandeln – idempotente Verarbeitung ✅ Payload validieren – die Struktur vor der Verarbeitung prüfen ✅ Alle Ereignisse protokollieren – für die Fehlersuche ✅ Secrets rotieren – alle 90 Tage ✅ Fehlschläge überwachen – und Alarme einrichten ✅ Gründlich testen – vor dem Go-live

Bewährte Vorgehensweisen

  1. Schnell antworten – sofort 200 OK zurückgeben und asynchron in Queue oder Worker verarbeiten
  2. Idempotent sein – Mehrfachzustellungen sauber über die Ereignis-ID abfangen
  3. Signaturen prüfen – die Echtheit eines Webhooks immer per HMAC validieren
  4. Alles protokollieren – Aufzeichnungen für Fehlersuche und Nachvollziehbarkeit aufbewahren
  5. Fehler sauber behandeln – die Verarbeitung einreihen, wenn Ihr System nicht erreichbar ist
  6. HTTPS verwenden – im Produktivbetrieb aus Sicherheitsgründen zwingend
  7. Überwachung einrichten – bei fehlgeschlagenen Zustellungen alarmieren
  8. Mit ngrok testen – lokal testen, bevor Sie in den Produktivbetrieb gehen
  9. Secrets regelmäßig rotieren – mindestens alle 90 Tage
  10. Ihren Endpunkt dokumentieren – damit spätere Wartung leichtfällt

Zustellverlauf ansehen

Den Zustellstatus Ihrer Webhooks finden Sie im Dashboard oder über die API:

// Get delivery history const deliveries = await fetch( 'https://operate.guru/api/v1/webhooks/deliveries?endpointId=wh_abc123', { headers: { 'Authorization': 'Bearer op_live_your_api_key' } } ).then(r => r.json());

Secrets rotieren

Rotieren Sie Ihr Webhook-Secret aus Sicherheitsgründen regelmäßig:

await fetch('https://operate.guru/api/v1/webhooks/endpoints/wh_abc123/rotate-secret', { method: 'POST', headers: { 'Authorization': 'Bearer op_live_your_api_key' } });

Nächste Schritte

    Webhooks | Operate