Skip to main content
POST
/
hooks
Add Webhook
curl --request POST \
  --url https://api.lemlist.com/api/hooks \
  --header 'Authorization: Basic <encoded-value>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "targetUrl": "https://webhook.site/00000000-0000-0000-0000-000000000000"
}
'
{
  "_id": "hoo_GvYkkWIcdPf2WsBDY",
  "targetUrl": "https://n8n.example.com/webhook/lemlist-webhook-surprise",
  "createdAt": "2025-10-29T00:47:42.035Z",
  "type": "linkedinInterested"
}

Documentation Index

Fetch the complete documentation index at: https://developer.lemlist.com/llms.txt

Use this file to discover all available pages before exploring further.

Available event types

When creating a webhook, you can subscribe to specific events using the type field. Events are organized by category below.

Lead state groups

These aggregate multiple activity types into a single lead-state change event.
EventDescription
contactedLead was contacted (email sent, LinkedIn message, API call, etc.)
hookedLead opened a message (email, LinkedIn, WhatsApp)
attractedLead clicked a link or accepted a LinkedIn invite
warmedLead replied (email, LinkedIn, WhatsApp, SMS)
interestedLead marked as interested
notInterestedLead marked as not interested

Email activities

EventDescription
emailsSentEmail sent
emailsOpenedEmail opened
emailsClickedLink clicked in email
emailsRepliedEmail replied
emailsBouncedEmail bounced
emailsFailedEmail failed to send
emailsInterestedLead marked as interested via email
emailsNotInterestedLead marked as not interested via email
emailsUnsubscribedLead unsubscribed via email

LinkedIn activities

EventDescription
linkedinSentLinkedIn message sent
linkedinOpenedLinkedIn message opened
linkedinRepliedLinkedIn message replied
linkedinInterestedLead marked as interested via LinkedIn
linkedinNotInterestedLead marked as not interested via LinkedIn
linkedinSendFailedLinkedIn message failed to send
linkedinVisitDoneLinkedIn profile visit completed
linkedinVisitFailedLinkedIn profile visit failed
linkedinFollowDoneLinkedIn follow completed
linkedinFollowFailedLinkedIn follow failed
linkedinFollowSkippedLinkedIn follow skipped
linkedinInviteDoneLinkedIn invite sent
linkedinInviteFailedLinkedIn invite failed
linkedinInviteAcceptedLinkedIn invite accepted
linkedinEndorseDoneLinkedIn endorsement completed
linkedinEndorseFailedLinkedIn endorsement failed
linkedinEndorseSkippedLinkedIn endorsement skipped
linkedinVoiceNoteDoneLinkedIn voice note sent
linkedinVoiceNoteFailedLinkedIn voice note failed
linkedinLikeLastPostDoneLinkedIn like last post completed
linkedinLikeLastPostNoPostLinkedIn like last post — no post found
linkedinLikeLastPostFailedLinkedIn like last post failed
linkedinWithdrawInvitationDoneLinkedIn invite withdrawn
linkedinWithdrawInvitationFailedLinkedIn invite withdrawal failed

WhatsApp activities

EventDescription
whatsappMessageSentWhatsApp message sent
whatsappMessageDeliveredWhatsApp message delivered
whatsappMessageOpenedWhatsApp message opened
whatsappRepliedWhatsApp message replied
whatsappMessageFailedWhatsApp message failed

SMS activities

EventDescription
smsSentSMS sent
smsDeliveredSMS delivered
smsRepliedSMS replied
smsFailedSMS failed

Call activities

EventDescription
aircallCreatedCall created
aircallEndedCall ended
aircallDoneCall task completed
aircallInterestedLead marked as interested via call
aircallNotInterestedLead marked as not interested via call
callRecordingDoneCall recording ready
callTranscriptDoneCall transcript ready

API activities

EventDescription
apiDoneAPI step executed
apiInterestedLead marked as interested via API
apiNotInterestedLead marked as not interested via API
apiFailedAPI step failed

Manual activities

EventDescription
manualInterestedLead marked as interested manually
manualNotInterestedLead marked as not interested manually

Task activities

EventDescription
annotatedLead annotated

Workspace activities

EventDescription
pausedLead paused
resumedLead resumed
stoppedLead stopped
campaignCompleteCampaign completed
customDomainErrorsCustom domain error detected
connectionIssueEmail account connection issue
sendLimitReachedDaily send limit reached
lemwarmPausedLemwarm paused

Enrichment

EventDescription
enrichmentDoneEnrichment completed
enrichmentErrorEnrichment failed

Inbox activities

EventDescription
inboxLabelUpdatedInbox conversation label changed

Signal Agents

EventDescription
signalRegisteredNew signal detected by a Signal Agent

Deliverability hub

EventDescription
deliverabilityAlertTriggeredDeliverability alert triggered

Deprecated events

These events have been removed from the API. Use the replacements below.
Removed eventReplacement
skippedNo direct replacement
emailsSendFailedUse emailsFailed instead
opportunitiesDoneUse annotated or task-level webhooks instead

Verifying webhook authenticity

