
# Webhooks API

Webhooks lader platformen give besked til dine andre systemer i det øjeblik, der sker noget — en ny kontakt, et svar, en booket aftale og mere. Denne API administrerer selve **abonnementerne**: hvilke URL'er der modtager hvilke hændelser. For information om, hvordan du modtager og verificerer de payloads, dit endpoint modtager, se [Webhooks](../integrations/webhooks.md).

Alle stier herunder er relative til API'ets base-URL:

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

Enhver anmodning skal godkendes. Se [Godkendelse](authentication.md) for de fire accepterede metoder. Eksemplerne her bruger `X-API-Key`-headeren (og én forespørgselsparameter-form til cURL).

::: note
**Bemærk:** Webhooks skal være aktiveret for din konto. Hvis de ikke er det, returnerer disse slutpunkter en `403`.
:::


---

## Hvordan abonnementer adresseres

Hvert abonnement har et `id` og et valgfrit `name`. Begge kan bruges som `{webhookId}` i stien til opdatering, sletning, test, sundhedstjek og genaktivering.

> **Foretræk navnet.** Abonnements-id'er er positionelle, så de kan ændre sig, efter et andet abonnement er slettet. Hvis du angiver et stabilt `name`, når du opretter et abonnement, så adressér det ved navn for at undgå overraskelser.

---

## List abonnementer

`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()
```

**Svar**

