Skip to main content
Typing indicators and read receipts make an automated conversation feel attended. You start and stop your typing indicator with POST and DELETE /v1/chats/{chat_id}/typing, mark a chat as read with POST /v1/chats/{chat_id}/read, and hear when your contacts are typing through the chat.typing_indicator.started and chat.typing_indicator.stopped webhooks.

Show a typing indicator

Start the indicator before you send a reply, and stop it if you decide not to send one.
curl
curl
Both return 204 No Content with an X-Trace-ID header. Typing is best effort: a 204 means Blujay accepted the request, not that the other person saw a typing bubble. Blujay doesn’t promise how long the bubble stays up. Start it right before you send, and call DELETE if you decide not to send. What happens depends on the chat: Check the chat’s supports_typing_indicators field from GET /v1/chats/{chat_id} to know in advance whether an indicator can appear. You can call the typing endpoints either way.

Mark a chat as read

POST /v1/chats/{chat_id}/read marks every incoming message in the chat as read in Blujay. It works on the whole chat; there is no per-message read, and the call takes no body.
curl
It returns 204 No Content. In direct iMessage and RCS chats, Blujay also sends a read receipt, so the other person can see that you read their messages. SMS chats and group chats are only marked read in Blujay; nobody is notified. Mark-read ignores Idempotency-Key; calling it twice is harmless. A 503 PHONE_NUMBER_UNAVAILABLE means the read receipt couldn’t be sent. The chat is still marked read in Blujay, so you can retry or move on.

Receive typing indicators

Subscribe to chat.typing_indicator.started and chat.typing_indicator.stopped to hear when a contact is typing to one of your numbers in a direct iMessage chat. SMS and RCS chats never produce typing events, and your own typing calls never produce them.
chat.typing_indicator.started
occurred_at is when Blujay observed the typing, not the exact keystroke time. expires_at is always 60 seconds after occurred_at.

Group typing snapshots

Subscriptions on webhook version 2026-10-03 also receive typing for iMessage group chats, but only on Dedicated numbers (access_type: "dedicated" in GET /v1/phone-numbers). Earlier versions never receive group typing, and a Free Plan number never does. A group event uses the same two event types and adds participants: everyone typing in that group right now.
chat.typing_indicator.started (group)
  • started always lists at least one participant. stopped has "participants": [].
  • There are no per-person events. When one person stops while another keeps typing, you get another started with the shorter list. Replace the chat’s whole list of typers with each newer snapshot.
  • Each participant has type (phone or email) and address, plus contact_id when they match a contact in your workspace. Your own Blujay numbers never appear.

Display typing correctly

Typing events can be repeated, delayed or out of order, and a stopped event isn’t guaranteed. Apply these rules for each chat_id and phone_number_id pair:
1

Deduplicate

Ignore any event_id you have already processed.
2

Drop stale events

Ignore an event whose expires_at has passed, or whose occurred_at is older than the last event you applied.
3

Break ties toward stop

If a started and a stopped have the same occurred_at, apply the stopped.
4

Expire on your own

Clear the indicator at expires_at even if no stopped arrives.
A refreshed indicator arrives as another started event with a later occurred_at and expires_at.
Common mistakes
  • A 204 from POST /typing doesn’t mean a bubble appeared. Check supports_typing_indicators on the chat if it matters.
  • POST /read marks the whole chat, not one message.
  • A stopped event isn’t guaranteed. Clear the indicator at expires_at on your own.
  • Group typing events need webhook version 2026-10-03 and a Dedicated number. On older versions or a Free Plan number, you’ll never see them.

Limitations

  • Typing indicators you send appear only in direct iMessage chats and established iMessage groups. Everything else is accepted with 204 and shows nothing.
  • No duration is promised for a typing bubble, and Blujay doesn’t confirm that it was shown.
  • Typing can be switched off for a workspace (400 FEATURE_NOT_ENABLED); only support can switch it back on.
  • Read receipts go out for direct iMessage and RCS chats only. SMS and group chats are marked read in Blujay without notifying anyone.
  • Mark-read covers the whole chat. There is no per-message read receipt.
  • Incoming typing events come from direct iMessage chats, and from iMessage groups only on Dedicated numbers with webhook version 2026-10-03. SMS and RCS chats never produce them.
  • Your own typing calls never produce typing events.

Next steps

Webhooks overview

Create a subscription for typing and message events.

Webhook versions

Move to 2026-10-03 to receive group typing snapshots.

Group chats

Learn what makes a group an established iMessage group.

Send messages

Send the reply after your typing indicator.