Set up real-time webhooks to sync SmartLead events with your CRM, database, or automation tools — including event types, payload formats, and security verification
Webhooks let SmartLead push real-time event notifications to your server whenever something happens in a campaign — a lead replies, an email bounces, someone unsubscribes, or a message is sent. Instead of polling the API for updates, you receive instant HTTP POST requests to your endpoint.This guide covers how to set up webhooks, handle events, verify payloads, and integrate with common tools like CRMs and Slack.
from flask import Flask, request, jsonifyapp = Flask(__name__)@app.route('/webhooks/smartlead', methods=['POST'])def handle_webhook(): event = request.json if event['event_type'] == 'EMAIL_REPLIED': print(f"Reply from {event['lead']['email']}") # Sync to CRM, create task, notify Slack elif event['event_type'] == 'EMAIL_BOUNCED': print(f"Bounce: {event['lead']['email']}") # Flag in database, update lead quality score elif event['event_type'] == 'LEAD_UNSUBSCRIBED': print(f"Unsubscribed: {event['lead']['email']}") # Add to suppression list return jsonify({'received': True}), 200if __name__ == '__main__': app.run(port=3000)
Always return a 200 status code within 30 seconds. If your endpoint times out or returns an error, SmartLead will retry the webhook up to 3 times with exponential backoff.
Verify your endpoint is publicly accessible (not localhost). Check that the webhook is active (is_active: true). Ensure your endpoint returns a 200 response within 30 seconds. Check server logs for incoming requests.
Receiving duplicate events
SmartLead may retry if your server didn’t respond with 200 in time. Implement idempotency by checking the message_id or timestamp — skip events you’ve already processed.
Webhook payloads are missing fields
Not all event types include all fields. For example, reply_body is only present on EMAIL_REPLIED events. Always check for the existence of fields before accessing them.