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

# Webhooks overview

> Signed event deliveries for opens, clicks, bounces, replies, and unsubscribes.

Vibefollow can push events back to your backend over HTTPS — one delivery per email open, click, bounce, reply, and unsubscribe. You receive them at an endpoint you control, verify the signature, and react however you like (update your CRM, kick off a workflow, alert on negative replies).

## Lifecycle of a delivery

```mermaid theme={null}
sequenceDiagram
    participant PM as Postmark / inbound
    participant VF as Vibefollow
    participant You as Your endpoint
    PM->>VF: Open, click, bounce, reply, or unsubscribe
    VF->>VF: HMAC-SHA256 sign body with webhook secret
    VF->>You: POST + X-Vibefollow-Signature: t=...,v1=...
    You->>You: Verify signature with SDK
    You-->>VF: 2xx within 10 s
    Note over VF,You: On non-2xx or timeout:<br/>retry with exponential backoff,<br/>up to 6 attempts over ~24h
```

<Steps>
  <Step title="A receivable event happens">
    Postmark reports an open back to Vibefollow, an inbound reply comes through, or a user clicks the one-click unsubscribe link.
  </Step>

  <Step title="Vibefollow signs the payload">
    Body bytes are HMAC-SHA256'd with your project's webhook secret; the timestamp goes in the header.
  </Step>

  <Step title="POST to your endpoint">
    `Content-Type: application/json`, `X-Vibefollow-Signature: t=…,v1=…`.
  </Step>

  <Step title="You verify and respond">
    Return `2xx` within 10 seconds and the delivery is marked complete.
  </Step>

  <Step title="On non-2xx or timeout">
    Vibefollow retries with exponential backoff — up to 6 attempts over \~24 hours. After that the delivery is dead-lettered and visible in the dashboard.
  </Step>
</Steps>

## Setting up an endpoint

<Steps>
  <Step title="Expose an HTTPS endpoint">
    Accept `POST` with JSON bodies. Make sure your framework can hand you the raw request body, not a parsed object.
  </Step>

  <Step title="Register the URL">
    In **Settings → Developers → Webhooks**, add the URL and generate a signing secret. Store the secret as `VIBEFOLLOW_WEBHOOK_SECRET`.
  </Step>

  <Step title="Verify every delivery">
    Use the SDK — see [Signature verification](/webhooks/signature-verification).
  </Step>

  <Step title="Subscribe to event types">
    Switch on the event types you care about.
  </Step>
</Steps>

<Snippet file="webhook-signature.mdx" />

## Retry policy

Failed deliveries (non-2xx, timeout, connection error) retry on a fixed back-off schedule. Total budget is 6 attempts: 1 initial dispatch plus 5 retries.

| Attempt | Delay since previous |
| ------- | -------------------- |
| 1       | initial              |
| 2       | 1 minute             |
| 3       | 5 minutes            |
| 4       | 30 minutes           |
| 5       | 2 hours              |
| 6       | 12 hours             |

After 6 attempts the delivery is marked `failed`. You can manually re-queue it from the in-dashboard deliveries log.

## Why the raw body

<Warning>
  The signature is computed over the **exact bytes the server sent**. If you parse the body first and re-serialise — key ordering, whitespace, escaped slashes — verification will fail. Use your framework's raw-body mechanism (`express.raw()`, Hono `request.text()`, etc.) before the SDK touches it.
</Warning>

## What events you can receive

<CardGroup cols={2}>
  <Card title="email.opened" icon="envelope-open">
    Recipient opened a tracked email.
  </Card>

  <Card title="email.clicked" icon="arrow-pointer">
    Recipient clicked a link in a tracked email.
  </Card>

  <Card title="email.bounced" icon="triangle-exclamation">
    Postmark reported a bounce or spam complaint.
  </Card>

  <Card title="email.replied" icon="reply">
    Inbound reply parsed and tone-classified.
  </Card>

  <Card title="email.unsubscribed" icon="ban">
    One-click unsubscribe, reply-request, or manual.
  </Card>

  <Card title="Event types reference" icon="book" href="/webhooks/event-types">
    Full payload spec for each event type.
  </Card>
</CardGroup>
