Skip to main content

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": { ... }
}

JID format

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.received

Fires 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.
FieldTypeDescription
idstringWhatsApp message ID
fromJIDRefSender’s identifier
senderJIDRefIn groups, the individual participant who sent the message
typestringMessage type: text, image, video, audio, document, location, contact, poll, sticker, reaction, revoke, edited, unknown
textstringMessage text (present when type=text)
captionstringCaption (present for image, video, document, sticker)
mimeTypestringMIME type of the media attachment
fromMebooleanWhether the message was sent by the authenticated account
isGroupbooleanWhether the message is from a group chat
pushNamestringDisplay name of the sender on WhatsApp
timestampintegerUnix timestamp in seconds
unavailablebooleantrue when content is unavailable (view-once or decrypt failure)

message.sent

Fires 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.ack

Fires 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.revoked

Fires 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.reaction

Fires 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.edited

Fires 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.update

Fires 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.delete

Fires 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.vote

Fires 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.status

Fires 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
CONNECTEDAuthenticated 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.qr

Fires 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.connected

Fires 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_out

Fires 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.update

Fires 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.participant

Fires 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.update

Fires 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.received

Fires 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.missed

Fires 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.accepted

Fires 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.rejected

Fires 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
  }
}

contact.update

Fires when a contact’s profile information (display name or picture) changes.
{
  "event": "contact.update",
  "session": "my-session",
  "timestamp": "2025-01-15T11:20:00Z",
  "payload": {
    "id": "3EB0C767D1840...",
    "from": { "phoneNumber": "+5511999999999", "lid": "...", "mode": "pn" },
    "timestamp": 1736938800,
    "fromMe": false
  }
}

chat.archive

Fires 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.mute

Fires 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.read

Fires 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.clear

Fires 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.delete

Fires 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.update

Fires 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.update

Fires 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.update

Fires 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.sync

Fires 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.result

Fires 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.