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

# Webhooks

> Receive real-time notifications when events occur in your sub-accounts.

Receive real-time notifications when events occur in any sub-account. Configure webhook URLs at the partner level.

## Configure Webhooks

`POST /webhooks`

<ParamField body="url" type="string" required>
  Your webhook endpoint URL (must be HTTPS)
</ParamField>

<ParamField body="events" type="array" required>
  Array of event types to subscribe to
</ParamField>

<ParamField body="secret" type="string" required>
  Secret for HMAC signature verification
</ParamField>

```bash theme={null}
curl -X POST https://api.recoverbiz.com/v1/webhooks \
  -H "X-Partner-Key: pk_live_abc123def456..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourplatform.com/webhooks/recover",
    "events": [
      "conversation.started",
      "conversation.reply_received",
      "conversation.handoff_requested",
      "lead.status_changed",
      "lead.created",
      "checklist.item_collected",
      "checklist.completed",
      "sequence.completed",
      "sequence.reply_received"
    ],
    "secret": "whsec_your_signing_secret"
  }'
```

**Response: `201 Created`**

```json theme={null}
{
  "id": "wh_001",
  "url": "https://yourplatform.com/webhooks/recover",
  "events": [
    "conversation.started",
    "conversation.reply_received",
    "conversation.handoff_requested",
    "lead.status_changed",
    "lead.created",
    "checklist.item_collected",
    "checklist.completed",
    "sequence.completed",
    "sequence.reply_received"
  ],
  "active": true,
  "created_at": "2026-02-15T10:30:00Z"
}
```

## Event Types

| Event                            | Fires When                                       |
| -------------------------------- | ------------------------------------------------ |
| `conversation.started`           | First message exchanged with a new lead          |
| `conversation.reply_received`    | Lead sends an inbound message                    |
| `conversation.handoff_requested` | AI flags conversation for human review           |
| `lead.status_changed`            | Lead status transitions (new -> contacted, etc.) |
| `lead.created`                   | New lead imported via API or conversation        |
| `checklist.item_collected`       | A document or data point is collected            |
| `checklist.completed`            | All required checklist items are collected       |
| `sequence.completed`             | A lead finishes all sequence steps               |
| `sequence.reply_received`        | Lead replies during an active sequence           |

## Webhook Payload

All webhooks include a consistent envelope:

```json theme={null}
{
  "id": "evt_abc123",
  "type": "checklist.completed",
  "account_id": "acc_8f3a1b2c",
  "created_at": "2026-02-14T15:30:00Z",
  "data": {
    "phone": "+14155551234",
    "lead_name": "John Doe",
    "checklist_progress": 1.0,
    "completed_items": 4,
    "total_items": 4
  }
}
```

### Example Payloads

<Accordion title="conversation.reply_received">
  ```json theme={null}
  {
    "id": "evt_def456",
    "type": "conversation.reply_received",
    "account_id": "acc_8f3a1b2c",
    "created_at": "2026-02-14T15:30:00Z",
    "data": {
      "phone": "+14155551234",
      "lead_name": "John Doe",
      "message_body": "Sure, I can send the bank statements tomorrow.",
      "message_direction": "inbound"
    }
  }
  ```
</Accordion>

<Accordion title="lead.status_changed">
  ```json theme={null}
  {
    "id": "evt_ghi789",
    "type": "lead.status_changed",
    "account_id": "acc_8f3a1b2c",
    "created_at": "2026-02-14T16:00:00Z",
    "data": {
      "phone": "+14155551234",
      "lead_name": "John Doe",
      "previous_status": "new",
      "new_status": "contacted"
    }
  }
  ```
</Accordion>

<Accordion title="conversation.handoff_requested">
  ```json theme={null}
  {
    "id": "evt_jkl012",
    "type": "conversation.handoff_requested",
    "account_id": "acc_8f3a1b2c",
    "created_at": "2026-02-14T17:00:00Z",
    "data": {
      "phone": "+14155551234",
      "lead_name": "John Doe",
      "reason": "Lead requested to speak with a human agent"
    }
  }
  ```
</Accordion>

## Signature Verification

Every webhook includes an `X-Recover-Signature` header containing an HMAC-SHA256 signature of the raw request body using your webhook secret.

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function verifyWebhook(body, signature, secret) {
    const expected = crypto
      .createHmac('sha256', secret)
      .update(body)
      .digest('hex');
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expected)
    );
  }

  // In your Express handler (use express.raw() to get the raw body):
  app.post('/webhooks/recover', express.raw({ type: 'application/json' }), (req, res) => {
    const signature = req.headers['x-recover-signature'];
    const isValid = verifyWebhook(req.body, signature, WEBHOOK_SECRET);

    if (!isValid) {
      return res.status(401).send('Invalid signature');
    }

    const event = JSON.parse(req.body);
    const { type, data, account_id } = event;
    // Handle the event...

    res.status(200).send('OK');
  });
  ```

  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
      expected = hmac.new(
          secret.encode(),
          body,
          hashlib.sha256
      ).hexdigest()
      return hmac.compare_digest(signature, expected)
  ```
</CodeGroup>

<Warning>
  Always verify the webhook signature before processing the event. Never trust the payload without verification.
</Warning>

## Delivery & Retries

Recover delivers webhooks with automatic retry on failure:

| Attempt   | Delay      |
| --------- | ---------- |
| 1st retry | 30 seconds |
| 2nd retry | 2 minutes  |
| 3rd retry | 10 minutes |
| 4th retry | 1 hour     |
| 5th retry | 4 hours    |

Your endpoint must respond with a `2xx` status within **10 seconds** or the delivery is considered failed. After 5 failed retries, the event is dropped and a `webhook.delivery_failed` event is logged in your partner dashboard.

<Info>
  Each webhook delivery includes an `X-Recover-Delivery-Id` header with a unique delivery ID for idempotency tracking.
</Info>

## List Webhooks

`GET /webhooks`

Returns all configured webhook endpoints.

```bash theme={null}
curl https://api.recoverbiz.com/v1/webhooks \
  -H "X-Partner-Key: pk_live_abc123def456..."
```

**Response: `200 OK`**

```json theme={null}
{
  "webhooks": [
    {
      "id": "wh_001",
      "url": "https://yourplatform.com/webhooks/recover",
      "events": ["conversation.reply_received", "checklist.completed"],
      "active": true,
      "created_at": "2026-02-10T09:00:00Z"
    }
  ]
}
```

## Update Webhook

`PATCH /webhooks/:webhook_id`

Update the URL, events, or active status.

```bash theme={null}
curl -X PATCH https://api.recoverbiz.com/v1/webhooks/wh_001 \
  -H "X-Partner-Key: pk_live_abc123def456..." \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["conversation.reply_received", "checklist.completed", "lead.status_changed"],
    "active": true
  }'
```

## Delete Webhook

`DELETE /webhooks/:webhook_id`

```bash theme={null}
curl -X DELETE https://api.recoverbiz.com/v1/webhooks/wh_001 \
  -H "X-Partner-Key: pk_live_abc123def456..."
```

**Response: `200 OK`**

```json theme={null}
{
  "success": true,
  "deleted": true
}
```
