Skip to main content

Webhook Payloads

Every webhook is an HTTP POST request to your Webhook URL with a JSON body. This page describes that body: the envelope that is the same for all 18 events, and every object that can appear inside it.

The request

PropertyValue
MethodPOST
URLExactly the Webhook URL saved in Settings -> Webhooks, with no path or query string added
Content typeapplication/json
BodyThe envelope described below
HeadersNo signature header, no authentication header and no custom Dead Simple Chat headers are sent

Because no identifying header is sent, an endpoint that accepts these requests is accepting them from anyone who knows the URL. See Delivery and limitations for how to work around that.

The envelope

The body always has exactly two top-level keys:

JSON
{
"event": "new_chatroom_message",
"data": {
"chatMessage": { }
}
}
FieldTypeDescription
eventstringOne of the 18 strings listed in the Event reference. Switch on this field.
dataobjectThe payload for that event. Its keys depend on the event.

data holds one object under a named key for most events — chatMessage, channelMessage, chatRoom, channel, user, likeAction or privateMessage. The one exception is private_message_initiated, which puts member_one, member_two and chatRoom directly on data.

info

Always branch on the event string rather than on the shape of data. Several events share the same data key, and new event types may be added.

Which identifier each event gives you

Dead Simple Chat has two kinds of room identifier: the public roomId (a short string such as bbNiVFoXm, the one the REST API uses) and the internal _id (a 24-character hex id). Not every event carries the public one, and some carry no room identifier at all.

eventWhere the room or channel is identified
chatroom_created, chatroom_updated, chatroom_deleteddata.chatRoom.roomId (public) and data.chatRoom._id
channel_created, channel_updated, channel_deleteddata.channel.roomId (public) and data.channel._id
user_joined_chatroomdata.user.lastChatRoomId (public roomId)
user_left_chatroomNot included
new_chatroom_message, chatroom_message_deleted, chatroom_message_approveddata.chatMessage.chatRoom — the internal _id only
chatroom_message_like_toggleNot included — only data.likeAction.messageId
new_channel_message, channel_message_deleted, channel_message_approveddata.channelMessage.channel — the internal channel _id only
channel_message_like_toggledata.likeAction.channelId — the internal channel _id only
private_message_initiated, new_private_messagedata.chatRoom / data.privateMessage.chatRoom (public roomId)
caution

The message events give you the room's internal _id, and the REST API addresses rooms by their public roomId. The two are different values and one cannot be derived from the other. If you need to call the REST API in response to a message event, build a lookup of _id to roomId — the Get All Chat Rooms API returns both.

Objects

chatRoom

Sent by chatroom_created, chatroom_updated and chatroom_deleted. It carries the room's full current configuration — the same fields the Get a Chat Room API returns, not only the ones that changed.

The fields most consumers need:

FieldTypeDescription
_idstringInternal id of the chat room
roomIdstringPublic room id, the one used by the REST API and the embed URL
namestringName of the chat room
descriptionstringDescription of the chat room
metadatastringYour own metadata for the room
customerstringYour account id
chatRoomPermissionLevelstringpublic, provisioned_users or members
createdstringISO 8601 timestamp
caution

Because this is the complete record, it also contains the room's configuration — including roomPassword for a password-protected room, and bannedUsers with the IP addresses of banned users. Use an https Webhook URL and treat the payload as sensitive.

chatroom_created (chatRoom object abridged)
{
"event": "chatroom_created",
"data": {
"chatRoom": {
"_id": "653f9e50ed0f012c972936fa",
"roomId": "bbNiVFoXm",
"name": "Support Room",
"description": "Chat Room created using the API",
"customer": "631794a83671700c713b1ce5",
"chatRoomPermissionLevel": "public",
"passwordProtected": false,
"preModeratedChatRoom": false,
"enableChannels": true,
"enableOneToOneChat": true,
"created": "2026-09-02T10:14:08.213Z",
"__v": 0
}
}
}

channel

Sent by channel_created, channel_updated and channel_deleted. Unlike chatRoom, this is a fixed set of five fields, not the whole channel record:

FieldTypeDescription
_idstringInternal id of the channel. This is the value that appears as channel on a channelMessage.
channelNamestringName of the channel
enabledbooleanWhether the channel is enabled
notifyAllUsersbooleanWhether all users are notified of messages in this channel
roomIdstringPublic roomId of the chat room the channel belongs to

A channel's metadata is not included, even though channels can store it.

channel_created
{
"event": "channel_created",
"data": {
"channel": {
"_id": "6540f869ed0f012c9729384b",
"channelName": "announcements",
"enabled": true,
"notifyAllUsers": false,
"roomId": "bbNiVFoXm"
}
}
}

user

Sent by user_joined_chatroom and user_left_chatroom, but the two are not the same shape.

user_joined_chatroom

The full user record for the user who joined. The fields you are most likely to need:

FieldTypeDescription
_idstringInternal id of the user
usernamestringDisplay name in the chat room
lastChatRoomIdstringPublic roomId of the room just joined — the only room identifier in this payload
isModeratorbooleanWhether the user joined as a moderator
uniqueUserIdentifierstringYour identifier for a provisioned user, if the user was provisioned
externalUserIdstringYour external id for the user, if one was set
metastringYour metadata for the user, if any
profilePicstringProfile picture URL
emailstringEmail address, if the user has one
firstName, lastNamestringSet for provisioned users
parentCustomerAccountstringYour account id
ipAddressstringIP address the user connected from
created, updatedstringISO 8601 timestamps
user_joined_chatroom
{
"event": "user_joined_chatroom",
"data": {
"user": {
"_id": "648e211a81cea20bd8b1581d",
"username": "alice",
"uniqueUserIdentifier": "crm-40121",
"isModerator": false,
"claimed": false,
"verified": false,
"profilePic": "https://example.com/avatars/alice.png",
"meta": "{\"tier\":\"gold\"}",
"parentCustomerAccount": "631794a83671700c713b1ce5",
"lastChatRoomId": "bbNiVFoXm",
"lastSeen": "2026-09-02T11:02:44.019Z",
"created": "2026-08-14T09:31:10.442Z",
"updated": "2026-09-02T11:02:44.019Z",
"__v": 0
}
}
}

user_left_chatroom

A reduced object with only these five fields:

FieldTypeDescription
_idstringInternal id of the user
usernamestringDisplay name
emailstringEmail address, if any
isModeratorbooleanWhether the user was a moderator
parentCustomerAccountstringYour account id

There is no lastChatRoomId and no room reference of any kind, so this event cannot tell you which room was left. Match on _id against the user_joined_chatroom event you stored earlier.

user_left_chatroom
{
"event": "user_left_chatroom",
"data": {
"user": {
"_id": "648e211a81cea20bd8b1581d",
"username": "alice",
"isModerator": false,
"parentCustomerAccount": "631794a83671700c713b1ce5"
}
}
}

chatMessage

Sent by new_chatroom_message, chatroom_message_deleted and chatroom_message_approved.

FieldTypeDescription
_idstringInternal id of the message
messagestringThe message text, after HTML sanitisation
createdstringISO 8601 timestamp
chatRoomstringInternal _id of the chat room — not the public roomId
customerstringYour account id
userobjectThe sender, in the same shape as the user object above
likesarrayReactions on the message. Empty on a new message.
disapprovedboolPresent and true while a message is held in a pre-moderated chat room. Absent once approved.
fileobjectPresent when the message has an attachment: _id, url, fileName, size, fileType, contentType, imageWidth, imageHeight
repliedToobjectPresent when the message is a reply: message, username, userId, messageId, messageCreatedAt
pollstringId of the poll, when the message created one
systemMessagebooltrue for messages sent as system messages through the API
messageOnlyVisibleToUserstringSet when the message is visible to a single user only
new_chatroom_message
{
"event": "new_chatroom_message",
"data": {
"chatMessage": {
"_id": "632a11a5f0357f1c648791eb",
"likes": [],
"created": "2026-09-02T11:04:12.848Z",
"chatRoom": "653f9e50ed0f012c972936fa",
"message": "Has anyone seen the release notes?",
"user": {
"_id": "648e211a81cea20bd8b1581d",
"username": "alice",
"isModerator": false,
"parentCustomerAccount": "631794a83671700c713b1ce5",
"lastChatRoomId": "bbNiVFoXm"
},
"customer": "631794a83671700c713b1ce5",
"__v": 0
}
}
}
info

When a message is sent through the Send Chat Room Message API with a userAccessToken, the user object carries two extra fields, accessTokenId and iat. Read the fields you need by name rather than assuming a fixed set.

channelMessage

Sent by new_channel_message, channel_message_deleted and channel_message_approved. It is the same idea as chatMessage with two differences: it identifies a channel instead of a chat room, and it has no customer field.

