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:{
"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.{
"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..."
}
}
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;
};
};
followup.sent
Triggered when a follow-up message is sent to an existing lead.{
"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..."
}
}
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;
};
};
reply.received
Triggered when a lead replies to your automation messages.{
"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
}
}
}
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;
};
};
automation.paused
Triggered when an automation is automatically paused by the system (not by user action).{
"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"
}
}
type AutomationPausedWebhook = {
event: 'automation.paused';
user_id: string;
created_at: string;
data: {
event: 'automation.paused';
user_id: string;
automation_id: string;
details: string;
};
};
automation paused - too many messagesautomation paused - account is not verifiedautomation paused - daily_message_limit_reacheddisconnected pause
automation.out_of_leads
Triggered when an automation runs out of available leads to contact.{
"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"
}
}
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;
};
};
Lead Data Structure
Thelead_data field contains detailed Twitter profile information for the lead:
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
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: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 - Learn how to verify webhook signatures
- Webhooks Overview - Get started with webhooks