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

# Webhooks Overview

> Receive real-time notifications when events occur in SendPilot

Webhooks allow you to receive real-time HTTP notifications when events occur in your SendPilot workspace. Instead of polling the API, webhooks push data to your server as events happen.

## How Webhooks Work

```mermaid theme={null}
sequenceDiagram
    participant SP as SendPilot
    participant WH as Your Webhook Endpoint
    participant App as Your Application

    SP->>WH: POST event payload
    WH->>App: Process event
    App->>WH: Return 200 OK
    WH->>SP: Acknowledge receipt
```

1. An event occurs in SendPilot (e.g., a lead replies to a message)
2. SendPilot sends an HTTP POST request to your webhook URL
3. Your server processes the event and returns a 2xx response
4. SendPilot marks the delivery as successful

## Available Events

<CardGroup cols={2}>
  <Card title="Message Events" icon="message">
    * `message.sent` - Message sent to a lead
    * `reply.received` - Reply received from a lead
  </Card>

  <Card title="Connection Events" icon="link">
    * `connection_request.sent` - Connection request sent
    * `connection_request.accepted` - Connection accepted
  </Card>

  <Card title="Campaign Events" icon="rocket">
    * `campaign.started` - Campaign started
    * `campaign.paused` - Campaign paused
    * `campaign.resumed` - Campaign resumed
    * `campaign.finished` - Campaign finished
  </Card>

  <Card title="Lead Events" icon="user">
    * `lead.tag.updated` - Lead tags updated
    * `lead.updated` - Lead status updated
  </Card>

  <Card title="Lead Database Events" icon="database">
    * `lead_database.search.completed` - Search completed with all leads
  </Card>

  <Card title="Lead Extractor Events" icon="download">
    * `lead_extractor.job.completed` - Extraction job completed with all leads
  </Card>
</CardGroup>

## Webhook Payload Structure

All webhook payloads follow a consistent structure:

```json theme={null}
{
  "eventId": "evt_1708456789123_abc123def",
  "eventType": "reply.received",
  "timestamp": "2024-02-24T10:30:00.000Z",
  "workspaceId": "ws_abc123xyz",
  "data": {
    // Event-specific data
  }
}
```

| Field         | Type   | Description                                            |
| ------------- | ------ | ------------------------------------------------------ |
| `eventId`     | string | Unique identifier for this event (use for idempotency) |
| `eventType`   | string | The type of event that occurred                        |
| `timestamp`   | string | ISO 8601 timestamp when the event occurred             |
| `workspaceId` | string | Your workspace ID                                      |
| `data`        | object | Event-specific payload data                            |

## Delivery & Retries

SendPilot uses reliable webhook delivery with automatic retries:

* **Timeout**: Your endpoint must respond within 30 seconds
* **Success**: Any 2xx response is considered successful
* **Retries**: Failed deliveries are retried with exponential backoff:
  * 1st retry: 5 seconds
  * 2nd retry: 30 seconds
  * 3rd retry: 2 minutes
  * 4th retry: 15 minutes
  * 5th retry: 1 hour
* **Max retries**: 5 attempts total

<Warning>
  If all retries fail, the event is marked as failed. You can view failed deliveries in the SendPilot dashboard.
</Warning>

## Security

### Signature Verification

All webhook requests include a signature header for verification:

```
Webhook-Signature: v1,t=1708456789,s=abc123...
```

Verify the signature by computing HMAC-SHA256 of the request body using your webhook secret:

```javascript theme={null}
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const parts = signature.split(',');
  const timestamp = parts.find(p => p.startsWith('t=')).slice(2);
  const providedSignature = parts.find(p => p.startsWith('s=')).slice(2);
  
  const signedPayload = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(providedSignature),
    Buffer.from(expectedSignature)
  );
}
```

### IP Allowlisting

For additional security, you can allowlist SendPilot's webhook IPs. Contact support for the current IP ranges.

## Best Practices

<AccordionGroup>
  <Accordion title="Respond quickly">
    Return a 2xx response as fast as possible. Process events asynchronously to avoid timeouts.
  </Accordion>

  <Accordion title="Handle duplicates">
    Use the `eventId` field for idempotency. The same event may be delivered multiple times in rare cases.
  </Accordion>

  <Accordion title="Verify signatures">
    Always verify the webhook signature to ensure the request came from SendPilot.
  </Accordion>

  <Accordion title="Log everything">
    Log incoming webhooks for debugging. This helps troubleshoot integration issues.
  </Accordion>

  <Accordion title="Use HTTPS">
    Always use HTTPS endpoints to protect sensitive data in transit.
  </Accordion>

  <Accordion title="Handle large payloads">
    Lead Database and Lead Extractor webhooks include full lead data. Process these asynchronously for large result sets.
  </Accordion>
</AccordionGroup>

## Next Steps

<Card title="Set Up Webhooks" icon="gear" href="/webhooks/setup">
  Learn how to configure webhook subscriptions
</Card>
