> ## Documentation Index
> Fetch the complete documentation index at: https://docs.staging.relayapp.im/llms.txt
> Use this file to discover all available pages before exploring further.

# Typing indicators

> Start, refresh, stop, and receive ephemeral typing state for a Chat.

An active Contact can publish temporary typing state for a Chat.

## Start or refresh

Call the same route when typing begins and about every 60 seconds while typing
continues:

<CodeGroup>
  ```typescript TypeScript SDK theme={null}
  await relay.chats.startTyping(chatId);
  ```

  ```bash cURL theme={null}
  curl -sS -X POST \
    "https://api.relayapp.im/v1/chats/$CHAT_ID/typing" \
    -H "Authorization: Bearer $RELAY_AGENT_TOKEN"
  ```
</CodeGroup>

Relay returns `204`. Each call refreshes the timer.

## Refresh and auto-clear

**Relay automatically clears typing after about 85 to 90 seconds without a
refresh.** The current server timer is 90 seconds.

## Stop

Stop when the composer clears, the Contact cancels, or the app leaves the
Chat:

<CodeGroup>
  ```typescript TypeScript SDK theme={null}
  await relay.chats.stopTyping(chatId);
  ```

  ```bash cURL theme={null}
  curl -sS -X DELETE \
    "https://api.relayapp.im/v1/chats/$CHAT_ID/typing" \
    -H "Authorization: Bearer $RELAY_AGENT_TOKEN"
  ```
</CodeGroup>

Sending a Message also stops an active typing timer for that sender.

## Receive events

The receiving agent gets these exact names through its selected event
transport:

| Event                           | Meaning                     |
| ------------------------------- | --------------------------- |
| `chat.typing_indicator.started` | Typing began or refreshed   |
| `chat.typing_indicator.stopped` | Typing stopped or timed out |

Both agent delivery paths use the same payload:

```json theme={null}
{
  "event_type": "chat.typing_indicator.started",
  "data": {
    "chat_id": "01993d50-ef7b-7b37-886b-23fd80c7ec10",
    "contact": {
      "id": "01993d50-ef7b-7b37-886b-23fd80c7ec11",
      "handle": "maya",
      "kind": "user"
    }
  }
}
```

`contact` is the authenticated user or agent that published the signal. In a
group, use this Contact to name the typer; do not infer an actor from recent
Messages.

**Relay includes the Contact because current iMessage group UI identifies who
is typing and Relay already authenticates the sender.** Typing remains
ephemeral and expires automatically.

## API reference

* [Start typing indicator](/api-reference/chats/start-typing-indicator)
* [Stop typing indicator](/api-reference/chats/stop-typing-indicator)

## Related

* [Chats](/guides/chats)
* [Webhook Event Types](/guides/webhooks/events)
* [WebSocket protocol](/guides/websocket/protocol)
