Documentation Index Fetch the complete documentation index at: https://docs.usetitan.app/llms.txt
Use this file to discover all available pages before exploring further.
Titan delivers 30 event types across eight categories. Every event uses the same outer envelope — an id, event type string, session name, timestamp, and a payload object whose structure depends on the event. Subscribe to the events you need when creating a webhook , or pass ["*"] to receive everything.
All event payloads are documented below with their fields and an example. The payload field maps to the payload key in the delivery envelope:
{
"id" : "evt_abc123" ,
"event" : "message.received" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:30:00Z" ,
"payload" : { ... }
}
Sender and recipient identifiers in payloads follow the JIDRef format:
Individual: { "phoneNumber": "+5511999999999", "lid": "...", "mode": "pn" }
Group: { "id": "[email protected] " }
The mode field is pn (phone number addressing) or lid (linked device ID addressing). For groups and newsletters the id field is present instead.
message.receivedFires when an incoming message arrives on the session. Covers all message types: text, image, video, audio, document, location, contact, poll, sticker, and reactions. {
"id" : "evt_abc123" ,
"event" : "message.received" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:30:00Z" ,
"payload" : {
"id" : "3EB0C767D1826..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"body" : "Hello!" ,
"type" : "text" ,
"text" : "Hello!" ,
"timestamp" : 1736937000 ,
"fromMe" : false ,
"pushName" : "John Doe" ,
"isGroup" : false
}
}
For media messages, the payload also contains a mimeType field and a mediaId you can use to download or persist the file . Field Type Description idstring WhatsApp message ID fromJIDRef Sender’s identifier senderJIDRef In groups, the individual participant who sent the message typestring Message type: text, image, video, audio, document, location, contact, poll, sticker, reaction, revoke, edited, unknown textstring Message text (present when type=text) captionstring Caption (present for image, video, document, sticker) mimeTypestring MIME type of the media attachment fromMeboolean Whether the message was sent by the authenticated account isGroupboolean Whether the message is from a group chat pushNamestring Display name of the sender on WhatsApp timestampinteger Unix timestamp in seconds unavailableboolean true when content is unavailable (view-once or decrypt failure)
message.sentFires when the session successfully sends a message. The payload structure is the same as message.received, with fromMe: true. {
"id" : "evt_def456" ,
"event" : "message.sent" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:31:00Z" ,
"payload" : {
"id" : "3EB0C767D1827..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"type" : "text" ,
"text" : "Hi there!" ,
"timestamp" : 1736937060 ,
"fromMe" : true
}
}
message.ackFires when WhatsApp delivers a delivery or read receipt for one or more messages. {
"id" : "evt_ghi789" ,
"event" : "message.ack" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:31:05Z" ,
"payload" : {
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"sender" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"messageIds" : [ "3EB0C767D1827..." ],
"type" : "read" ,
"timestamp" : 1736937065
}
}
type valueMeaning deliveredMessage delivered to device readMessage opened and read playedVoice note played errorDelivery failed
message.revokedFires when a sender deletes a message for everyone before you process it. The payload.revokedId field contains the ID of the original message. {
"event" : "message.revoked" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:32:00Z" ,
"payload" : {
"id" : "3EB0C767D1830..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"type" : "revoke" ,
"revokedId" : "3EB0C767D1826..." ,
"timestamp" : 1736937120 ,
"fromMe" : false
}
}
message.reactionFires when a contact adds or removes an emoji reaction. The reaction field contains the emoji; an empty string means the reaction was removed. {
"event" : "message.reaction" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:33:00Z" ,
"payload" : {
"id" : "3EB0C767D1831..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"type" : "reaction" ,
"reaction" : "👍" ,
"reactionTo" : "3EB0C767D1826..." ,
"timestamp" : 1736937180 ,
"fromMe" : false
}
}
message.editedFires when a sender edits a previously sent message. The payload.text field contains the updated text. {
"event" : "message.edited" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:34:00Z" ,
"payload" : {
"id" : "3EB0C767D1826..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"type" : "edited" ,
"text" : "Hello, updated!" ,
"edited" : true ,
"timestamp" : 1736937240 ,
"fromMe" : false
}
}
message.updateFires on a general message update that does not fit a more specific event type. {
"event" : "message.update" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:35:00Z" ,
"payload" : {
"id" : "3EB0C767D1826..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736937300 ,
"fromMe" : false
}
}
message.deleteFires when a message is deleted for everyone. {
"event" : "message.delete" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:36:00Z" ,
"payload" : {
"id" : "3EB0C767D1832..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"type" : "revoke" ,
"timestamp" : 1736937360 ,
"fromMe" : false
}
}
message.voteFires when a contact submits a vote on a poll message. {
"event" : "message.vote" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:37:00Z" ,
"payload" : {
"id" : "3EB0C767D1833..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"type" : "poll" ,
"title" : "Favorite color?" ,
"pollOptions" : [
{ "name" : "Blue" , "hash" : "a3f1..." }
],
"timestamp" : 1736937420 ,
"fromMe" : false
}
}
session.statusFires whenever the session’s connection state changes. Use this event to track whether a session is online and to detect disconnects. {
"event" : "session.status" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:00:00Z" ,
"payload" : {
"status" : "DISCONNECTED" ,
"statusReason" : "FAILED"
}
}
statusstatusReasonMeaning CONNECTINGSCAN_QRWaiting for QR code scan CONNECTINGAUTO_RECONNECTReconnecting after a drop CONNECTED— Authenticated and active DISCONNECTEDMANUAL_STOPStopped via API DISCONNECTEDLOGGED_OUTWhatsApp account unlinked DISCONNECTEDQR_TIMEOUTQR code expired without a scan DISCONNECTEDFAILEDConnection error DISCONNECTEDTEMPORARY_BANTemporary ban by WhatsApp DISCONNECTEDSTREAM_ERRORWebSocket stream error
session.qrFires when a new QR code is generated for pairing. Display the payload.code value to the user as a QR code so they can scan it from WhatsApp. {
"event" : "session.qr" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:00:05Z" ,
"payload" : {
"code" : "2@ABC123XYZ..."
}
}
session.connectedFires once after successful pairing. Contains the phone number and display name of the linked WhatsApp account. {
"event" : "session.connected" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T10:01:00Z" ,
"payload" : {
"phoneNumber" : "+5511999999999" ,
"pushName" : "John Doe" ,
"businessName" : null ,
"lid" : "12345@lid"
}
}
session.logged_outFires when the WhatsApp account unlinks the session (for example, from WhatsApp Settings > Linked Devices). The session moves to DISCONNECTED with reason LOGGED_OUT and must be re-paired to reconnect. {
"event" : "session.logged_out" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T12:00:00Z" ,
"payload" : {}
}
group.updateFires when a group’s subject, description, or picture changes, or when the session joins a group via an invite link. {
"event" : "group.update" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:00:00Z" ,
"payload" : {
"id" : "[email protected] " ,
"newSubject" : "New Group Name" ,
"newDescription" : "Updated group description" ,
"action" : null
}
}
When action is "joined", the session joined the group via an invite link. The subject and description fields are omitted in that case. group.participantFires when participants join, leave, are promoted, or are demoted in a group. {
"event" : "group.participant" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:05:00Z" ,
"payload" : {
"id" : "[email protected] " ,
"joined" : [
{ "phoneNumber" : "+5511888888888" , "lid" : "..." , "mode" : "pn" }
],
"left" : [],
"promoted" : [],
"demoted" : []
}
}
Each of joined, left, promoted, and demoted is an array of JIDRef objects. Only the arrays with changes are populated.
presence.updateFires when a contact’s presence state changes. You receive this event for contacts whose presence you have subscribed to via POST /api/{session}/presence/subscribe. {
"event" : "presence.update" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:10:00Z" ,
"payload" : {
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"sender" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"state" : "composing" ,
"media" : null ,
"unavailable" : false ,
"lastSeen" : null
}
}
stateMeaning composingContact is typing pausedContact stopped typing
When unavailable is true, the contact went offline. lastSeen contains their last seen Unix timestamp when available.
call.receivedFires when an incoming call is detected on the session. {
"event" : "call.received" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:15:00Z" ,
"payload" : {
"id" : "CALL123..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736938500
}
}
call.missedFires when an incoming call was not answered. {
"event" : "call.missed" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:15:30Z" ,
"payload" : {
"id" : "CALL123..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736938530
}
}
call.acceptedFires when the session accepts an incoming call. {
"event" : "call.accepted" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:16:00Z" ,
"payload" : {
"id" : "CALL123..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736938560
}
}
call.rejectedFires when the session rejects an incoming call. {
"event" : "call.rejected" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:16:05Z" ,
"payload" : {
"id" : "CALL123..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736938565
}
}
chat.archiveFires when a chat is archived or unarchived. {
"event" : "chat.archive" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:25:00Z" ,
"payload" : {
"id" : "3EB0C767D1841..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736939100 ,
"fromMe" : false
}
}
chat.muteFires when a chat is muted or unmuted. {
"event" : "chat.mute" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:26:00Z" ,
"payload" : {
"id" : "3EB0C767D1842..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736939160 ,
"fromMe" : false
}
}
chat.readFires when a chat is marked as read. {
"event" : "chat.read" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:27:00Z" ,
"payload" : {
"id" : "3EB0C767D1843..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736939220 ,
"fromMe" : false
}
}
chat.clearFires when the chat history is cleared. {
"event" : "chat.clear" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:28:00Z" ,
"payload" : {
"id" : "3EB0C767D1844..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736939280 ,
"fromMe" : false
}
}
chat.deleteFires when a chat is deleted. {
"event" : "chat.delete" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:29:00Z" ,
"payload" : {
"id" : "3EB0C767D1845..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736939340 ,
"fromMe" : false
}
}
labels.updateFires when a label is assigned to or removed from a chat. {
"event" : "labels.update" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:30:00Z" ,
"payload" : {
"id" : "3EB0C767D1846..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736939400 ,
"fromMe" : false
}
}
newsletter.updateFires when a channel (newsletter) you follow is updated. {
"event" : "newsletter.update" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:31:00Z" ,
"payload" : {
"id" : "3EB0C767D1847..." ,
"from" : { "id" : "120363012345678901@newsletter" },
"timestamp" : 1736939460 ,
"fromMe" : false
}
}
blocklist.updateFires when a contact is blocked or unblocked. {
"event" : "blocklist.update" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:32:00Z" ,
"payload" : {
"id" : "3EB0C767D1848..." ,
"from" : { "phoneNumber" : "+5511999999999" , "lid" : "..." , "mode" : "pn" },
"timestamp" : 1736939520 ,
"fromMe" : false
}
}
history.syncFires when WhatsApp delivers a chunk of conversation history. The payload contains a syncType field describing the kind of history sync and a data field with the encoded history content. {
"event" : "history.sync" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:33:00Z" ,
"payload" : {
"syncType" : "RECENT" ,
"data" : "..." ,
"timestamp" : 1736939580
}
}
Sync types include INITIAL_BOOTSTRAP, INITIAL_STATUS_V3, FULL, RECENT, PUSH_NAME, NON_BLOCKING_DATA, and ON_DEMAND. command.resultFires when an async command you submitted with Prefer: respond-async completes. Match the result to your original request using the correlationId. {
"event" : "command.result" ,
"session" : "my-session" ,
"timestamp" : "2025-01-15T11:34:00Z" ,
"payload" : {
"correlationId" : "req_xyz789" ,
"result" : { ... },
"error" : null
}
}
See Async commands for details on the Prefer: respond-async pattern.