Typing Indicator
Real-time signal that a user is composing a message. The protocol supports both periodic start pings (to refresh the indicator while the user keeps typing) and an explicit stop event (when the user clears the input, sends the message, switches chat, or closes the window). Recording a voice message is composing one too, signalled by voice in place of start.
Send Typing Signal
Fire-and-forget — no id, no response expected.
Request:
{
"type": "typing.set",
"data": {
"conversation_id": "direct:12345:67890",
"state": "start"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
conversation_id |
string | Yes | The conversation being composed in |
state |
string | Yes | "start" (typing), "voice" (recording a voice message) or "stop" (no longer composing) |
Typing Push (Server → Client)
Server forwards the signal to the conversation's other members with the sender's ID:
{
"type": "typing.changed",
"data": {
"conversation_id": "direct:12345:67890",
"user_id": 67890,
"state": "start"
}
}
| Field | Type | Description |
|---|---|---|
conversation_id |
string | The conversation being composed in |
user_id |
number | Who is composing |
state |
string | "start", "voice" or "stop" |
In a direct conversation the server forwards the push only if the recipient has the sender in their contact list, or the sender asked to be there (a contact request). Presence follows contacts alone. If the recipient is offline, the push is dropped silently. Nothing is persisted. For a group or channel, the server verifies membership and fans the signal out to all other online members. Read-only channel members cannot emit typing signals. Typing signals remain ephemeral in both forms.
Client Behavior
Sender:
- While the user is composing a non-empty message in an active chat, send
state: "start"no more often than every 2.5 seconds (throttled); while they record a voice message, sendstate: "voice"the same way. - Send
state: "stop"exactly once when:- The input field becomes empty (user cleared it).
- The message is sent.
- A voice message being recorded is sent, cancelled or paused.
- The user switches to a different chat.
- The chat view goes away (window closed, app quits — best-effort).
- The user signs out.
stop is sent only if there was a prior start or voice for that recipient.
Receiver:
- On
state: "start"or"voice"— start displaying the indicator, which says which of the two, and arm a 5-second timeout to auto-hide it (safety net for loststopevents). - On
state: "stop"— hide the indicator immediately. - On receiving an actual
message.createdevent from the same sender — hide the indicator immediately (the typing session ended with that message).