Skip to content

n8n Triggers

The Tenreply Trigger node registers a webhook with Tenreply and fires your workflow every time the selected event occurs. One event per trigger node; add more trigger nodes to react to different events.

If your n8n instance cannot receive inbound HTTP, use Tenreply Trigger (Polling) instead — see the end of this page.

Events

GroupEventFires when
Messagingmessage.receivedA customer sends a message (WhatsApp, Instagram DM, Messenger)
message.sentAn agent or automation sends a message
message.deliveredA sent message is delivered
message.readThe customer reads a message
message.failedDelivery fails
Conversationsconversation.createdA new conversation starts
conversation.status_changedOpened, closed, pending, or a custom status label changes
conversation.assignedAssigned to a team member or returned to the queue
Contactscontact.createdA contact is created — manually, by API, or from a first inbound message
contact.updatedA contact record changes
contact.taggedTags are added to or removed from a contact (including automatic behaviour tags)
Campaignsbroadcast.completedA broadcast send finishes
sequence.enrolledA contact is enrolled in a drip sequence
sequence.completedA contact reaches the end of a sequence
Socialsocial_post.publishedA LinkedIn, Instagram, or Facebook post goes live
social_post.failedA post could not be published
comment.receivedSomeone comments on an Instagram or Facebook post
CRMdeal.createdA deal is added to a pipeline
deal.stage_changedA deal moves to another stage
deal.status_changedA deal is marked won, lost, or reopened

Every delivery carries the event name in the X-Tenreply-Event header.

Event payloads

message.received

{
"message": {
"id": "msg_abc123",
"conversationId": "conv_xyz",
"contactId": "contact_def",
"direction": "inbound",
"type": "text",
"content": { "text": "Hello, I need help!" },
"status": "delivered",
"waMessageId": "wamid.abc",
"timestamp": "2026-06-01T10:00:00.000Z"
},
"conversation": { "id": "conv_xyz", "status": "open", "channel": "whatsapp", "contactId": "contact_def" },
"contact": { "id": "contact_def", "name": "Jane Doe", "phoneNumber": "1234567890" }
}

message.sent and message.failed carry { "message": { … } }; message.delivered and message.read carry { "waMessageId", "status", "errorMessage" }.

conversation.created / conversation.status_changed / conversation.assigned

{
"conversation": {
"id": "conv_xyz",
"status": "closed",
"statusLabelId": null,
"channel": "whatsapp",
"contactId": "contact_def",
"assignedAgentId": "user_42",
"contact": { "id": "contact_def", "name": "Jane Doe" }
},
"previousStatus": "open",
"previousStatusLabelId": null,
"changedByUserId": "user_42"
}

conversation.assigned replaces the previousStatus* keys with previousAssignedAgentId and assignedAgentId.

contact.created / contact.updated / contact.tagged

{
"contact": {
"id": "contact_def",
"phoneNumber": "1234567890",
"name": "Jane Doe",
"email": "jane@example.com",
"tags": ["vip", "customer"],
"createdAt": "2026-06-01T10:00:00.000Z"
},
"source": "manual",
"changes": ["tags"],
"addedTags": ["customer"],
"removedTags": []
}

source is manual (UI/API) or inbound (first message) on contact.created; changes lists the fields touched on contact.updated; addedTags / removedTags appear on contact.tagged, with source: "behaviour" when the CRM applied them automatically.

broadcast.completed

{
"broadcastId": "bcast_123",
"broadcastSendId": "send_456",
"name": "June promo",
"channel": "whatsapp",
"sent": 842,
"failed": 3,
"completedAt": "2026-06-01T11:00:00.000Z"
}

social_post.published / social_post.failed

{
"post": {
"id": "post_789",
"platform": "instagram",
"postType": "reel",
"caption": "Launch day 🚀",
"mediaUrls": ["https://…/launch.mp4"],
"status": "published",
"externalPostId": "17895695668004550"
},
"platform": "instagram",
"postType": "reel",
"status": "published",
"externalPostId": "17895695668004550"
}

social_post.failed carries status: "failed" and an errorMessage.

comment.received

{
"platform": "instagram",
"comment": {
"commentId": "17912345678901234",
"parentCommentId": null,
"mediaId": "17895695668004550",
"socialPostId": "post_789",
"fromId": "1784…",
"fromUsername": "jane.doe",
"text": "Is this available in blue?",
"commentedAt": "2026-06-01T12:00:00.000Z"
},
"post": { "id": "post_789", "platform": "instagram", "caption": "Launch day 🚀" }
}

Facebook comments use postId and fromName instead of mediaId and fromUsername. Feed comment.commentId into Social Comment → Reply or Reply Privately.

deal.created / deal.stage_changed / deal.status_changed

{
"deal": {
"id": "deal_1",
"title": "Website redesign",
"pipelineId": "pipe_1",
"stageId": "stage_3",
"contactId": "contact_def",
"value": "2500.00",
"currency": "INR",
"status": "won",
"stage": { "id": "stage_3", "name": "Won" }
},
"previousStatus": "open",
"status": "won"
}

deal.stage_changed carries previousStageId and stageId instead of the status keys.

sequence.enrolled / sequence.completed

{
"enrollment": { "id": "enr_1", "contactId": "contact_def", "sequenceId": "seq_1", "status": "active", "currentStep": 0 },
"sequence": { "id": "seq_1", "name": "Onboarding" },
"contactId": "contact_def"
}

Signature verification

Each delivery includes the header X-Tenreply-Signature: sha256=<hmac-hex>. The node verifies this automatically (constant-time) using the secret returned when the subscription was created. To skip verification (e.g. local testing), open the node’s Options and disable Verify Signature.

Tenreply Trigger (Polling)

For n8n instances without a public URL. The node polls Tenreply on the workflow’s schedule for one of:

EventSource
New ContactContacts, newest first
New ConversationConversations, newest first
New Inbound MessageCustomer messages, newest first

The first run after activation records what already exists instead of replaying it; later runs emit only rows the node has not seen, oldest first. “Fetch Test Event” returns the most recent row. Webhooks remain the better choice whenever they are possible: they fire instantly and cover all 20 events above.