Zuverlässige Webhooks entwickeln: Tipps & Best Practices

Ashley Innocent

Ashley Innocent

13 March 2026

Zuverlässige Webhooks entwickeln: Tipps & Best Practices

Apidog für Unternehmen

On-Premises Bereitstellung

SSO & RBAC

SOC 2 konform

Apidog Enterprise entdecken

Kurz gesagt

Entwickeln Sie zuverlässige Webhooks mit exponentiellem Backoff-Retry (5-10 Versuche), Idempotenzschlüsseln, HMAC-Signaturprüfung und 5-Sekunden-Timeouts. Geben Sie sofort 2xx zurück und verarbeiten Sie asynchron. Die moderne PetstoreAPI implementiert Webhooks für Bestellaktualisierungen, Haustieradoptionen und Zahlungsbenachrichtigungen mit vollständiger Wiederholungslogik und Sicherheit.

Einleitung

Sie senden einen Webhook, um einen Client darüber zu informieren, dass sein Haustier adoptiert wurde. Der Server des Clients ist ausgefallen. Ihr Webhook schlägt fehl. Versuchen Sie es erneut? Wie oft? Was, wenn der Client den Webhook zweimal erhält und dem Kunden zweimal Gebühren berechnet?

Webhooks sind HTTP-Callbacks, die Ereignisse an Client-URLs senden. Sie sind theoretisch einfach, in der Praxis jedoch komplex. Netzwerke fallen aus, Server stürzen ab, und Clients haben Fehler. Produktions-Webhooks benötigen eine Wiederholungslogik, Idempotenz, Sicherheit und Überwachung.

Die moderne PetstoreAPI implementiert produktionsreife Webhooks für Bestellaktualisierungen, Haustieradoptionen und Zahlungsbenachrichtigungen. Jeder Webhook beinhaltet Wiederholungslogik, Signaturprüfung und Idempotenz.

💡
Wenn Sie Webhooks entwickeln oder testen, hilft Ihnen Apidog dabei, die Webhook-Zustellung zu testen, Signaturen zu validieren und Fehlerfälle zu simulieren. Sie können die Wiederholungslogik testen und die Idempotenzbehandlung überprüfen.
Schaltfläche

In diesem Leitfaden erfahren Sie, wie Sie zuverlässige Webhooks mithilfe der Muster der modernen PetstoreAPI entwerfen.

Grundlagen von Webhooks

Webhooks sind HTTP-POST-Anfragen, die bei Ereignissen an vom Client bereitgestellte URLs gesendet werden.

Wie Webhooks funktionieren

1. Client registriert Webhook-URL:

POST /webhooks
{
  "url": "https://client.com/webhooks/petstore",
  "events": ["pet.adopted", "order.completed"]
}

2. Ereignis tritt ein (Haustier adoptiert)

3. Server sendet Webhook:

POST https://client.com/webhooks/petstore
Content-Type: application/json
X-Webhook-Signature: sha256=abc123...

{
  "event": "pet.adopted",
  "data": {
    "petId": "019b4132",
    "userId": "user-456",
    "timestamp": "2026-03-13T10:30:00Z"
  }
}

4. Client antwortet:

200 OK

Das Zuverlässigkeitsproblem

Webhooks können aus vielen Gründen fehlschlagen:

Ohne Wiederholungslogik gehen Ereignisse verloren. Ohne Idempotenz führen doppelte Webhooks zu doppelten Aktionen.

Wiederholungslogik mit exponentiellem Backoff

Fehlgeschlagene Webhooks mit zunehmenden Verzögerungen wiederholen.

Exponentielle Backoff-Strategie

Versuch 1: Sofort
Versuch 2: 1 Sekunde später
Versuch 3: 2 Sekunden später
Versuch 4: 4 Sekunden später
Versuch 5: 8 Sekunden später
Versuch 6: 16 Sekunden später

Warum exponentiell? Wenn der Client ausgefallen ist, hilft es nicht, ihn mit Wiederholungsversuchen zu bombardieren. Exponentieller Backoff gibt Zeit zur Erholung.

Implementierung

async function sendWebhook(url, payload, attempt = 1, maxAttempts = 6) {
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Webhook-Signature': generateSignature(payload)
      },
      body: JSON.stringify(payload),
      timeout: 5000 // 5 second timeout
    });

    if (response.ok) {
      return { success: true, attempt };
    }

    // Retry on 5xx errors
    if (response.status >= 500 && attempt < maxAttempts) {
      const delay = Math.pow(2, attempt - 1) * 1000;
      await sleep(delay);
      return sendWebhook(url, payload, attempt + 1, maxAttempts);
    }

    // Don't retry 4xx errors (client error)
    return { success: false, status: response.status };

  } catch (error) {
    // Network error or timeout - retry
    if (attempt < maxAttempts) {
      const delay = Math.pow(2, attempt - 1) * 1000;
      await sleep(delay);
      return sendWebhook(url, payload, attempt + 1, maxAttempts);
    }
    return { success: false, error: error.message };
  }
}

