> ## Documentation Index
> Fetch the complete documentation index at: https://docs.exoid.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# How they work

> Understand what an Exoid webhook is, how a response travels to your endpoint and when Exoid retries.

A webhook is an HTTP notification that Exoid sends to your system every time a relevant event happens, for example a new response coming in. You need it when you want data to land in your database, CRM or data warehouse the moment it's collected, with no manual exports.

<Info>
  You enable webhooks from **Settings (side toolbar) → Webhook**.
</Info>

## The delivery flow

When an interview is completed, Exoid runs six steps in sequence.

<Steps>
  <Step title="Validation">
    Exoid checks that the response is correct and well-formed.
  </Step>

  <Step title="Formatting">
    The data is organized into a clean, consistent JSON payload.
  </Step>

  <Step title="Digital signature">
    The payload is signed with HMAC-SHA256 using the campaign secret.
  </Step>

  <Step title="Delivery">
    The data is sent with an HTTPS `POST` request to your endpoint.
  </Step>

  <Step title="Automatic retries">
    On a temporary error, Exoid repeats the request up to 7 times within one hour.
  </Step>

  <Step title="Logging">
    Every request is tracked and made available in the dashboard logs.
  </Step>
</Steps>

What happens after the `POST` leaves depends entirely on your server's answer: a success closes the event, a temporary error puts the same request back in the queue, and a permanent error ends it there. Once the seventh attempt fails, the event is dropped.

```mermaid theme={"dark"}
%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, -apple-system, system-ui, sans-serif','fontSize':'15px','lineColor':'#8891C7','primaryColor':'#4252FF','primaryTextColor':'#FFFFFF','primaryBorderColor':'#4252FF','clusterBkg':'transparent','clusterBorder':'#8891C7','titleColor':'#6B78FF','tertiaryTextColor':'#6B78FF','edgeLabelBackground':'transparent'}}}%%
flowchart TD
  P["Signed payload"] --> S["HTTPS POST"]
  S --> E["Your endpoint"]
  E -->|"2xx"| OK["Delivered"]
  E -->|"429 or 5xx"| R["Retry, up to 7"]
  E -->|"4xx"| L["Lost, no retry"]
  R --> S

  classDef primary fill:#4252FF,stroke:#4252FF,color:#FFFFFF,rx:8,ry:8
  classDef step fill:#6B78FF,stroke:#6B78FF,color:#FFFFFF,rx:8,ry:8
  classDef soft fill:#2B34B8,stroke:#2B34B8,color:#FFFFFF,rx:8,ry:8
  classDef ghost fill:transparent,stroke:#8891C7,stroke-dasharray:4 4,color:#8891C7,rx:8,ry:8

  class P step
  class S primary
  class E ghost
  class OK primary
  class R soft
  class L soft
```

## Retry logic

If your endpoint doesn't respond or returns a temporary code, Exoid makes up to 7 attempts with progressive delays.

| Attempt | Delay after the previous one |
| ------- | ---------------------------- |
| 1       | Immediate                    |
| 2       | 1 minute                     |
| 3       | 2 minutes                    |
| 4       | 4 minutes                    |
| 5       | 8 minutes                    |
| 6       | 16 minutes                   |
| 7       | 32 minutes                   |

### When Exoid retries and when it doesn't

There's one rule: `429`, `5xx` and network errors trigger retries. `4xx` request or authentication errors are permanent and the event is lost.

<Tabs>
  <Tab title="Triggers a retry">
    | Condition      | Detail                      |
    | -------------- | --------------------------- |
    | `429`          | Too Many Requests           |
    | `500`          | Internal server error       |
    | `502`          | Bad Gateway                 |
    | `503`          | Service unavailable         |
    | `504`          | Gateway Timeout             |
    | Network errors | Timeouts, connection errors |
  </Tab>

  <Tab title="Permanent error">
    | Condition | Detail                              |
    | --------- | ----------------------------------- |
    | `400`     | Malformed request                   |
    | `401`     | Invalid signature or authentication |
    | `403`     | Access denied                       |
    | `404`     | Endpoint does not exist             |
  </Tab>
</Tabs>

<Warning>
  A permanent error (`400`, `401`, `403`, `404`) triggers no retry at all: the event is lost. If your endpoint rejects a valid request — for example because signature verification is implemented incorrectly — that response will never be delivered to you again.
</Warning>

<Note>
  Failed requests remain viewable in the dashboard logs together with their status code.
</Note>

## Next steps

<CardGroup cols={2}>
  <Card title="Configuration" icon="settings" href="/en/webhooks/configuration">
    Enable the webhook, set URL and secret, check the request logs.
  </Card>

  <Card title="Signature and security" icon="shield" href="/en/webhooks/security">
    Verify the HMAC-SHA256 signature before accepting a payload.
  </Card>

  <Card title="Payload reference" icon="file-json" href="/en/webhooks/payload">
    The full data model, response types and a complete example.
  </Card>
</CardGroup>


## Related topics

- [Payload reference](/en/webhooks/payload.md)
- [Troubleshooting](/en/troubleshooting.md)
- [Quotas](/en/distribute/quotas.md)
