
# Webhooks-API

Webhooks ermöglichen es der Plattform, Ihre anderen Systeme sofort zu benachrichtigen, wenn etwas passiert – ein neuer Kontakt, eine Antwort, ein gebuchter Termin und mehr. Diese API verwaltet die **Abonnements** selbst: welche URLs welche Ereignisse empfangen. Informationen zum Empfang und zur Überprüfung der Payloads, die Ihr Endpunkt erhält, finden Sie unter [Webhooks](../integrations/webhooks.md).

Alle unten aufgeführten Pfade sind relativ zur API-Basis-URL:

```
https://api.youraiconnector.com/v1
```

Jede Anfrage muss authentifiziert sein. Siehe [Authentifizierung](authentication.md) für die vier akzeptierten Methoden. Die Beispiele hier verwenden den `X-API-Key`-Header (und eine Abfrageparameter-Form für cURL).

::: note
**Hinweis:** Webhooks müssen für Ihr Konto aktiviert sein. Falls dies nicht der Fall ist, geben diese Endpunkte einen `403` zurück.
:::


---

## Wie Abonnements adressiert werden

Jedes Abonnement hat eine `id` und optional einen `name`. Beides kann als `{webhookId}` im Pfad für Aktualisierungen, Löschungen, Tests, Statusprüfungen und die erneute Aktivierung verwendet werden.

> **Bevorzugen Sie den Namen.** Abonnement-IDs sind positionsabhängig und können sich verschieben, nachdem ein anderes Abonnement gelöscht wurde. Wenn Sie beim Erstellen eines Abonnements einen stabilen `name` festlegen, adressieren Sie diesen über den Namen, um Überraschungen zu vermeiden.

---

## Abonnements auflisten