Wann wiederholen?

Wiederholen bei:

Nicht wiederholen bei:

Dead Letter Queue

Nach maximalen Wiederholungsversuchen, verschieben Sie fehlgeschlagene Webhooks zur manuellen Überprüfung in eine Dead Letter Queue:

if (!result.success) {
  await deadLetterQueue.add({
    url,
    payload,
    attempts: maxAttempts,
    lastError: result.error,
    timestamp: new Date()
  });
}

Idempotenz zur Vermeidung von Duplikaten

Clients können denselben Webhook mehrmals erhalten. Idempotenz verhindert doppelte Verarbeitung.

Idempotenzschlüssel

Fügen Sie jedem Webhook eine eindeutige ID hinzu:

{
  "id": "webhook_019b4132",
  "event": "pet.adopted",
  "data": {...}
}

Client speichert verarbeitete IDs:

app.post('/webhooks/petstore', async (req, res) => {
  const webhookId = req.body.id;

  // Check if already processed
  const processed = await db.webhooks.findOne({ id: webhookId });
  if (processed) {
    return res.status(200).json({ message: 'Already processed' });
  }

  // Process webhook
  await processPetAdoption(req.body.data);

  // Mark as processed
  await db.webhooks.insert({ id: webhookId, processedAt: new Date() });

  res.status(200).json({ message: 'Processed' });
});

Idempotente Operationen

Operationen idempotent gestalten:

Schlecht (nicht idempotent):

// Charging twice causes double charge
await chargeCustomer(userId, amount);

Gut (idempotent):

// Charging with idempotency key prevents double charge
await chargeCustomer(userId, amount, { idempotencyKey: webhookId });

Signaturprüfung für die Sicherheit

Überprüfen Sie, ob Webhooks von Ihrer API stammen und nicht von einem Angreifer.

HMAC-Signatur

Signatur mit gemeinsamem Geheimnis generieren:

// Server generates signature
const crypto = require('crypto');

function generateSignature(payload, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(JSON.stringify(payload));
  return hmac.digest('hex');
}

// Include in header
headers['X-Webhook-Signature'] = `sha256=${generateSignature(payload, webhookSecret)}`;

Client verifiziert Signatur:

function verifySignature(payload, signature, secret) {
  const expected = generateSignature(payload, secret);
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}

app.post('/webhooks/petstore', (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
  ...
});

Zeitstempel-Validierung

Fügen Sie einen Zeitstempel hinzu, um Replay-Angriffe zu verhindern:

{
  "id": "webhook_019b4132",
  "timestamp": "2026-03-13T10:30:00Z",
  "event": "pet.adopted",
  "data": {...}
}

Alte Webhooks ablehnen:

const webhookAge = Date.now() - new Date(req.body.timestamp);
if (webhookAge > 5 * 60 * 1000) { // 5 minutes
  return res.status(400).json({ error: 'Webhook too old' });
}

Timeout-Behandlung

Legen Sie aggressive Timeouts fest, um zu verhindern, dass langsame Clients Ihr System blockieren.

5-Sekunden-Timeout

const response = await fetch(url, {
  method: 'POST',
  body: JSON.stringify(payload),
  timeout: 5000 // 5 seconds
});

Warum 5 Sekunden? Webhooks sollten sofort zurückkehren. Wenn ein Client länger braucht, führt er synchrone Verarbeitung durch (falsches Muster).

Asynchrones Verarbeitungsmuster

Schlecht (synchron):

app.post('/webhooks/petstore', async (req, res) => {
  // This takes 30 seconds - webhook will timeout
  await processOrder(req.body.data);
  await sendEmail(req.body.data);
  await updateInventory(req.body.data);

  res.status(200).json({ message: 'Processed' });
});

Gut (asynchron):

app.post('/webhooks/petstore', async (req, res) => {
  // Return immediately
  res.status(200).json({ message: 'Received' });

  // Process asynchronously
  queue.add('process-webhook', req.body);
});

Wie die moderne PetstoreAPI Webhooks implementiert

Die moderne PetstoreAPI implementiert produktionsreife Webhooks.

Webhook-Ereignisse