FieldTypeDescription
_idstringInternal id of the channel message
messagestringThe message text, after HTML sanitisation
createdstringISO 8601 timestamp
channelstringInternal _id of the channel. There is no chat room field.
userobjectThe sender, in the same shape as the user object above
likesarrayReactions on the message
disapprovedboolPresent and true while held in a pre-moderated chat room
fileobjectPresent when the message has an attachment, same fields as above
repliedToobjectPresent when the message is a reply, same fields as above
new_channel_message
{
"event": "new_channel_message",
"data": {
"channelMessage": {
"_id": "6540f961ed0f012c972938a1",
"likes": [],
"created": "2026-09-02T11:06:55.104Z",
"channel": "6540f869ed0f012c9729384b",
"message": "Deploy is finished.",
"user": {
"_id": "648e211a81cea20bd8b1581d",
"username": "alice",
"isModerator": true,
"parentCustomerAccount": "631794a83671700c713b1ce5"
},
"__v": 0
}
}
}

likeAction

Sent by chatroom_message_like_toggle and channel_message_like_toggle. It describes one reaction being added or removed — it is not the message and not the full list of reactions.

FieldTypeDescription
messageIdstringInternal id of the message that was reacted to
reactionstringOne of wave, thumbs_up, clap, pray, strong, celebrate, heart
actionstringliked when the reaction was added, unliked when it was removed
usernamestringDisplay name of the user who reacted
userIdstringInternal id of the user who reacted
channelIdstringchannel_message_like_toggle only. Internal _id of the channel the message is in.
chatroom_message_like_toggle
{
"event": "chatroom_message_like_toggle",
"data": {
"likeAction": {
"messageId": "632a11a5f0357f1c648791eb",
"reaction": "thumbs_up",
"username": "bob",
"userId": "648e2dfe81cea20bd8b15901",
"action": "liked"
}
}
}

private_message_initiated

This event does not nest its payload under a named key. member_one, member_two and chatRoom sit directly on data.

FieldTypeDescription
member_oneobjectThe user who opened the conversation
member_twoobjectThe other participant
chatRoomstringPublic roomId of the chat room the conversation is in

Both member objects have the same five fields:

FieldTypeDescription
_idstringInternal id of the user
usernamestringDisplay name
externalUserIdstringYour external id for the user, if set
profilePicstringProfile picture URL
metastringYour metadata for the user, if any
private_message_initiated
{
"event": "private_message_initiated",
"data": {
"member_one": {
"_id": "648e211a81cea20bd8b1581d",
"username": "alice",
"externalUserId": "crm-40121",
"profilePic": "https://example.com/avatars/alice.png",
"meta": "{\"tier\":\"gold\"}"
},
"member_two": {
"_id": "648e2dfe81cea20bd8b15901",
"username": "bob",
"profilePic": "https://example.com/avatars/bob.png"
},
"chatRoom": "bbNiVFoXm"
}
}

privateMessage

Sent by new_private_message.

FieldTypeDescription
member_oneobjectOne participant, in the five-field shape above
member_twoobjectThe other participant
messagestringThe message text, after HTML sanitisation
userstringInternal id of the sender. Compare it with member_one._id and member_two._id to find out who sent it.
chatRoomstringPublic roomId of the chat room the conversation is in

There is no message id, no conversation id and no timestamp on this payload. Use Get Chat Room Conversations and Get Conversation Messages if you need them.

new_private_message
{
"event": "new_private_message",
"data": {
"privateMessage": {
"member_one": {
"_id": "648e211a81cea20bd8b1581d",
"username": "alice",
"externalUserId": "crm-40121",
"profilePic": "https://example.com/avatars/alice.png",
"meta": "{\"tier\":\"gold\"}"
},
"member_two": {
"_id": "648e2dfe81cea20bd8b15901",
"username": "bob",
"profilePic": "https://example.com/avatars/bob.png"
},
"message": "Can you take a look at ticket 214?",
"user": "648e211a81cea20bd8b1581d",
"chatRoom": "bbNiVFoXm"
}
}
}

A minimal handler

Node.js / Express
app.post("/hooks/deadsimplechat", express.json(), (req, res) => {
// Acknowledge first. A slow response is a lost webhook; there is no retry.
res.sendStatus(200);

const { event, data } = req.body;

switch (event) {
case "new_chatroom_message":
console.log(data.chatMessage.user.username, "said", data.chatMessage.message);
break;
case "user_joined_chatroom":
console.log(data.user.username, "joined room", data.user.lastChatRoomId);
break;
case "channel_created":
console.log("channel", data.channel.channelName, "in room", data.channel.roomId);
break;
default:
console.log("unhandled event", event);
}
});