---
title: "chat.room-insight-result@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/chat.room-insight-result"
updated: null
---

# chat.room-insight-result@1 · OpenVibe.Services

HTML: [chat.room-insight-result@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/chat.room-insight-result)

# ChatRoomInsightResult `chat.room-insight-result@1`

Generated at 2026-11-13 06:25:48 UTC from [`openvibe-contracts v0.419.0`](https://github.com/OpenVibers/OpenVibe.Contracts/tree/v0.419.0) and [`openvibe-sdk v0.161.0`](https://github.com/OpenVibers/OpenVibe.SDK/tree/v0.161.0).

- Version: 1.0.0
- Owner: chat
- Visibility: public
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/chat/room-insight-result.v1.json`](/docs/contracts/chat.room-insight-result.json)

chat.room-insight-result@1: the answer of GET /api/v1/rooms/:id/insight on OpenVibe.Chat, public (no account, as the room itself is readable). One shape for every room: Global (id \`global\`) first, then a server's channels and the rooms people make. The overview is the summary OpenVibe.Chat's chat-AI job keeps (the same schedule, window and budget rules as Live's, only when there were new messages); it reads only the messages of people who allowed AI use of them (network.consent@1, purpose ai.train on kind chat), so an overview never quotes someone who did not. state is \`ready\` when the overview is fresh, \`quiet\` when there is nothing new to say (text and topics empty, the timeline keeps history), and \`off\` when the room's owner has not turned the insight on (private rooms; never a DM). A room the rollout does not cover answers 404. Timestamps are Chat's UTC \`YYYY-MM-DD HH:MM:SS\` (ov\_now()), or null.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `overview` | object | yes |  | - `no other fields` |
| `overview.text` | string | yes | The overview written for someone arriving now, in plain prose; empty when state is quiet or off. | - `maxLength 2000` |
| `overview.topics` | array of object | yes | The words the window kept coming back to, most mentioned first. Empty when state is quiet or off. | - `maxItems 20`<br>- `items: no other fields` |
| `overview.topics[].label` | string | yes |  | - `minLength 1`<br>- `maxLength 60` |
| `overview.topics[].count` | integer | yes | How many messages of the window mentioned the topic. | - `minimum 1` |
| `overview.people` | integer | yes | How many different people wrote in the window the overview reads. | - `minimum 0` |
| `overview.messages` | integer | yes | How many messages the window held (the ones the summariser was allowed to read). | - `minimum 0` |
| `overview.from` | string \| null | yes | The window's first message time. |  |
| `overview.to` | string \| null | yes | The window's last time, which is when the job last looked. |  |
| `overview.updated_at` | string \| null | yes | When the overview row was last written. |  |
| `timeline` | array of object | yes | The room's notable moments, newest first. History survives a quiet window. | - `maxItems 60`<br>- `items: no other fields` |
| `timeline[].at` | string | yes | When it happened, Chat's UTC \`YYYY-MM-DD HH:MM:SS\`. |  |
| `timeline[].kind` | string | yes | What kind of moment: \`moment\` for a notable thing the summariser recorded, \`event\` for a non-chat activity (a donation, a clip), \`message\` for a line it picked out. | - `maxLength 20` |
| `timeline[].title` | string | yes |  | - `minLength 1`<br>- `maxLength 140` |
| `timeline[].text` | string | yes |  | - `maxLength 400` |
| `timeline[].message_id` | integer \| null | yes | The message it came from, when it is one message; null for a summary of several. | - `minimum 1` |
| `state` | enum | yes | ready: the overview above is fresh. quiet: nothing new to say; said as quiet, never invented. off: the room's owner has not turned insight on. | - `one of "ready", "quiet", "off"` |

## Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

 Valid: quiet

~~~~
{
  "overview": {
    "text": "",
    "topics": [],
    "people": 0,
    "messages": 0,
    "from": null,
    "to": null,
    "updated_at": null
  },
  "timeline": [],
  "state": "quiet"
}
~~~~

Valid: ready

~~~~
{
  "overview": {
    "text": "People are planning the Friday stream and comparing two capture cards. Someone asked for the clip of the ending, and the room voted for a Saturday replay.",
    "topics": [
      {
        "label": "capture card",
        "count": 7
      },
      {
        "label": "friday stream",
        "count": 4
      }
    ],
    "people": 9,
    "messages": 42,
    "from": "2026-11-10 08:10:00",
    "to": "2026-11-10 09:45:00",
    "updated_at": "2026-11-10 09:45:03"
  },
  "timeline": [
    {
      "at": "2026-11-10 09:40:12",
      "kind": "moment",
      "title": "The Saturday replay",
      "text": "The room agreed on a replay at the weekend.",
      "message_id": 90214
    },
    {
      "at": "2026-11-10 09:12:44",
      "kind": "event",
      "title": "A donation came in",
      "text": "goosely gave 500 OpenCoins for the capture card fund.",
      "message_id": null
    }
  ],
  "state": "ready"
}
~~~~

Rejected: bad-state

~~~~
{
  "overview": {
    "text": "A room whose state is not one of the three.",
    "topics": [],
    "people": 1,
    "messages": 1,
    "from": null,
    "to": null,
    "updated_at": null
  },
  "timeline": [],
  "state": "busy"
}
~~~~

Rejected: no-timeline

~~~~
{
  "overview": {
    "text": "An overview without its timeline.",
    "topics": [],
    "people": 0,
    "messages": 0,
    "from": null,
    "to": null,
    "updated_at": null
  },
  "state": "ready"
}
~~~~

## Validate

~~~~
const contracts = require('openvibe-contracts');
contracts.validate('chat.room-insight-result@1', value);   // { valid, errors: [{ path, message }] }
~~~~