pet.adopted - Haustier wurde adoptiert
pet.status_changed - Status des Haustiers geändert
order.created - Bestellung erstellt
order.completed - Bestellung abgeschlossen
payment.succeeded - Zahlung erfolgreich
payment.failed - Zahlung fehlgeschlagen

Webhook-Payload

{
  "id": "webhook_019b4132-70aa-764f-b315-e2803d882a24",
  "event": "pet.adopted",
  "timestamp": "2026-03-13T10:30:00Z",
  "data": {
    "petId": "019b4132-70aa-764f-b315-e2803d882a24",
    "userId": "user-456",
    "orderId": "order-789",
    "adoptionDate": "2026-03-13"
  },
  "apiVersion": "v1"
}

Wiederholungskonfiguration

Sicherheit

Testen von Webhooks mit Apidog

Apidog unterstützt das Testen von Webhooks.

Webhook-Zustellung testen

  1. Mock-Webhook-Endpunkt in Apidog erstellen
  2. Endpunkt bei der PetstoreAPI registrieren
  3. Ereignis auslösen (Haustier adoptieren)
  4. Verifizieren, ob Webhook empfangen wurde
  5. Payload-Format überprüfen

Signaturprüfung testen

// Apidog test script
const signature = pm.request.headers.get('X-Webhook-Signature');
const payload = pm.request.body.raw;
const secret = pm.environment.get('WEBHOOK_SECRET');

const expected = generateSignature(payload, secret);
pm.test('Signature valid', () => {
  pm.expect(signature).to.equal(`sha256=${expected}`);
});

Wiederholungslogik testen

  1. 500er-Fehler vom Mock-Endpunkt zurückgeben
  2. Wiederholungsversuche mit exponentiellem Backoff überprüfen
  3. Dead Letter Queue nach maximalen Wiederholungsversuchen prüfen

Idempotenz testen

  1. Webhook empfangen
  2. 200 zurückgeben
  3. Denselben Webhook erneut empfangen (simulierter Wiederholungsversuch)
  4. Verifizieren, dass keine doppelte Verarbeitung stattfindet

Fazit

Zuverlässige Webhooks erfordern:

Die moderne PetstoreAPI implementiert all diese Muster. Sehen Sie in der Webhook-Dokumentation nach vollständigen Beispielen.

Testen Sie Ihre Webhooks mit Apidog, um die Wiederholungslogik, Signaturen und Idempotenz vor der Produktivsetzung zu überprüfen.

Schaltfläche

FAQ

Wie viele Wiederholungsversuche sollten Webhooks haben?

5-10 Versuche mit exponentiellem Backoff. Dies deckt vorübergehende Ausfälle (5-17 Minuten) ab, ohne den Client zu überlasten.

Sollten Webhooks bei 4xx-Fehlern erneut versuchen?

Nein. 4xx-Fehler weisen auf Client-Probleme hin (falsche URL, Authentifizierungsfehler). Ein erneuter Versuch wird diese nicht beheben. Wiederholen Sie nur bei 5xx-Fehlern und Netzwerkfehlern.

Wie lang sollten Webhook-Timeouts sein?

Maximal 5 Sekunden. Clients sollten sofort 200 zurückgeben und asynchron verarbeiten. Längere Timeouts deuten darauf hin, dass der Client eine synchrone Verarbeitung durchführt.

Was, wenn ein Client nie auf Webhooks antwortet?

Nach maximalen Wiederholungsversuchen in die Dead Letter Queue verschieben. Den Client per E-Mail benachrichtigen. Erwägen Sie, Webhooks für diesen Client nach wiederholten Fehlern zu deaktivieren.

Sollten Webhook-URLs HTTPS sein?

Ja, fordern Sie immer HTTPS. HTTP-Webhooks können abgefangen und verändert werden. Die moderne PetstoreAPI lehnt HTTP-Webhook-URLs ab.

Wie verhindern Sie Replay-Angriffe?

Fügen Sie einen Zeitstempel in die Payload ein und lehnen Sie Webhooks ab, die älter als 5 Minuten sind. Kombinieren Sie dies mit der Signaturprüfung.

Können Clients eine erneute Zustellung von Webhooks anfordern?

Ja. Die moderne PetstoreAPI bietet einen Endpunkt zur erneuten Zustellung spezifischer Webhooks: POST /webhooks/{id}/redeliver

Wie testen Sie Webhooks lokal?

Verwenden Sie Tools wie ngrok, um localhost dem Internet zugänglich zu machen, oder nutzen Sie den Mock-Server von Apidog, um Webhook-Endpunkte während der Entwicklung zu simulieren.

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen