Skip to content

Mujib webhook events: every event and its fields

Mujib has 5 webhook events: contact.created, booking.created, booking.cancelled, conversation.handoff and message.received. Every event arrives in the same envelope, and the fields inside data depend on its type. This page is the reference for every field; setup, retries and what your server must answer are in WhatsApp webhook.

A value that does not apply to an event arrives as null; it is never left out of the body. Write your receiver so it ignores any field it does not know.

Every event is a JSON object with five fixed fields, and all the details sit inside data.

FieldTypeMeaning
idstring (UUID)The event id, the same in every webhook that receives this event
typestringThe event type, matching the X-Mujib-Event header
createdAtstringWhen the event happened, in UTC, for example 2026-01-01T09:30:00.000Z
workspaceIdstring (UUID)Your business’s id in Mujib, the same in all your events
dataobjectThe event’s details, as in the sections below

Mujib reads the data once, moments after the event, and every retry of a delivery carries that same body. If what the event is about was deleted before then, nothing is sent.

New customer is sent once per new customer: on the first message from a new sender on WhatsApp, Instagram or Messenger, when you message a number that is not yet a customer from your business phone, or when someone on the team adds a customer in the dashboard.

FieldTypeMeaning
data.contact.idstring (UUID)The customer’s id in Mujib
data.contact.namestring or nullThe customer’s saved name
data.contact.phonestring or nullTheir number as saved, for example 962790000000. Usually null for Messenger and Instagram customers
data.contact.channelstringWhere they came from: whatsapp, instagram, facebook for Messenger, or manual when the team added them
data.contact.stagestringThe customer’s stage: new, engaged, qualified, won or lost
data.contact.createdAtstringWhen the customer was first seen, in UTC
{
"id": "5d7c1e2a-3b4f-4c6d-9e8f-0a1b2c3d4e5f",
"type": "contact.created",
"createdAt": "2026-01-01T00:00:00.000Z",
"workspaceId": "7f3e9a10-2c4b-4d5e-8f60-71829a0b1c2d",
"data": {
"contact": {
"id": "c1a2b3c4-d5e6-4f70-8192-a3b4c5d6e7f8",
"name": "سارة",
"phone": "962790000000",
"channel": "whatsapp",
"stage": "new",
"createdAt": "2026-01-01T00:00:00.000Z"
}
}
}

Which fields do booking.created and booking.cancelled carry?

Section titled “Which fields do booking.created and booking.cancelled carry?”

Both carry the same fields in data.booking: New booking is sent when the agent books an appointment or the team adds one in the calendar, and Booking cancelled when an appointment is cancelled. A recurring booking sends one event per appointment in it.

FieldTypeMeaning
idstring (UUID)The booking id
statusstringrequested, confirmed, cancelled, completed or no_show
sourcestringWho made it: agent or staff
servicestringThe visit type code your business defined
startsAtstringThe start instant in UTC, for example 2026-11-02T14:30:00Z
localTimestringThe start in the branch’s local time, with no zone, for example 2026-11-02T17:30:00
timezonestringThe branch’s time zone, for example Asia/Amman
durationMinutesnumber or nullThe length in minutes; null means your business’s default length
branchobject or nullThe branch: id and name
specialiststring or nullThe specialist’s name, when one is assigned
customerobjectcontactId, name and phone. contactId is null when the booking is not linked to a customer in Mujib
createdAtstringWhen the booking was made, in UTC
{
"id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"type": "booking.created",
"createdAt": "2026-11-01T08:15:02.441Z",
"workspaceId": "7f3e9a10-2c4b-4d5e-8f60-71829a0b1c2d",
"data": {
"booking": {
"id": "b7e6d5c4-b3a2-4910-8f7e-6d5c4b3a2910",
"status": "confirmed",
"source": "agent",
"service": "consultation",
"startsAt": "2026-11-02T14:30:00Z",
"localTime": "2026-11-02T17:30:00",
"timezone": "Asia/Amman",
"durationMinutes": 30,
"branch": { "id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b", "name": "الفرع الرئيسي" },
"specialist": "ليلى",
"customer": { "contactId": "c1a2b3c4-d5e6-4f70-8192-a3b4c5d6e7f8", "name": "سارة", "phone": "962790000000" },
"createdAt": "2026-11-01T08:15:01.982Z"
}
}
}

