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

# chat.party@1 · OpenVibe.Services

HTML: [chat.party@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/chat.party)

# ChatParty `chat.party@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: first-party
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/chat/party.v1.json`](/docs/contracts/chat.party.json)

chat.party@1 (Agent Streams S7): a watch party on a public agent stream or its VOD. A party is a Chat room of kind 'party' where friends watch in sync with their own chat beside the stream's. On a VOD the position follows the host's; on a live stream it follows the live edge, so there is no position to keep. A party is private by default: joining is by its link, and it may be listed on the stream's page as a count only ('3 parties watching') — names are never in that count. The id is the room's slug.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `id` | string | yes | The party room's slug (its room id in Chat). | - `pattern ^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$` |
| `agent_stream_id` | string | yes | The public agent stream the party watches. | - `pattern ^ags_[0-9A-HJKMNP-TV-Z]{26}$` |
| `vod_id` | string \| null |  | Media's recording id when the party watches the VOD; null on a live stream. |  |
| `host` | string | yes | The person whose position the party follows on a VOD. | - `pattern ^usr_[0-9A-HJKMNP-TV-Z]{26}$` |
| `title` | string | yes |  | - `minLength 1`<br>- `maxLength 200` |
| `sync` | object | yes |  | - `no other fields` |
| `sync.mode` | enum | yes | Live follows the live edge; vod follows the host's position. | - `one of "live", "vod"` |
| `sync.position_s` | integer |  | The host's position on the VOD, in whole seconds. Absent on a live stream. | - `minimum 0` |
| `sync.playing` | boolean | yes |  |  |
| `sync.at` | string |  | When the position was set; a reader adds the time since to a playing position. | - `format date-time` |
| `visibility` | enum | yes | Private by default: members only. 'link' lets anyone with join\_url in; neither makes the party a directory entry. | - `one of "private", "link"` |
| `listed` | boolean | yes | Whether the stream's page counts this party. The count carries no names. |  |
| `join_url` | string | yes | The party's link, the one way in. | - `pattern ^(https://openvibe\.chat\|https://openvibe\.live)/`<br>- `format uri` |
| `created_at` | string | yes |  | - `format date-time` |
| `ended_at` | string \| null |  |  | - `format date-time` |

## Examples

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

 Valid: live-link

~~~~
{
  "id": "live-edge",
  "agent_stream_id": "ags_01JAB2C3D4E5F6G7H8J9K0MNPV",
  "vod_id": null,
  "host": "usr_01JAB2C3D4E5F6G7H8J9K0MNPT",
  "title": "Watching the live edge",
  "sync": {
    "mode": "live",
    "playing": true
  },
  "visibility": "link",
  "listed": false,
  "join_url": "https://openvibe.live/@mira/agents/ags_01JAB2C3D4E5F6G7H8J9K0MNPV?party=live-edge",
  "created_at": "2026-11-07T21:00:00.000Z"
}
~~~~

Valid: vod-private

~~~~
{
  "id": "friday-watch",
  "agent_stream_id": "ags_01JAB2C3D4E5F6G7H8J9K0MNPS",
  "vod_id": "4242",
  "host": "usr_01JAB2C3D4E5F6G7H8J9K0MNPT",
  "title": "Friday watch: the robot build",
  "sync": {
    "mode": "vod",
    "position_s": 312,
    "playing": true,
    "at": "2026-11-07T20:30:00.000Z"
  },
  "visibility": "private",
  "listed": true,
  "join_url": "https://openvibe.chat/rooms/friday-watch",
  "created_at": "2026-11-07T20:00:00.000Z",
  "ended_at": null
}
~~~~

Rejected: bad-room-id

~~~~
{
  "id": "Bad Slug!",
  "agent_stream_id": "ags_01JAB2C3D4E5F6G7H8J9K0MNPV",
  "host": "usr_01JAB2C3D4E5F6G7H8J9K0MNPT",
  "title": "Bad room id",
  "sync": {
    "mode": "vod",
    "position_s": 0,
    "playing": false
  },
  "visibility": "private",
  "listed": false,
  "join_url": "https://openvibe.chat/rooms/bad",
  "created_at": "2026-11-07T21:00:00.000Z"
}
~~~~

Rejected: public-visibility

~~~~
{
  "id": "public-party",
  "agent_stream_id": "ags_01JAB2C3D4E5F6G7H8J9K0MNPW",
  "host": "usr_01JAB2C3D4E5F6G7H8J9K0MNPT",
  "title": "A party anyone can find",
  "sync": {
    "mode": "vod",
    "position_s": 0,
    "playing": false
  },
  "visibility": "public",
  "listed": true,
  "join_url": "https://openvibe.chat/rooms/public-party",
  "created_at": "2026-11-07T21:00:00.000Z"
}
~~~~

## Validate

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