```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` og `retries_enabled` er tilvalg pr. abonnement, som begge er deaktiveret, medmindre du aktiverer dem. Se [Signerede payloads](#signed-payloads) og [Forsøg igen](#retries).

`apply_to_sub_accounts` er tilvalget for bureau-arv — se [Ét abonnement til alle klientkonti](#one-subscription-for-all-client-accounts-agencies). Deaktiveret som standard og inaktivt på konti, der ikke har nogen klientkonti.

`enabled` er abonnementets tænd/sluk-knap — se [Slukning af et abonnement](#switching-a-subscription-off). Slukkede abonnementer er stadig angivet her.

Selve signeringshemmeligheden er aldrig inkluderet her — læs den fra [`GET /webhooks/{id}/signing-secret`](#read-the-signing-secret).

---

## List abonnerbare hændelsestyper

Returnerer de præcise strenge, du kan bruge i `subscribed_to`. Brug dette til at finde gyldige hændelsesnavne i stedet for at hardcode dem.

`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()
```

**Svar**

Svaret er `{"success": true, "events": [...]}`, hvor `events` i øjeblikket indeholder 22 præcise strenge: 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 og Broadcast Completed (Channel Connected accepteres i `subscribed_to`, men intet udsender det i dag, så byg ikke mod det).

For hvad hver hændelse betyder, og den `event`-kode den sender i payloaden, se [De 22 Webhook-hændelser](../integrations/webhooks.md#the-22-webhook-events). Dette endpoint er den autoritative liste til enhver tid — læs den live frem for at hardcode navnene.

---

## Opret et abonnement

`POST /webhooks`

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `url` | Ja | HTTPS-URL, der modtager hændelses-payloads via `POST`. Skal være offentligt tilgængelig. |
| `subscribed_to` | Ja | Et ikke-tomt array af hændelsesnavne (se `/webhooks/events`). |
| `name` | Nej | Et visningsnavn. Kan også bruges som `{webhookId}` senere. Standard er et tidsstemplet navn. |
| `subscribed_to_tags` | Nej | Tag-ID'er, der indsnævrer, hvilke tags der producerer en besked om samtaleresumé. Det begrænser ikke abonnementets hændelser til disse tags — for at få en anmodning, når et specifikt tag tilføjes, skal du indstille en webhook-URL på det pågældende tag under fanen **Tags** for agenten (eller kampagnen). |
| `retries_enabled` | Nej | Boolesk værdi, standard er `false`. Tilmeld dig [genforsøg](#retries) af mislykkede leveringer. |
| `generate_signing_secret` | Nej | Boolesk værdi, standard er `false`. Opret en HMAC [signaturhemmelighed](#signed-payloads) sammen med abonnementet. Hemmeligheden returneres én gang som et `signing_secret` på øverste niveau i svaret. |
| `enabled` | Nej | Boolesk værdi, standard er `true`. Send `false` for at oprette abonnementet i deaktiveret tilstand. Se [Deaktivering af et abonnement](#switching-a-subscription-off). |
| `apply_to_sub_accounts` | Nej | Boolesk værdi, standard er `false`. På en bureaukonto gør `true`, at dette abonnement også modtager hændelser fra alle klientkonti — se [Ét abonnement til alle klientkonti](#one-subscription-for-all-client-accounts-agencies). |

> **URL-regler:** URL'en skal bruge `https://` og være offentligt tilgængelig. Almindelig `http://`, `localhost`, private netværksadresser og interne platformadresser afvises med en `400`.

**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()
```

**Svar**

```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"
  }
}
```

---

## Opdater et abonnement

Angiv mindst én af `url`, `subscribed_to`, `name`, `subscribed_to_tags`, `retries_enabled`, `enabled` eller `apply_to_sub_accounts`. Udeladte felter beholder deres nuværende værdier. `subscribed_to` og `subscribed_to_tags` er erstatninger, ikke fletninger.

`PUT /webhooks/{webhookId}`

> Opdatering af et abonnement forstyrrer aldrig dets signeringshemmelighed — administrer den via [ruterne for signeringshemmeligheder](#signed-payloads).

> Når URL'en ændres, genaktiveres levering til den nye URL automatisk, hvilket giver et tidligere fejlbehæftet slutpunkt en frisk start.

**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()
```

**Svar**

```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"
  }
}
```

Et ukendt id eller navn returnerer `404` med `{ "success": false, "error": "Webhook not found" }`.

---

## Slet et abonnement

Fjerner abonnementet, så dets URL stopper med at modtage nyttelaster. Dets leverings-sundhedstællere nulstilles, så gen-tilføjelse af den samme URL senere starter med en ren historik.

`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()
```

**Svar**

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

---

## Send en test-nyttelast

Sender en eksempel-nyttelast til abonnementets URL, så du kan verificere din modtager ende-til-ende. Send eventuelt en `event` for at styre, hvilken begivenhedstype eksemplet simulerer. Testleveringer påvirker aldrig abonnementets sundhedstællere.

`POST /webhooks/{webhookId}/test`

Svaret returnerer altid `200` og rapporterer resultatet med et `delivered`-flag — en mislykket test returnerer **ikke** en fejlstatus. Når `delivered` er `false`, inkluderer svaret detaljer om fejlen.

| Felt | Påkrævet | Beskrivelse |
|---|---|---|
| `event` | Nej | Begivenhedstype der skal simuleres (skal være en af `/webhooks/events`). Standard er en leveringsbegivenhed. |

**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()
```

**Svar** (leveret)

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

**Svar** (fejlet)

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

`failure_type` er en af `permanent`, `temporary`, `timeout`, `network` eller `unknown`.

---

## Tjek leveringsstatus

Returnerer leveringsstatus-posten for abonnementets URL: hvor mange leveringer der er lykkedes og fejlet, om levering i øjeblikket er sat på pause efter gentagne fejl, samt detaljer om den seneste fejl. Returnerer `"health": null`, når der endnu ikke er forsøgt nogen leveringer.

`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()
```

**Svar**

```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"
  }
}
```

Når `is_disabled` er `true`, er levering til URL'en automatisk blevet sat på pause efter gentagne fejl. Reparer din modtager, og genaktiver den derefter (nedenfor).

---

## Genaktiver levering

Genoptager levering for en webhook, hvis URL automatisk blev sat på pause efter gentagne fejl. Dette nulstiller pause-flaget og tællere for fejl, men forsøger **ikke** en levering — brug test-endepunktet bagefter for at bekræfte, at din modtager er sund igen.

`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()
```

**Svar**

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

---

## Slukning af et abonnement

`enabled` er abonnementets egen tænd/sluk-knap. Hvis du slukker for den, stoppes leveringer, mens URL'en, event-listen og signeringshemmeligheden bevares intakte.

```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}'
```

- **Fravær betyder tændt.** Et abonnement oprettet før dette felt eksisterede, har ingen `enabled`-værdi gemt og leverer normalt. `GET /webhooks` rapporterer altid en konkret boolesk værdi.
- Slukkede abonnementer er **stadig angivet** af `GET /webhooks` — det er sådan, du finder dem for at tænde for dem igen.
- Et [genforsøg](#retries), der er sat i kø før slukningen, genoptages ikke: genforsøget genlæser abonnementet på afsendelsestidspunktet og annulleres, hvis det er slukket.
- Intet, der er undertrykt, mens det var slukket, afspilles igen, når du tænder for det igen.

> Adskilt fra den automatiske deaktivering efter gentagne fejl, som rapporteres af [`GET /webhooks/{id}/health`](#check-delivery-health) som `is_disabled` og ryddes med [`POST /webhooks/{id}/reenable`](#re-enable-delivery). `enabled` er kontoens kontakt; `is_disabled` er vores. Ingen af dem tilsidesætter den anden — et abonnement skal både være tændt og ikke automatisk deaktiveret for at levere.

---

## Ét abonnement til alle klientkonti (bureauer)

På en bureaukonto skal du indstille `apply_to_sub_accounts: true` på et abonnement (ved oprettelse eller via `PUT`), hvorefter det også modtager hændelser, der sker på hver af bureauets klientkonti — ét endpoint dækker hele bureauet i stedet for at skulle genoprette abonnementet på hver klientkonto.

```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}'
```

Sådan fungerer det:

- **`user`-blokken adskiller kontiene.** Hver payloads `user`-blok identificerer den konto, hvor hændelsen rent faktisk fandt sted, så din modtager kan rute pr. klient.
- **Bureauabonnementets egne indstillinger gælder overalt.** Dets hændelsesliste, [signaturhemmelighed](#signed-payloads) og [genforsøgs](#retries)-tilvalg bruges også til de arvede leveringer.
- **En klientkontos eget abonnement til samme URL vinder.** Hvis en klientkonto har sit eget abonnement, der peger på samme URL, bruges det til den kontos hændelser — den samme hændelse leveres aldrig to gange til ét endpoint.
- **Klientkonti ser det ikke.** Arvede abonnementer vises ikke på en klientkontos egen webhook-liste, og klienten kan ikke deaktivere dem — kun bureauet administrerer dem.
- **Leveringsstatus spores pr. klientkonto.** Et endpoint, der bliver ved med at fejle, deaktiveres automatisk for den konto, hvis leveringer fejlede, ikke for hele bureauet.
- **`subscribed_to_tags` nedarves ikke.** Tag-listen refererer til bureauets egne tags, som ikke findes på klientkonti — indsnævring af samtaleresumé gælder kun for bureauets egne hændelser.
- **Inaktivt andre steder.** På en konto uden klientkonti gemmes flaget fint, men gør intet.

---

## Headere ved hver levering

Disse tre headere sendes ved hver levering, uanset om abonnementet er signeret eller ej:

| Header | Betydning |
|---|---|
| `X-Webhook-Delivery` | Stabilt ID for den logiske hændelse. Identisk på tværs af genforsøg – brug det til deduplikering. |
| `X-Webhook-Attempt` | Forsøgsnummer (1-baseret). |
| `X-Webhook-Event` | Hændelsesnavnet. |

---

## Signerede payloads

Signering er valgfri, deaktiveret som standard og indstilles pr. abonnement. Når et abonnement har en signeringshemmelighed, indeholder hver levering to ekstra headere ud over de tre, der sendes ved hver levering (`X-Webhook-Delivery`, `X-Webhook-Attempt` og `X-Webhook-Event`):

| Header | Betydning |
|---|---|
| `X-Webhook-Signature` | `v1=<hex>` — HMAC-SHA256 af strengen `"<timestamp>.<raw request body>"`, kodet med den webhook-specifikke signeringshemmelighed, som du opretter og roterer på `GET/POST/DELETE /v1/webhooks/{webhookId}/signing-secret`. |
| `X-Webhook-Timestamp` | Sendetidspunkt, Unix-sekunder. Bundet til signaturen, så det kan ikke ændres uafhængigt. |

For at verificere skal du genberegne HMAC-SHA256 over den rå body med din hemmelighed og sammenligne den med headeren. Verificer mod den **rå** request-body. Gen-serialisering af parsede JSON-data ændrer bytes og ødelægger sammenligningen. Afvis leveringer, hvis tidsstempel ligger uden for et friskhedsvindue (300 sekunder er en fornuftig standard) for at forhindre replay-angreb, og sammenlign med en timing-sikker funktion.

Se [Signerede Payloads](../integrations/webhooks.md#signed-payloads-verifying-a-webhook-really-came-from-us) for fuldstændige eksempler på verificering i Node og Python.

> **Signering er ikke det samme som API-autentificering.** Selve REST API'et autentificerer med API-nøgler frem for OAuth (OAuth 2.1 findes til MCP-servere, som du registrerer som bot-værktøjer), og der findes endnu ingen officielle npm- eller PyPI SDK-pakker – kald endpoints med en hvilken som helst HTTP-klient.

### Læs signeringshemmeligheden

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

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

**Svar**

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

Når signering er deaktiveret, er `signing_enabled` lig med `false` og `signing_secret` er lig med `null`.

### Generer eller roter signeringshemmeligheden

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

Opretter en hemmelighed (aktiverer signering) eller erstatter den eksisterende. Returnerer den nye hemmelighed.

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

**Svar**

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

Rotation træder i kraft med det samme — den næste levering signeres kun med den nye hemmelighed. Accepter begge hemmeligheder kortvarigt, mens du udruller ændringen til et live-endepunkt.

Du kan også oprette en hemmelighed ved oprettelse ved at sende `"generate_signing_secret": true` til `POST /webhooks`; svaret indeholder derefter et `signing_secret`-felt på øverste niveau.

### Deaktiver signering

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

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

**Svar**

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

> Alle tre ruter til signeringshemmeligheder kræver **redigerings**-tilladelse til integrationer, inklusive `GET` — hemmeligheden er en legitimation, der kan forfalske leveringer, så den eksponeres ikke for skrivebeskyttede roller.

---

## Forsøg igen

Valgfrit, deaktiveret som standard, og indstilles pr. abonnement via den boolske værdi `retries_enabled` på `POST /webhooks` eller `PUT /webhooks/{id}`.

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

Når det er aktiveret, forsøges en mislykket levering igen efter **1m, 5m, 30m og 2t** fra det første forsøg (ca. 2t 40m dækning).

- **Forsøges igen:** 5xx-svar, timeouts og forbindelsesfejl.
- **Forsøges ikke igen:** alle 4xx. Modtageren afviser selve anmodningen, så en uændret gentagelse vil blot reproducere afvisningen.

Forsøg gør duplikeret levering mulig — et slutpunkt, der har behandlet en hændelse, men fik timeout før svar, vil se den igen. Brug `X-Webhook-Delivery` til deduplikering, da det er konstant på tværs af forsøg. Dette er grunden til, at forsøg er valgfrie.

Tællerne for [delivery-health](#check-delivery-health) tæller en hel levering, ikke hvert forsøg: en fejl registreres kun, når alle forsøg er opbrugt, så aktivering af gentagne forsøg får ikke den automatiske deaktivering til at udløses hurtigere.

---

## Fejl

Alle fejl bruger standard-konvolutten:

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

Almindelige tilfælde: en URL, der ikke er tilladt, en tom/ugyldig `subscribed_to` eller manglende felter returnerer `400`; et ukendt id eller navn returnerer `404`; og en `403` betyder, at webhooks ikke er aktiveret for din konto. Se [Fejl](errors-and-pagination.md) for den fulde liste.

---

## Næste skridt

- [Webhooks (modtagelse af payloads)](../integrations/webhooks.md) — opsæt din modtager og forstå payload-strukturen.
- [Autentificering](authentication.md) — de fire måder at autentificere en anmodning på.
- [Fejl & hastighedsbegrænsninger](errors-and-pagination.md) — statuskoder og grænsen på 300 anmodninger/min.
