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

# Webhook Events

> Complete reference for all Drippi webhook events and their payloads

## Event Types

Drippi sends webhooks for the following automation events:

| Event Type                | Description                     | Triggers                                               |
| ------------------------- | ------------------------------- | ------------------------------------------------------ |
| `cold_dm.sent`            | Cold DM successfully sent       | When an initial message is sent to a new lead          |
| `followup.sent`           | Follow-up message sent          | When a follow-up message is sent to an existing lead   |
| `reply.received`          | Lead replied to automation      | When a lead responds to your automation messages       |
| `automation.paused`       | Automation automatically paused | When system pauses automation due to limits or issues  |
| `automation.out_of_leads` | Automation has no more leads    | When automation runs out of available leads to contact |

## Common Payload Structure

All webhook events share a common base structure:

```json theme={null}
{
    "event": "event_type",
    "user_id": "string",
    "created_at": "2024-01-15T10:30:00.000Z",
    "data": {
        // Event-specific data
    }
}
```

### Base Fields

| Field        | Type   | Description                                |
| ------------ | ------ | ------------------------------------------ |
| `event`      | string | The webhook event type                     |
| `user_id`    | string | Drippi user ID who owns the automation     |
| `created_at` | string | ISO 8601 timestamp when the event occurred |
| `data`       | object | Event-specific payload data                |

## Event Details

### cold\_dm.sent

Triggered when a cold DM is successfully sent to a new lead.

<CodeGroup>
  ```json Example Payload theme={null}
  {
      "event": "cold_dm.sent",
      "user_id": "user_123456",
      "created_at": "2024-01-15T10:30:00.000Z",
      "data": {
          "event": "cold_dm.sent",
          "user_id": "user_123456",
          "automation_id": "automation_789",
          "lead_twitter_id": "1234567890",
          "lead_data": {
              "id": "1234567890",
              "name": "John Doe",
              "username": "johndoe",
              "created_at": "2020-01-01T00:00:00.000Z",
              "protected": false,
              "location": "San Francisco, CA",
              "url": "https://johndoe.com",
              "description": "Tech entrepreneur and investor",
              "verified": false,
              "entities": {
                  "url": {
                      "urls": []
                  },
                  "description": {
                      "urls": [],
                      "hashtags": [],
                      "mentions": [],
                      "cashtags": []
                  }
              },
              "profile_image_url": "https://pbs.twimg.com/profile_images/123/avatar.jpg",
              "public_metrics": {
                  "followers_count": 1500,
                  "following_count": 300,
                  "tweet_count": 850,
                  "listed_count": 25
              },
              "pinned_tweet_id": null
          },
          "message": "Hi John, I noticed you're interested in tech startups..."
      }
  }
  ```

  ```typescript TypeScript Type theme={null}
  type ColdDmSentWebhook = {
      event: 'cold_dm.sent';
      user_id: string;
      created_at: string;
      data: {
          event: 'cold_dm.sent';
          user_id: string;
          automation_id: string;
          lead_twitter_id: string;
          lead_data: DrippiTwitterUser;
          message: string;
      };
  };
  ```
</CodeGroup>

### followup.sent

Triggered when a follow-up message is sent to an existing lead.

<CodeGroup>
  ```json Example Payload theme={null}
  {
      "event": "followup.sent",
      "user_id": "user_123456",
      "created_at": "2024-01-15T14:45:00.000Z",
      "data": {
          "event": "followup.sent",
          "user_id": "user_123456",
          "automation_id": "automation_789",
          "lead_twitter_id": "1234567890",
          "lead_data": {
              "id": "1234567890",
              "name": "John Doe",
              "username": "johndoe",
              "created_at": "2020-01-01T00:00:00.000Z",
              "protected": false,
              "location": "San Francisco, CA",
              "url": "https://johndoe.com",
              "description": "Tech entrepreneur and investor",
              "verified": false,
              "entities": {
                  "url": {
                      "urls": []
                  },
                  "description": {
                      "urls": [],
                      "hashtags": [],
                      "mentions": [],
                      "cashtags": []
                  }
              },
              "profile_image_url": "https://pbs.twimg.com/profile_images/123/avatar.jpg",
              "public_metrics": {
                  "followers_count": 1500,
                  "following_count": 300,
                  "tweet_count": 850,
                  "listed_count": 25
              },
              "pinned_tweet_id": null
          },
          "message": "Just wanted to follow up on my previous message about..."
      }
  }
  ```

  ```typescript TypeScript Type theme={null}
  type FollowupSentWebhook = {
      event: 'followup.sent';
      user_id: string;
      created_at: string;
      data: {
          event: 'followup.sent';
          user_id: string;
          automation_id: string;
          lead_twitter_id: string;
          lead_data: DrippiTwitterUser;
          message: string;
      };
  };
  ```
</CodeGroup>

### reply.received

Triggered when a lead replies to your automation messages.