Which fields does conversation.handoff carry?

Section titled “Which fields does conversation.handoff carry?”

Handed to staff is sent once per handoff to staff, including a handoff that happens because the agent could not reply.

FieldTypeMeaning
data.conversation.idstring (UUID)The conversation id
data.conversation.channelstringwhatsapp, instagram or facebook
data.conversation.reasonstring or nullWhy it was handed over: a short code, or a sentence the agent wrote in the conversation’s language. Show it as it is; do not build fixed rules on it
data.contactobject or nullThe customer: id, name and phone
{
"id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
"type": "conversation.handoff",
"createdAt": "2026-11-01T10:02:47.120Z",
"workspaceId": "7f3e9a10-2c4b-4d5e-8f60-71829a0b1c2d",
"data": {
"conversation": {
"id": "f0e1d2c3-b4a5-4697-8879-6a5b4c3d2e1f",
"channel": "whatsapp",
"reason": "العميلة تطلب عرض سعر خاص لمجموعة"
},
"contact": { "id": "c1a2b3c4-d5e6-4f70-8192-a3b4c5d6e7f8", "name": "سارة", "phone": "962790000000" }
}
}

New message is sent with every message a customer sends on any channel, and carries its text only, never a file.

FieldTypeMeaning
data.message.idstring (UUID)The message id
data.message.conversationIdstring (UUID)The conversation id
data.message.channelstringwhatsapp, instagram or facebook
data.message.typestringThe kind of message, such as text, image, audio, video, document or location
data.message.textstring or nullThe message text, or the transcript of a voice note when one is available, cut after 4000 characters. null for the other kinds
data.message.createdAtstringWhen the message was received, in UTC
data.contactobject or nullThe customer: id, name and phone
{
"id": "8e9f0a1b-2c3d-4e5f-9a6b-7c8d9e0f1a2b",
"type": "message.received",
"createdAt": "2026-11-01T18:40:11.305Z",
"workspaceId": "7f3e9a10-2c4b-4d5e-8f60-71829a0b1c2d",
"data": {
"message": {
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"conversationId": "f0e1d2c3-b4a5-4697-8879-6a5b4c3d2e1f",
"channel": "instagram",
"type": "text",
"text": "هل يوجد موعد غدًا مساءً؟",
"createdAt": "2026-11-01T18:40:11.298Z"
},
"contact": { "id": "d2e3f4a5-b6c7-4d8e-9f0a-1b2c3d4e5f6a", "name": "سارة", "phone": null }
}
}

What does the webhook.test event look like?

Section titled “What does the webhook.test event look like?”

The test event arrives when you press Send a test, signed with the same secret as real events, so it is the right way to test your signature check.

  • It goes only to the webhook whose button you pressed, with a single attempt and no retries.
  • It is not in the list of events you subscribe to, and shows in the log as Test delivery.
{
"id": "0f1e2d3c-4b5a-4968-8776-5a4b3c2d1e0f",
"type": "webhook.test",
"createdAt": "2026-11-01T12:00:00.000Z",
"workspaceId": "7f3e9a10-2c4b-4d5e-8f60-71829a0b1c2d",
"data": {
"test": true,
"message": "This is a test delivery from Mujib. Your endpoint received and can verify it."
}
}

Frequently asked questions

Is there an event for a rescheduled booking?

No. Changing the time or the specialist sends no event. To get a booking's latest state, read it by its id from the Mujib API.

Why is the phone number sometimes empty?

Messenger and Instagram do not share the customer's phone number, so phone stays null unless a number was saved for them in Mujib.

Do the agent's replies arrive as message.received?

No. The event covers incoming customer messages only; replies from the agent and the team are not sent.

What is the difference between the body's id and the X-Mujib-Delivery header?

id identifies the event and is the same in every webhook that receives it. X-Mujib-Delivery identifies one delivery to one webhook and stays the same across retries.