`GET /webhooks`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "webhooks": [
    {
      "id": "0",
      "name": "Order updates hook",
      "url": "https://hooks.example.com/incoming",
      "subscribed_to": ["Contact Created", "Replies"],
      "subscribed_to_tags": [],
      "created_at": "2026-06-09T12:00:00.000Z",
      "signing_enabled": true,
      "signing_secret_created_at": "2026-07-15T09:30:00.000Z",
      "retries_enabled": true,
      "enabled": true,
      "apply_to_sub_accounts": false
    }
  ]
}
```

`signing_enabled` und `retries_enabled` sind abonnementbasierte Opt-ins, die standardmäßig deaktiviert sind, sofern Sie sie nicht aktivieren. Siehe [Signierte Payloads](#signed-payloads) und [Wiederholungsversuche](#retries).

`apply_to_sub_accounts` ist das Opt-in für die Agentur-Vererbung – siehe [Ein Abonnement für alle Kundenkonten](#one-subscription-for-all-client-accounts-agencies). Standardmäßig deaktiviert und inaktiv bei Konten, die keine Kundenkonten haben.

`enabled` ist der Ein-/Ausschalter des Abonnements – siehe [Abonnement ausschalten](#switching-a-subscription-off). Ausgeschaltete Abonnements werden hier weiterhin aufgelistet.

Das Signierungsgeheimnis selbst ist hier nie enthalten – lesen Sie es aus [`GET /webhooks/{id}/signing-secret`](#read-the-signing-secret) aus.

---

## Abonnierbare Ereignistypen auflisten

Gibt die exakten Zeichenfolgen zurück, die Sie in `subscribed_to` verwenden können. Nutzen Sie dies, um gültige Ereignisnamen zu ermitteln, anstatt sie fest zu kodieren.

`GET /webhooks/events`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks/events" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/events", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks/events",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwort**

Die Antwort ist `{"success": true, "events": [...]}`, wobei `events` derzeit 22 exakte Zeichenfolgen enthält: Contact Created, Human Alerted, Appointment Booked, Replies, Reads, Deliveries, Credits Spent, Credits Recharged, Low Credit Balance, Contact Paused, Contact Do Not Disturb, Contact Unarchived, New Message, Contact Resumed, Chat Concluded, Task Created, Task Updated, Task Completed, Daily Summary Created, Channel Connected, Broadcast Started und Broadcast Completed (Channel Connected wird in `subscribed_to` akzeptiert, aber derzeit von nichts ausgegeben, daher sollten Sie nicht darauf aufbauen).

Was die einzelnen Ereignisse bedeuten und welchen `event`-Code sie im Payload senden, erfahren Sie unter [Die 22 Webhook-Ereignisse](../integrations/webhooks.md#the-22-webhook-events). Dieser Endpunkt ist jederzeit die maßgebliche Liste – lesen Sie sie live, anstatt die Namen fest zu kodieren.

---

## Abonnement erstellen

`POST /webhooks`

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `url` | Ja | HTTPS-URL, die Ereignis-Payloads über `POST` empfängt. Muss öffentlich erreichbar sein. |
| `subscribed_to` | Ja | Ein nicht leeres Array von Ereignisnamen (siehe `/webhooks/events`). |
| `name` | Nein | Ein Anzeigename. Kann später auch als `{webhookId}` verwendet werden. Standardmäßig ein Name mit Zeitstempel. |
| `subscribed_to_tags` | Nein | Tag-IDs, die einschränken, welche Tags eine Benachrichtigung zur Konversationszusammenfassung erzeugen. Dies schränkt die Ereignisse des Abonnements nicht auf diese Tags ein – um eine Anfrage zu erhalten, wenn ein bestimmtes Tag angewendet wird, legen Sie eine Webhook-URL für dieses Tag auf dem Tab **Tags** des Agenten (oder der Kampagne) fest. |
| `retries_enabled` | Nein | Boolescher Wert, Standardwert ist `false`. Opt-in für [Wiederholungsversuche](#retries) bei fehlgeschlagenen Zustellungen. |
| `generate_signing_secret` | Nein | Boolescher Wert, Standardwert ist `false`. Erstellen Sie ein HMAC-[Signaturgeheimnis](#signed-payloads) mit dem Abonnement. Das Geheimnis wird einmalig als `signing_secret` auf oberster Ebene in der Antwort zurückgegeben. |
| `enabled` | Nein | Boolescher Wert, Standardwert ist `true`. Übergeben Sie `false`, um das Abonnement deaktiviert zu erstellen. Siehe [Ein Abonnement ausschalten](#switching-a-subscription-off). |
| `apply_to_sub_accounts` | Nein | Boolescher Wert, Standardwert ist `false`. Bei einem Agenturkonto sorgt `true` dafür, dass dieses Abonnement auch Ereignisse von jedem Kundenkonto empfängt – siehe [Ein Abonnement für alle Kundenkonten](#one-subscription-for-all-client-accounts-agencies). |

> **URL-Regeln:** Die URL muss `https://` verwenden und öffentlich erreichbar sein. Einfaches `http://`, `localhost`, Adressen in privaten Netzwerken und interne Plattformadressen werden mit einem `400` abgelehnt.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "name": "Order updates hook"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://hooks.example.com/incoming",
    subscribed_to: ["Contact Created", "Replies"],
    name: "Order updates hook",
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "url": "https://hooks.example.com/incoming",
        "subscribed_to": ["Contact Created", "Replies"],
        "name": "Order updates hook",
    },
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "webhook_id": "1",
  "webhook": {
    "id": "1",
    "name": "Order updates hook",
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

---

## Abonnement aktualisieren

Geben Sie mindestens eines der Felder `url`, `subscribed_to`, `name`, `subscribed_to_tags`, `retries_enabled`, `enabled` oder `apply_to_sub_accounts` an. Weggelassene Felder behalten ihre aktuellen Werte bei. `subscribed_to` und `subscribed_to_tags` sind Ersetzungen, keine Zusammenführungen.

`PUT /webhooks/{webhookId}`

> Das Aktualisieren eines Abonnements beeinträchtigt niemals dessen Signierungsgeheimnis – verwalten Sie dies über die [Routen für Signierungsgeheimnisse](#signed-payloads).

> Wenn sich die URL ändert, wird die Zustellung für die neue URL automatisch wieder aktiviert, wodurch ein zuvor fehlerhafter Endpunkt einen Neuanfang erhält.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/Order%20updates%20hook" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/v2/incoming",
    "subscribed_to": ["Replies", "Chat Concluded"]
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  `https://api.youraiconnector.com/v1/webhooks/${encodeURIComponent("Order updates hook")}`,
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      url: "https://hooks.example.com/v2/incoming",
      subscribed_to: ["Replies", "Chat Concluded"],
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/webhooks/Order updates hook",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "url": "https://hooks.example.com/v2/incoming",
        "subscribed_to": ["Replies", "Chat Concluded"],
    },
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "webhook_id": "0",
  "webhook": {
    "id": "0",
    "name": "Order updates hook",
    "url": "https://hooks.example.com/v2/incoming",
    "subscribed_to": ["Replies", "Chat Concluded"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

Eine unbekannte ID oder ein unbekannter Name gibt `404` mit `{ "success": false, "error": "Webhook not found" }` zurück.

---

## Abonnement löschen

Entfernt das Abonnement, sodass die zugehörige URL keine Payloads mehr empfängt. Die Zustellungs-Integritätszähler werden zurückgesetzt, sodass das erneute Hinzufügen derselben URL später mit einem sauberen Datensatz beginnt.

`DELETE /webhooks/{webhookId}`

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/webhooks/0",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true
}
```

---

## Test-Payload senden

Sendet eine Beispiel-Payload an die URL des Abonnements, damit Sie Ihren Empfänger Ende-zu-Ende überprüfen können. Übergeben Sie optional ein `event`, um zu steuern, welchen Ereignistyp das Beispiel simuliert. Testzustellungen wirken sich niemals auf die Integritätszähler des Abonnements aus.

`POST /webhooks/{webhookId}/test`

Die Antwort gibt immer `200` zurück und meldet das Ergebnis mit einem `delivered`-Flag – ein fehlgeschlagener Test gibt **keinen** Fehlerstatus zurück. Wenn `delivered` auf `false` gesetzt ist, enthält die Antwort die Fehlerdetails.

| Feld | Erforderlich | Beschreibung |
|---|---|---|
| `event` | Nein | Zu simulierender Ereignistyp (muss einer der Werte in `/webhooks/events` sein). Standardmäßig wird ein Zustellungsereignis verwendet. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/test?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "event": "Contact Created" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/test", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ event: "Contact Created" }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks/0/test",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"event": "Contact Created"},
)
data = res.json()
```

**Antwort** (zugestellt)

```json
{
  "success": true,
  "webhook_id": "0",
  "delivered": true
}
```

**Antwort** (fehlgeschlagen)

```json
{
  "success": true,
  "webhook_id": "0",
  "delivered": false,
  "failure_type": "permanent",
  "status_code": 404,
  "error_message": "Request failed with status code 404"
}
```

`failure_type` ist eines von `permanent`, `temporary`, `timeout`, `network` oder `unknown`.

---

## Zustellungsstatus prüfen

Gibt den Zustellungsstatus für die URL des Abonnements zurück: wie viele Zustellungen erfolgreich waren und fehlgeschlagen sind, ob die Zustellung nach wiederholten Fehlern derzeit pausiert ist und die Details des letzten Fehlers. Gibt `"health": null` zurück, wenn noch keine Zustellungsversuche unternommen wurden.

`GET /webhooks/{webhookId}/health`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks/0/health" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/health", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks/0/health",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "webhook_id": "0",
  "url": "https://hooks.example.com/incoming",
  "health": {
    "consecutive_failures": 0,
    "total_failures": 2,
    "total_successes": 120,
    "is_disabled": false,
    "disabled_at": null,
    "disabled_reason": null,
    "last_failure": null,
    "last_success_at": "2026-06-09T12:00:00.000Z",
    "created_at": "2026-05-01T08:00:00.000Z",
    "updated_at": "2026-06-09T12:00:00.000Z"
  }
}
```

Wenn `is_disabled` auf `true` steht, wurde die Zustellung an die URL nach wiederholten Fehlern automatisch pausiert. Reparieren Sie Ihren Empfänger und aktivieren Sie ihn anschließend (siehe unten) wieder.

---

## Zustellung wieder aktivieren

Setzt die Zustellung für einen Webhook fort, dessen URL nach wiederholten Fehlern automatisch pausiert wurde. Dies setzt das Pausen-Flag und die Fehlerzähler zurück, führt aber **keinen** Zustellungsversuch durch – verwenden Sie danach den Test-Endpunkt, um zu bestätigen, dass Ihr Empfänger wieder ordnungsgemäß funktioniert.

`POST /webhooks/{webhookId}/reenable`

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/reenable?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/reenable", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks/0/reenable",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwort**

```json
{
  "success": true,
  "webhook_id": "0"
}
```

---

## Abonnement ausschalten

`enabled` ist der eigene Ein-/Ausschalter des Abonnements. Das Ausschalten stoppt die Zustellungen, während die URL, die Ereignisliste und das Signaturgeheimnis erhalten bleiben.

```bash
# Off
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

# Back on
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'
```

- **Nicht vorhanden bedeutet eingeschaltet.** Ein Abonnement, das vor der Existenz dieses Feldes erstellt wurde, hat keinen gespeicherten `enabled`-Wert und wird normal zugestellt. `GET /webhooks` meldet immer einen konkreten booleschen Wert.
- Ausgeschaltete Abonnements werden von `GET /webhooks` **weiterhin aufgelistet** – so finden Sie diese, um sie wieder einzuschalten.
- Ein [Wiederholungsversuch](#retries), der vor dem Ausschalten in die Warteschlange gestellt wurde, wird nicht fortgesetzt: Der Wiederholungsversuch liest das Abonnement zum Sendezeitpunkt erneut und wird verworfen, wenn es ausgeschaltet ist.
- Nichts, was während des ausgeschalteten Zustands unterdrückt wurde, wird erneut abgespielt, wenn Sie es wieder einschalten.

> Dies unterscheidet sich von der automatischen Deaktivierung nach wiederholten Fehlern, die von [`GET /webhooks/{id}/health`](#check-delivery-health) als `is_disabled` gemeldet und mit [`POST /webhooks/{id}/reenable`](#re-enable-delivery) zurückgesetzt wird. `enabled` ist der Schalter des Kontos; `is_disabled` ist unser Schalter. Keiner überschreibt den anderen – ein Abonnement muss sowohl eingeschaltet als auch darf nicht automatisch deaktiviert sein, um zugestellt zu werden.

---

## Ein Abonnement für alle Kundenkonten (Agenturen)

Setzen Sie bei einem Agenturkonto `apply_to_sub_accounts: true` für ein Abonnement (zum Zeitpunkt der Erstellung oder über `PUT`), damit es auch Ereignisse empfängt, die auf jedem der Kundenkonten der Agentur stattfinden – ein Endpunkt deckt die gesamte Agentur ab, anstatt das Abonnement für jedes Kundenkonto neu erstellen zu müssen.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"apply_to_sub_accounts": true}'
```

So funktioniert es:

- **Der `user`-Block unterscheidet die Konten.** Der `user`-Block jedes Payloads identifiziert das Konto, auf dem das Ereignis tatsächlich stattgefunden hat, sodass Ihr Empfänger pro Kunde routen kann.
- **Die eigenen Einstellungen des Agentur-Abonnements gelten überall.** Seine Ereignisliste, das [Signaturgeheimnis](#signed-payloads) und das [Wiederholungs-Opt-in](#retries) werden auch für die vererbten Zustellungen verwendet.
- **Das eigene Abonnement eines Kundenkontos für dieselbe URL hat Vorrang.** Wenn ein Kundenkonto ein eigenes Abonnement hat, das auf dieselbe URL verweist, wird dieses für die Ereignisse dieses Kontos verwendet – dasselbe Ereignis wird niemals zweimal an einen Endpunkt zugestellt.
- **Kundenkonten sehen es nicht.** Vererbte Abonnements erscheinen nicht in der eigenen Webhook-Liste eines Kundenkontos, und der Kunde kann sie nicht ausschalten – nur die Agentur verwaltet sie.
- **Der Zustellungsstatus wird pro Kundenkonto verfolgt.** Ein Endpunkt, der wiederholt fehlschlägt, wird automatisch für das Konto deaktiviert, dessen Zustellungen fehlgeschlagen sind, nicht für die gesamte Agentur.
- **`subscribed_to_tags` wird nicht vererbt.** Die Tag-Liste verweist auf die eigenen Tags der Agentur, die auf Kundenkonten nicht existieren – die Einschränkung der Konversationszusammenfassung gilt nur für die eigenen Ereignisse der Agentur.
- **Anderswo inaktiv.** Auf einem Konto ohne Kundenkonten wird das Flag zwar gespeichert, hat aber keine Auswirkungen.

---

## Header bei jeder Zustellung

Diese drei Header werden bei jeder Zustellung gesendet, unabhängig davon, ob das Abonnement signiert ist oder nicht:

| Header | Bedeutung |
|---|---|
| `X-Webhook-Delivery` | Stabile ID für das logische Ereignis. Identisch über Wiederholungsversuche hinweg – zur Deduplizierung verwenden. |
| `X-Webhook-Attempt` | 1-basierte Versuchsnummer. |
| `X-Webhook-Event` | Der Ereignisname. |

---

## Signierte Payloads

Die Signierung ist optional, standardmäßig deaktiviert und wird pro Abonnement festgelegt. Wenn ein Abonnement über ein Signaturgeheimnis verfügt, enthält jede Zustellung zusätzlich zu den drei bei jeder Zustellung gesendeten Headern (`X-Webhook-Delivery`, `X-Webhook-Attempt` und `X-Webhook-Event`) zwei weitere Header:

| Header | Bedeutung |
|---|---|
| `X-Webhook-Signature` | `v1=<hex>` – HMAC-SHA256 der Zeichenfolge `"<timestamp>.<raw request body>"`, verschlüsselt mit dem pro Webhook erstellten Signaturgeheimnis, das Sie unter `GET/POST/DELETE /v1/webhooks/{webhookId}/signing-secret` rotieren können. |
| `X-Webhook-Timestamp` | Sendezeit in Unix-Sekunden. In die Signatur eingebunden, daher kann sie nicht unabhängig geändert werden. |

Zur Überprüfung berechnen Sie den HMAC-SHA256 über den Rohdaten-Body mit Ihrem Geheimnis neu und vergleichen ihn mit dem Header. Überprüfen Sie ihn anhand des **rohen** Request-Bodys. Eine erneute Serialisierung von geparstem JSON ändert die Bytes und macht den Vergleich ungültig. Lehnen Sie Zustellungen ab, deren Zeitstempel außerhalb eines Aktualitätsfensters liegt (300s ist ein sinnvoller Standardwert), um Replay-Angriffe zu verhindern, und verwenden Sie für den Vergleich eine zeitlich sichere Funktion.

Siehe [Signierte Payloads](../integrations/webhooks.md#signed-payloads-verifying-a-webhook-really-came-from-us) für vollständige Beispiele zur Überprüfung in Node und Python.

> **Signierung ist nicht dasselbe wie API-Authentifizierung.** Die REST-API selbst authentifiziert sich mit API-Schlüsseln anstelle von OAuth (OAuth 2.1 existiert für MCP-Server, die Sie als Bot-Tools registrieren), und es gibt noch keine offiziellen npm- oder PyPI-SDK-Pakete – rufen Sie die Endpunkte mit einem beliebigen HTTP-Client auf.

### Signierungsgeheimnis lesen

`GET /webhooks/{id}/signing-secret`

```bash
curl "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Antwort**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": true,
  "signing_secret": "whsec_1a2b3c...",
  "signing_secret_created_at": "2026-07-15T09:30:00.000Z"
}
```

Wenn die Signierung deaktiviert ist, ist `signing_enabled` gleich `false` und `signing_secret` gleich `null`.

### Signierungsgeheimnis generieren oder rotieren

`POST /webhooks/{id}/signing-secret`

Erstellt ein Secret (und aktiviert die Signierung) oder ersetzt ein bestehendes. Gibt das neue Secret zurück.

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Antwort**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": true,
  "signing_secret": "whsec_9f8e7d...",
  "signing_secret_created_at": "2026-07-15T10:00:00.000Z"
}
```

Die Rotation wird sofort wirksam – die nächste Zustellung wird nur mit dem neuen Secret signiert. Akzeptieren Sie kurzzeitig beide Secrets, während Sie die Änderung auf einem Live-Endpunkt ausrollen.

Sie können ein Secret auch direkt bei der Erstellung generieren, indem Sie `"generate_signing_secret": true` an `POST /webhooks` übergeben; die Antwort enthält dann ein `signing_secret`-Feld auf oberster Ebene.

### Signierung deaktivieren

`DELETE /webhooks/{id}/signing-secret`

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Antwort**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": false
}
```

> Alle drei Routen für Signierungs-Secrets erfordern die Berechtigung **edit** für Integrationen, einschließlich `GET` – da das Secret ein Anmeldeinformation ist, mit der Zustellungen gefälscht werden können, ist es für Rollen mit reinen Lesezugriffen nicht zugänglich.

---

## Wiederholungsversuche

Optional, standardmäßig deaktiviert und pro Abonnement über den booleschen Wert `retries_enabled` in `POST /webhooks` oder `PUT /webhooks/{id}` konfigurierbar.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"retries_enabled": true}'
```

Wenn aktiviert, wird eine fehlgeschlagene Zustellung nach dem ersten Versuch nach **1 Min., 5 Min., 30 Min. und 2 Std.** erneut versucht (insgesamt ca. 2 Std. 40 Min. Abdeckung).

- **Wiederholt:** 5xx-Antworten, Timeouts und Verbindungsfehler.
- **Nicht wiederholt:** jegliche 4xx-Fehler. Der Empfänger lehnt die Anfrage selbst ab, daher führt eine unveränderte Wiederholung nur zur erneuten Ablehnung.

Wiederholungsversuche können zu einer mehrfachen Zustellung führen — ein Endpunkt, der ein Ereignis verarbeitet hat, aber vor der Antwort einen Timeout erhielt, wird es erneut erhalten. Verwenden Sie `X-Webhook-Delivery` zur Deduplizierung, da dieser Wert über alle Versuche hinweg konstant bleibt. Aus diesem Grund sind Wiederholungsversuche optional.

Die [delivery-health](#check-delivery-health)-Zähler zählen eine gesamte Zustellung, nicht jeden einzelnen Versuch: Ein Fehler wird erst aufgezeichnet, wenn alle Wiederholungsversuche ausgeschöpft sind. Die Aktivierung von Wiederholungsversuchen führt also nicht dazu, dass die automatische Deaktivierung früher ausgelöst wird.

---

## Fehler

Alle Fehler verwenden das Standard-Envelope:

```json
{
  "success": false,
  "error": "Webhook not found"
}
```

Häufige Fälle: Eine nicht zulässige URL, ein leeres/ungültiges `subscribed_to` oder fehlende Felder führen zu `400`; eine unbekannte ID oder ein unbekannter Name führen zu `404`; und ein `403` bedeutet, dass Webhooks für Ihr Konto nicht aktiviert sind. Siehe [Fehler](errors-and-pagination.md) für die vollständige Liste.

---

## Nächste Schritte

- [Webhooks (Payloads empfangen)](../integrations/webhooks.md) — Richten Sie Ihren Empfänger ein und verstehen Sie die Struktur der Payloads.
- [Authentifizierung](authentication.md) — die vier Möglichkeiten zur Authentifizierung einer Anfrage.
- [Fehler & Ratenbegrenzungen](errors-and-pagination.md) — Statuscodes und das Limit von 300 Anfragen/Min.