<CodeGroup>
  ```json Example Payload theme={null}
  {
      "event": "reply.received",
      "user_id": "user_123456",
      "created_at": "2024-01-15T16:20:00.000Z",
      "data": {
          "event": "reply.received",
          "user_id": "user_123456",
          "automation_id": "automation_789",
          "lead_twitter_id": "1234567890",
          "lead_data": {
              "id": "1234567890",
              "name": "John Doe",
              "username": "johndoe",
              "created_at": "2020-01-01T00:00:00.000Z",
              "protected": false,
              "location": "San Francisco, CA",
              "url": "https://johndoe.com",
              "description": "Tech entrepreneur and investor",
              "verified": false,
              "entities": {
                  "url": {
                      "urls": []
                  },
                  "description": {
                      "urls": [],
                      "hashtags": [],
                      "mentions": [],
                      "cashtags": []
                  }
              },
              "profile_image_url": "https://pbs.twimg.com/profile_images/123/avatar.jpg",
              "public_metrics": {
                  "followers_count": 1500,
                  "following_count": 300,
                  "tweet_count": 850,
                  "listed_count": 25
              },
              "pinned_tweet_id": null
          }
      }
  }
  ```

  ```typescript TypeScript Type theme={null}
  type ReplyReceivedWebhook = {
      event: 'reply.received';
      user_id: string;
      created_at: string;
      data: {
          event: 'reply.received';
          user_id: string;
          automation_id: string;
          lead_twitter_id: string;
          lead_data: DrippiTwitterUser;
      };
  };
  ```
</CodeGroup>

### automation.paused

Triggered when an automation is automatically paused by the system (not by user action).

<CodeGroup>
  ```json Example Payload theme={null}
  {
      "event": "automation.paused",
      "user_id": "user_123456",
      "created_at": "2024-01-15T18:00:00.000Z",
      "data": {
          "event": "automation.paused",
          "user_id": "user_123456",
          "automation_id": "automation_789",
          "details": "automation paused - daily_message_limit_reached"
      }
  }
  ```

  ```typescript TypeScript Type theme={null}
  type AutomationPausedWebhook = {
      event: 'automation.paused';
      user_id: string;
      created_at: string;
      data: {
          event: 'automation.paused';
          user_id: string;
          automation_id: string;
          details: string;
      };
  };
  ```
</CodeGroup>

**Pause Reasons:**

* `automation paused - too many messages`
* `automation paused - account is not verified`
* `automation paused - daily_message_limit_reached`
* `disconnected pause`

### automation.out\_of\_leads

Triggered when an automation runs out of available leads to contact.

<CodeGroup>
  ```json Example Payload theme={null}
  {
      "event": "automation.out_of_leads",
      "user_id": "user_123456",
      "created_at": "2024-01-15T20:15:00.000Z",
      "data": {
          "event": "automation.out_of_leads",
          "user_id": "user_123456",
          "automation_id": "automation_789"
      }
  }
  ```

  ```typescript TypeScript Type theme={null}
  type AutomationOutOfLeadsWebhook = {
      event: 'automation.out_of_leads';
      user_id: string;
      created_at: string;
      data: {
          event: 'automation.out_of_leads';
          user_id: string;
          automation_id: string;
      };
  };
  ```
</CodeGroup>

## Lead Data Structure

The `lead_data` field contains detailed Twitter profile information for the lead:

```typescript theme={null}
type DrippiTwitterUser = {
    id: string; // Twitter user ID
    name: string; // Display name
    username: string; // Twitter handle (without @)
    created_at: string; // ISO 8601 account creation date
    protected: boolean | null; // Whether account is protected
    location: string | null; // User's location
    url: string | null; // User's website URL
    description: string | null; // Bio/description
    verified: boolean | null; // Twitter verification status
    entities: {
        url: {
            urls: any[];
        };
        description: {
            urls: any[];
            hashtags: any[];
            mentions: any[];
            cashtags: any[];
        };
    };
    profile_image_url: string; // Profile picture URL
    public_metrics: {
        followers_count: number; // Number of followers
        following_count: number; // Number of following
        tweet_count: number; // Total tweets
        listed_count: number; // Times listed
    };
    pinned_tweet_id: string | null; // ID of pinned tweet
    gqlId?: string; // GraphQL ID (optional)
};
```

## Handling Webhook Events

### Example Event Handler

```javascript theme={null}
app.post('/webhook', (req, res) => {
    const { event, user_id, created_at, data } = req.body;

    switch (event) {
        case 'cold_dm.sent':
            console.log(`Cold DM sent to @${data.lead_data.username}`);
            // Track successful outreach
            break;

        case 'followup.sent':
            console.log(`Follow-up sent to @${data.lead_data.username}`);
            // Track follow-up engagement
            break;

        case 'reply.received':
            console.log(`Reply from @${data.lead_data.username}`);
            // Notify sales team
            break;

        case 'automation.paused':
            console.log(`Automation paused: ${data.details}`);
            // Alert user to take action
            break;

        case 'automation.out_of_leads':
            console.log(`Automation ${data.automation_id} needs more leads`);
            // Trigger lead generation process
            break;

        default:
            console.log(`Unknown event type: ${event}`);
    }

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

### Idempotency

Implement idempotency to handle duplicate webhook deliveries:

```javascript theme={null}
const processedEvents = new Set();

app.post('/webhook', (req, res) => {
    const { event, user_id, created_at, data } = req.body;

    // Create unique event identifier
    const eventId = `${event}_${user_id}_${created_at}_${data.automation_id}`;

    // Check if already processed
    if (processedEvents.has(eventId)) {
        console.log(`Duplicate event ignored: ${eventId}`);
        return res.status(200).send('OK');
    }

    // Process the event
    processEvent(req.body);

    // Mark as processed
    processedEvents.add(eventId);

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

## Next Steps

* [Webhook Verification](/webhooks/verification) - Learn how to verify webhook signatures
* [Webhooks Overview](/webhooks/introduction) - Get started with webhooks