You can pass an optional secret in the request body when creating the webhook. It works like a shared password between lemlist and your endpoint:
  • Stored encrypted at rest.
  • Never returned by GET /hooks or any other endpoint.
  • Immutable — it cannot be changed after creation. To rotate it, delete the webhook and create a new one.
  • Sent back to your endpoint as a secret field in the JSON body of every webhook call, so you can verify the request originated from lemlist.

Webhook payload

Each event is delivered as a POST to your targetUrl with a JSON body that mirrors the underlying activity record. Common fields:
FieldTypeDescription
_idstringUnique activity identifier (act_…)
typestringEvent type (e.g. emailsSent, emailsReplied)
teamIdstringTeam the activity belongs to
createdAtISO dateWhen the activity happened
campaignIdstringSource campaign (absent for non-campaign events)
campaignNamestringCampaign display name
sequenceIdstringSequence the task belonged to
sequenceStepnumber0-based step index in the sequence
leadIdstringLead targeted by the activity
leadEmail, leadFirstName, leadLastNamestringDenormalized lead identity
sendUserId, sendUserEmail, sendUserNamestringSender (lemlist user) identity
subjectstringEmail subject (email events only)
secretstringEchoed back if a secret was set on the webhook

Email recipients (to / cc / bcc)

Email events (emailsSent, emailsReplied, emailsBounced) carry the full recipient lists as arrays of {address, name}. Addresses are lowercased. Fields are omitted when empty.
{
  "type": "emailsSent",
  "to":  [{ "address": "lead@example.com", "name": "Alice Doe" }],
  "cc":  [{ "address": "manager@example.com", "name": "" }],
  "bcc": [{ "address": "archive@crm.io", "name": "" }]
}
  • to — primary recipient(s). For outbound sends, this is the lead. For inbound replies, this is the mailbox owner; multi-recipient to lines (e.g. reply-all where the lead manually added people) are preserved.
  • cc — explicit CC recipients on the email.
  • bcc — only present for outbound emailsSent events when the sender has a hidden BCC configured in Settings → Integrations (users.lemlist.bcc). Inbound BCC is never visible because SMTP strips it for non-BCC’d recipients.

Third-party reply flag

When a reply on a thread comes from an address that does not match the original lead’s known contact emails, lemlist attributes the reply to the third-party sender rather than to the lead, and the event carries an extra flag:
{
  "type": "emailsReplied",
  "isThirdPartyReply": true
}
Third-party reply payloads omit campaignId, leadId, and sequenceId (since the reply is no longer attached to the original campaign flow). Use the flag to route these events differently if needed.

Examples

{
	"targetUrl": "https://webhook.site/your-id"
}
Tip: You can include an optional zapId if you use Zapier to track the webhook mapping on your side.

Authorizations

Authorization
string
header
required

Basic authentication header of the form Basic <encoded-value>, where <encoded-value> is the base64-encoded string username:password.

Query Parameters

campaignId
string

Webhook for specific campaign

isFirst
boolean

Webhook for first activity only

zapId
string

Zapier ID

Body

application/json
targetUrl
string<uri>
required

The URL that will receive webhook POST requests.

type
enum<string>

Optional event type to subscribe to. When omitted, all events are sent. See the full categorized list in the endpoint documentation.

Available options:
contacted,
hooked,
attracted,
warmed,
interested,
notInterested,
emailsSent,
emailsOpened,
emailsClicked,
emailsReplied,
emailsBounced,
emailsFailed,
emailsInterested,
emailsNotInterested,
emailsUnsubscribed,
linkedinSent,
linkedinOpened,
linkedinReplied,
linkedinInterested,
linkedinNotInterested,
linkedinSendFailed,
linkedinVisitDone,
linkedinVisitFailed,
linkedinFollowDone,
linkedinFollowFailed,
linkedinFollowSkipped,
linkedinInviteDone,
linkedinInviteFailed,
linkedinInviteAccepted,
linkedinEndorseDone,
linkedinEndorseFailed,
linkedinEndorseSkipped,
linkedinVoiceNoteDone,
linkedinVoiceNoteFailed,
linkedinLikeLastPostDone,
linkedinLikeLastPostNoPost,
linkedinLikeLastPostFailed,
linkedinWithdrawInvitationDone,
linkedinWithdrawInvitationFailed,
whatsappMessageSent,
whatsappMessageDelivered,
whatsappMessageOpened,
whatsappReplied,
whatsappMessageFailed,
smsSent,
smsDelivered,
smsReplied,
smsFailed,
aircallCreated,
aircallEnded,
aircallDone,
aircallInterested,
aircallNotInterested,
apiDone,
apiInterested,
apiNotInterested,
apiFailed,
manualInterested,
manualNotInterested,
paused,
resumed,
stopped,
campaignComplete,
customDomainErrors,
connectionIssue,
sendLimitReached,
lemwarmPaused,
annotated,
enrichmentDone,
enrichmentError,
callRecordingDone,
callTranscriptDone,
inboxLabelUpdated,
signalRegistered,
deliverabilityAlertTriggered
secret
string

Optional shared secret. Stored encrypted, never returned by GET, and immutable once set. Sent back to your endpoint as a secret field in the body of every webhook call so you can verify the request originated from lemlist.

Response

Success

_id
string

Unique identifier for the webhook

targetUrl
string

The URL where the webhook will send data

createdAt
string<date-time>

Timestamp when the webhook was created

type
string

Type of webhook event