# Events ```mermaid --- Events flow through it --- sequenceDiagram actor Andrea participant API actor Blake Note over Andrea,Blake: Subscribing to events Andrea ->> API : Subscribe Blake ->> API : Subscribe Note over Andrea,Blake: Sending a message Andrea ->>+ API : Send "hello, world!" API -->>- Andrea : Accepted Note over Andrea,Blake: Receiving events par API --) Andrea : Andrea sent "hello, world!" and API --) Blake : Andrea sent "hello, world!" end ``` The core of the service is to facilitate conversations between users. Conversational activity is delivered to clients using _events_. Each event notifies interested clients of activity sent to the service through its API. ## Asynchronous completion A number of endpoints return `202 Accepted` responses. The actions performed by those endpoints will be completed before events are delivered. To await the completion of an operation which returns this response, clients must monitor the event stream for the corresponding event. ## `GET /api/events` Subscribes to events. This endpoint is designed for use with the [EventSource] DOM API, and supports several features of that API, as described below. Other clients may implement these features for themselves. [EventSource]: https://developer.mozilla.org/en-US/docs/Web/API/EventSource ### Query parameters This endpoint requires a `resume_point` (integer) query parameter. The event stream will collect events published after that point in time. The value must be obtained by calling the [`GET /api/boot`](./boot.md) method. ### Request headers This endpoint accepts an optional `last-event-id` (string) header. If present, the value must be the value of the `id` field of the last message processed by the client. The returned event stream will begin with the following message. If absent, the returned event stream will begin from the start of the event collection. This header is set automatically by `EventSource` when reconnecting to an event stream. ### Success This endpoint will respond with a status of `200 Okay` when successful. The body of the response is an [event stream]: [event stream]: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format ``` id: 1234 data: { data: "type": "message", data: "event": "sent", data: "at": "2024-09-27T23:19:10.208147Z", data: "conversation": "C9876cyyz", data: "sender": "U1234abcd", data: "id": "M1312acab", data: "body": "beep" data: } ``` The service will keep the connection open, and will deliver events as they occur. The service may terminate the connection at any time. Clients should reconnect and resume the stream, using the `last-event-id` header to resume from the last message received. The `id` of each event is an ephemeral ID, useful only for this purpose. Each event's `data` consists of a JSON object describing one event. Every event includes the following fields: | Field | Type | Description | | :------ | :--------------- | :----------------------------------------------------------------------------------------------------------- | | `type` | string | The type of entity the event describes. Will be one of the types listed in the next section. | | `event` | string, optional | The specific kind of event. Will be one of the events listed with the associated `type` in the next section. | The remaining fields depend on the `type` and (if present) the `event` field. ## Heartbeat events ```json { "type": "heartbeat" } ``` To help clients detect network interruptions, the service guarantees that it will deliver an event after a fixed interval called the "heartbeat interval." The specific interval length is given in seconds as part of the [boot response](./boot.md). If the service determines that the heartbeat interval is close to expiring, it will synthesize and deliver a heartbeat event. Clients should treat any period of time without events, longer than the heartbeat interval, as an indication that the event stream may have been interrupted. Clients may also use other techniques, such as [browser APIs](https://developer.mozilla.org/en-US/docs/Web/API/EventSource/error_event), to detect this condition and restart the connection. These events have the `type` field set to `"heartbeat"`. The `event` field is absent. ## User events The following events describe changes to users. These events have the `type` field set to `"user"`. ### User created ```json { "type": "user", "event": "created", "at": "2024-09-27T23:17:10.208147Z", "id": "U1234abcd", "name": "example username" } ``` Sent whenever a new user is created. These events have the `event` field set to `"created"`. They include the following additional fields: | Field | Type | Description | | :----- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | | `at` | timestamp | The moment the user was created. | | `id` | string | A unique identifier for the newly-created user. This can be used to associate the user with other events, or to make API calls targeting the user. | | `name` | string | The user's name. | ## Conversation events The following events describe changes to [conversations](conversations-messages.md). These events have the `type` field set to `"conversation"`. ### Conversation created ```json { "type": "conversation", "event": "created", "at": "2024-09-27T23:18:10.208147Z", "id": "C9876cyyz", "name": "example conversation 2" } ``` Sent whenever a new conversation is created. These events have the `event` field set to `"created"`. They include the following additional fields: | Field | Type | Description | | :----------- | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `at` | timestamp | The moment the conversation was created. | | `id` | string | A unique identifier for the newly-created conversation. This can be used to associate the conversation with other events, or to make API calls targeting the conversation. | | `name` | string | The conversation's name. | | `deleted_at` | timestamp, optional | If set, the moment the conversation was deleted. | When a conversation is deleted or expires, the `"created"` event is replaced with a tombstone `"created"` event, so that the original conversation cannot be trivially recovered from the event stream. Tombstone events have a `deleted_at` field, and a `name` of `""`. Tombstone events for conversation use an empty string as the name, and not `null` or with the `name` field removed entirely, to simplify client development. While clients _should_ treat deleted conversation specially, for example by rendering them as "conversation deleted" markers, they don't have to be - they make sense if interpreted as conversation with empty names, too. Once a deleted conversation is [purged](conversations-messages.md#expiry-and-purging), these tombstone events are removed from the event stream. ### Conversation deleted ```json { "type": "conversation", "event": "deleted", "at": "2024-09-28T03:40:25.384318Z", "id": "C9876cyyz" } ``` Sent whenever a conversation is deleted or expires. These events have the `event` field set to `"deleted"`. They include the following additional fields: | Field | Type | Description | | :---- | :-------- | :--------------------------------------- | | `at` | timestamp | The moment the conversation was deleted. | | `id` | string | The deleted conversation's ID. | ## Message events The following events describe changes to [messages](conversations-messages.md). These events have the `type` field set to `"message"`. ### Message sent ```json { "type": "message", "event": "sent", "at": "2024-09-27T23:19:10.208147Z", "conversation": "C9876cyyz", "sender": "U1234abcd", "id": "M1312acab", "body": "an effusive blob of prose, condensed down to a single string" } ``` Sent whenever a message is sent by a client. These events have the `event` field set to `"sent"`. They include the following additional fields: | Field | Type | Description | | :------------- | :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------- | | `at` | timestamp | The moment the message was sent. | | `conversation` | string | The ID of the conversation the message was sent to. | | `sender` | string | The ID of the user that sent the message. | | `id` | string | A unique identifier for the message. This can be used to associate the message with other events, or to make API calls targeting the message. | | `body` | string | The text of the message. | | `deleted_at` | timestamp, optional | If set, the moment the message was deleted. | When a message is deleted or expires, the `"sent"` event is replaced with a tombstone `"sent"` event, so that the original message cannot be trivially recovered from the event stream. Tombstone events have a `deleted_at` field, and a `body` of `""`. Tombstone events for messages use an empty string as the `body`, and not `null` or with the `body` field removed entirely, to simplify client development. While clients _should_ treat deleted messages specially, for example by rendering them as "message deleted" markers, they don't have to be - they make sense if interpreted as messages with empty bodies, too. Once a deleted message is [purged](conversations-messages.md#expiry-and-purging), these tombstone events are removed from the event stream. ### Message deleted ```json { "type": "message", "event": "deleted", "at": "2024-09-28T02:44:27.077355Z", "id": "M1312acab" } ``` Sent whenever a message is deleted or expires. These events have the `event` field set to `"deleted"`. They include the following additional fields: | Field | Type | Description | | :---- | :-------- | :---------------------------------- | | `at` | timestamp | The moment the message was deleted. | | `id` | string | The deleted message's ID. |