openvibers/openvibe.contracts Commits
Contracts 0.152.0: video.playlist.read/manage are active (openvibe.video's playlist API) (#108)
Changes
@@@ -4,6 +4,16 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) thfrom `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,the notes were in the tag and commit messages (`git tag -n1`).++## 0.152.0 — 2026-10-12++++- **`video.playlist.read` and `video.playlist.manage` are active.** openvibe.video's playlist API (MediaHub#33) takes a++ person's Network token, an app/agent/service token with one of these, or no token for a public or unlisted playlist++ by id and a person's public list (`GET /api/v1/video/users/:username/playlists`). An app owns playlists under its own++ requester and project and never touches a person's.++- New schemas (owner media-hub): `video.playlist@1`, `video.playlist-read-request@1`, `video.playlist-read-result@1`,++ `video.playlist-manage-request@1` and `video.playlist-manage-result@1`, with fixtures; the two capabilities name them.++ Additive only (compat vs 0.151.0: no breaking changes).++## 0.151.0 — 2026-10-12- The media-hub site is named **Video** (tagline "Past streams, clips and your drive"): its public origin is openvibe.video,@@@ -7013,6 +7013,51 @@"compatibility": "backward","status": "active","adr": "ADR-004"++ },++ {++ "id": "video.playlist",++ "version": "1.0.0",++ "owner": "media-hub",++ "schema": "video/playlist.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "video.playlist-read-request",++ "version": "1.0.0",++ "owner": "media-hub",++ "schema": "video/playlist-read-request.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "video.playlist-read-result",++ "version": "1.0.0",++ "owner": "media-hub",++ "schema": "video/playlist-read-result.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "video.playlist-manage-request",++ "version": "1.0.0",++ "owner": "media-hub",++ "schema": "video/playlist-manage-request.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "video.playlist-manage-result",++ "version": "1.0.0",++ "owner": "media-hub",++ "schema": "video/playlist-manage-result.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"}]}nnew file mode 100644@@@ -0,0 +1,99 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist-manage-request.v1.json",++ "title": "VideoPlaylistManageRequest",++ "description": "video.playlist-manage-request@1: bodies of video.playlist.manage on openvibe.video. POST /api/v1/video/playlists { title, description?, visibility? } creates one (default private; 422 playlist.invalid_title over 120 characters, playlist.invalid_description over 2,000, playlist.invalid_visibility, playlist.limit at 100 per owner). PATCH /api/v1/video/playlists/:id { title?, description?, visibility? }. POST /api/v1/video/playlists/:id/items { kind, id } adds one (409 playlist.item_duplicate; 422 playlist.invalid_kind, playlist.invalid_item, playlist.items_limit at 500). PATCH /api/v1/video/playlists/:id/items { items: [{ kind, id }, ...] } reorders: the full list, each item once (422 playlist.invalid_items). DELETE /api/v1/video/playlists/:id and /items/:kind/:itemId take no body. Another owner's playlist answers 404 playlist.not_found.",++ "anyOf": [++ {++ "type": "object",++ "minProperties": 1,++ "additionalProperties": false,++ "properties": {++ "title": {++ "type": "string",++ "minLength": 1++ },++ "description": {++ "type": "string"++ },++ "visibility": {++ "enum": [++ "public",++ "unlisted",++ "private"++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "anyOf": [++ {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ {++ "type": "string",++ "pattern": "^[1-9][0-9]{0,15}$"++ }++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "items"++ ],++ "properties": {++ "items": {++ "type": "array",++ "maxItems": 500,++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "anyOf": [++ {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ {++ "type": "string",++ "pattern": "^[1-9][0-9]{0,15}$"++ }++ ]++ }++ }++ }++ }++ }++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,100 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist-manage-result.v1.json",++ "title": "VideoPlaylistManageResult",++ "description": "video.playlist-manage-result@1: { playlist } after a create (201, Location) or an edit, { item } after an add (201), { items } after a reorder; a delete answers 204 with no body.",++ "anyOf": [++ {++ "type": "object",++ "required": [++ "playlist"++ ],++ "properties": {++ "playlist": {++ "$ref": "playlist.v1.json"++ }++ }++ },++ {++ "type": "object",++ "required": [++ "item"++ ],++ "properties": {++ "item": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ },++ {++ "type": "object",++ "required": [++ "items"++ ],++ "properties": {++ "items": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ }++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,18 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist-read-request.v1.json",++ "title": "VideoPlaylistReadRequest",++ "description": "video.playlist-read-request@1: video.playlist.read takes no body. GET /api/v1/video/playlists (the caller's own), GET /api/v1/video/playlists/:id (the owner sees a private one; anyone a public or unlisted one; otherwise 404 playlist.not_found, never 403) and the open GET /api/v1/video/users/:username/playlists, whose query is { limit?, cursor? } (limit 1-50, default 20; cursor is the previous page's next_cursor; 404 user.not_found).",++ "type": "object",++ "properties": {++ "limit": {++ "type": "integer",++ "minimum": 1,++ "maximum": 50++ },++ "cursor": {++ "type": "string",++ "maxLength": 400++ }++ }++}nnew file mode 100644@@@ -0,0 +1,74 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist-read-result.v1.json",++ "title": "VideoPlaylistReadResult",++ "description": "video.playlist-read-result@1: a list ({ playlists, next_cursor? }) or one playlist with its ordered items ({ playlist, items }).",++ "anyOf": [++ {++ "type": "object",++ "required": [++ "playlists"++ ],++ "properties": {++ "playlists": {++ "type": "array",++ "items": {++ "$ref": "playlist.v1.json"++ }++ },++ "next_cursor": {++ "type": [++ "string",++ "null"++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "playlist",++ "items"++ ],++ "properties": {++ "playlist": {++ "$ref": "playlist.v1.json"++ },++ "items": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ }++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,73 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist.v1.json",++ "title": "VideoPlaylist",++ "description": "video.playlist@1: one playlist on openvibe.video as the API returns it. `owner` is present on reads of one playlist: a person (kind user, with their username when known) or an app, agent or service (never named).",++ "type": "object",++ "required": [++ "id",++ "title",++ "description",++ "visibility",++ "item_count",++ "created_at",++ "updated_at"++ ],++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^vpl_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "A playlist id (vpl_ + ULID)."++ },++ "title": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "description": {++ "type": "string",++ "maxLength": 2000++ },++ "visibility": {++ "enum": [++ "public",++ "unlisted",++ "private"++ ]++ },++ "item_count": {++ "type": "integer",++ "minimum": 0++ },++ "created_at": {++ "type": "string",++ "description": "ISO 8601 time."++ },++ "updated_at": {++ "type": "string",++ "description": "ISO 8601 time."++ },++ "owner": {++ "type": "object",++ "required": [++ "kind"++ ],++ "properties": {++ "kind": {++ "enum": [++ "user",++ "app",++ "agent",++ "service"++ ]++ },++ "username": {++ "type": [++ "string",++ "null"++ ]++ }++ }++ }++ }++}nnew file mode 100644@@@ -0,0 +1,4 @@++{++ "kind": "stream",++ "id": 1++}nnew file mode 100644@@@ -0,0 +1,4 @@++{++ "kind": "clip",++ "id": 441++}nnew file mode 100644@@@ -0,0 +1,4 @@++{++ "title": "Best of the week",++ "visibility": "public"++}nnew file mode 100644@@@ -0,0 +1,12 @@++{++ "items": [++ {++ "kind": "clip",++ "id": 441++ },++ {++ "kind": "vod",++ "id": 5717++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "item": {++ "kind": "vod",++ "id": 0,++ "position": 0,++ "added_at": "2026-10-12T19:01:00.000Z"++ }++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "item": {++ "kind": "vod",++ "id": 5717,++ "position": 0,++ "added_at": "2026-10-12T19:01:00.000Z"++ }++}nnew file mode 100644@@@ -0,0 +1,11 @@++{++ "playlist": {++ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",++ "title": "Best of the week",++ "description": "",++ "visibility": "public",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z"++ }++}nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "items": [++ {++ "kind": "vod",++ "id": 5717,++ "position": 0,++ "added_at": "2026-10-12T19:01:00.000Z"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,3 @@++{++ "limit": 51++}nnew file mode 100644@@@ -0,0 +1 @@++{}nnew file mode 100644@@@ -0,0 +1,4 @@++{++ "limit": 20,++ "cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNiJ9"++}nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "playlist": {++ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",++ "title": "Best of the week",++ "description": "",++ "visibility": "public",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z"++ },++ "items": [++ {++ "kind": "stream",++ "id": 5717,++ "position": 0,++ "added_at": "2026-10-12T19:01:00.000Z"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,14 @@++{++ "playlists": [++ {++ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",++ "title": "Best of the week",++ "description": "",++ "visibility": "public",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z"++ }++ ],++ "next_cursor": null++}nnew file mode 100644@@@ -0,0 +1,29 @@++{++ "playlist": {++ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",++ "title": "Best of the week",++ "description": "",++ "visibility": "public",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z",++ "owner": {++ "kind": "user",++ "username": "kim"++ }++ },++ "items": [++ {++ "kind": "vod",++ "id": 5717,++ "position": 0,++ "added_at": "2026-10-12T19:01:00.000Z"++ },++ {++ "kind": "clip",++ "id": 441,++ "position": 1,++ "added_at": "2026-10-12T19:01:00.000Z"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,9 @@++{++ "id": "pl_1",++ "title": "Best of the week",++ "description": "",++ "visibility": "public",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z"++}nnew file mode 100644@@@ -0,0 +1,9 @@++{++ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",++ "title": "Best of the week",++ "description": "",++ "visibility": "friends",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z"++}nnew file mode 100644@@@ -0,0 +1,12 @@++{++ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",++ "title": "Best of the week",++ "description": "",++ "visibility": "public",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z",++ "owner": {++ "kind": "app"++ }++}nnew file mode 100644@@@ -0,0 +1,9 @@++{++ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",++ "title": "Best of the week",++ "description": "",++ "visibility": "public",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z"++}nnew file mode 100644@@@ -0,0 +1,13 @@++{++ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",++ "title": "Best of the week",++ "description": "",++ "visibility": "public",++ "item_count": 2,++ "created_at": "2026-10-12T19:00:00.000Z",++ "updated_at": "2026-10-12T19:05:00.000Z",++ "owner": {++ "kind": "user",++ "username": "kim"++ }++}@@@ -78643,6 +78643,395 @@}}}++ },++ "video.playlist": {++ "version": "1.0.0",++ "owner": "media-hub",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist.v1.json",++ "title": "VideoPlaylist",++ "description": "video.playlist@1: one playlist on openvibe.video as the API returns it. `owner` is present on reads of one playlist: a person (kind user, with their username when known) or an app, agent or service (never named).",++ "type": "object",++ "required": [++ "id",++ "title",++ "description",++ "visibility",++ "item_count",++ "created_at",++ "updated_at"++ ],++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^vpl_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "A playlist id (vpl_ + ULID)."++ },++ "title": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "description": {++ "type": "string",++ "maxLength": 2000++ },++ "visibility": {++ "enum": [++ "public",++ "unlisted",++ "private"++ ]++ },++ "item_count": {++ "type": "integer",++ "minimum": 0++ },++ "created_at": {++ "type": "string",++ "description": "ISO 8601 time."++ },++ "updated_at": {++ "type": "string",++ "description": "ISO 8601 time."++ },++ "owner": {++ "type": "object",++ "required": [++ "kind"++ ],++ "properties": {++ "kind": {++ "enum": [++ "user",++ "app",++ "agent",++ "service"++ ]++ },++ "username": {++ "type": [++ "string",++ "null"++ ]++ }++ }++ }++ }++ }++ },++ "video.playlist-read-request": {++ "version": "1.0.0",++ "owner": "media-hub",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist-read-request.v1.json",++ "title": "VideoPlaylistReadRequest",++ "description": "video.playlist-read-request@1: video.playlist.read takes no body. GET /api/v1/video/playlists (the caller's own), GET /api/v1/video/playlists/:id (the owner sees a private one; anyone a public or unlisted one; otherwise 404 playlist.not_found, never 403) and the open GET /api/v1/video/users/:username/playlists, whose query is { limit?, cursor? } (limit 1-50, default 20; cursor is the previous page's next_cursor; 404 user.not_found).",++ "type": "object",++ "properties": {++ "limit": {++ "type": "integer",++ "minimum": 1,++ "maximum": 50++ },++ "cursor": {++ "type": "string",++ "maxLength": 400++ }++ }++ }++ },++ "video.playlist-read-result": {++ "version": "1.0.0",++ "owner": "media-hub",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist-read-result.v1.json",++ "title": "VideoPlaylistReadResult",++ "description": "video.playlist-read-result@1: a list ({ playlists, next_cursor? }) or one playlist with its ordered items ({ playlist, items }).",++ "anyOf": [++ {++ "type": "object",++ "required": [++ "playlists"++ ],++ "properties": {++ "playlists": {++ "type": "array",++ "items": {++ "$ref": "playlist.v1.json"++ }++ },++ "next_cursor": {++ "type": [++ "string",++ "null"++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "playlist",++ "items"++ ],++ "properties": {++ "playlist": {++ "$ref": "playlist.v1.json"++ },++ "items": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ }++ }++ ]++ }++ },++ "video.playlist-manage-request": {++ "version": "1.0.0",++ "owner": "media-hub",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist-manage-request.v1.json",++ "title": "VideoPlaylistManageRequest",++ "description": "video.playlist-manage-request@1: bodies of video.playlist.manage on openvibe.video. POST /api/v1/video/playlists { title, description?, visibility? } creates one (default private; 422 playlist.invalid_title over 120 characters, playlist.invalid_description over 2,000, playlist.invalid_visibility, playlist.limit at 100 per owner). PATCH /api/v1/video/playlists/:id { title?, description?, visibility? }. POST /api/v1/video/playlists/:id/items { kind, id } adds one (409 playlist.item_duplicate; 422 playlist.invalid_kind, playlist.invalid_item, playlist.items_limit at 500). PATCH /api/v1/video/playlists/:id/items { items: [{ kind, id }, ...] } reorders: the full list, each item once (422 playlist.invalid_items). DELETE /api/v1/video/playlists/:id and /items/:kind/:itemId take no body. Another owner's playlist answers 404 playlist.not_found.",++ "anyOf": [++ {++ "type": "object",++ "minProperties": 1,++ "additionalProperties": false,++ "properties": {++ "title": {++ "type": "string",++ "minLength": 1++ },++ "description": {++ "type": "string"++ },++ "visibility": {++ "enum": [++ "public",++ "unlisted",++ "private"++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "anyOf": [++ {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ {++ "type": "string",++ "pattern": "^[1-9][0-9]{0,15}$"++ }++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "items"++ ],++ "properties": {++ "items": {++ "type": "array",++ "maxItems": 500,++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "anyOf": [++ {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ {++ "type": "string",++ "pattern": "^[1-9][0-9]{0,15}$"++ }++ ]++ }++ }++ }++ }++ }++ }++ ]++ }++ },++ "video.playlist-manage-result": {++ "version": "1.0.0",++ "owner": "media-hub",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/video/playlist-manage-result.v1.json",++ "title": "VideoPlaylistManageResult",++ "description": "video.playlist-manage-result@1: { playlist } after a create (201, Location) or an edit, { item } after an add (201), { items } after a reorder; a delete answers 204 with no body.",++ "anyOf": [++ {++ "type": "object",++ "required": [++ "playlist"++ ],++ "properties": {++ "playlist": {++ "$ref": "playlist.v1.json"++ }++ }++ },++ {++ "type": "object",++ "required": [++ "item"++ ],++ "properties": {++ "item": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ },++ {++ "type": "object",++ "required": [++ "items"++ ],++ "properties": {++ "items": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ }++ }++ ]++ }}}}@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Actor API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Billing API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Blog API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Bot API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Chat API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Community API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Coupons API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Deals API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Events API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Food API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Games API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Host API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -113,6 +113,13 @@"operations": 9,"capabilities": 6},++ {++ "service": "media-hub",++ "name": "OpenVibe.MediaHub",++ "origin": "https://openvibe.video",++ "operations": 8,++ "capabilities": 2++ },{"service": "network","name": "OpenVibe.Network",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Inventory API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Live API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"nnew file mode 100644@@@ -0,0 +1,980 @@++{++ "openapi": "3.1.0",++ "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",++ "info": {++ "title": "OpenVibe.MediaHub API",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "license": {++ "name": "MIT",++ "identifier": "MIT"++ }++ },++ "servers": [++ {++ "url": "https://openvibe.video"++ }++ ],++ "paths": {++ "/api/v1/video/playlists": {++ "get": {++ "operationId": "get_api_v1_video_playlists",++ "summary": "Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or cli",++ "description": "**video.playlist.read** (public): Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or clip ids from OpenVibe.Live). A private playlist answers 404 to anyone but its owner. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download, the media hub's) needs this one.",++ "tags": [++ "video.playlist"++ ],++ "x-openvibe-capabilities": [++ "video.playlist.read"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "video-read",++ "security": [++ {++ "openvibeToken": [++ "video.playlist.read"++ ]++ }++ ],++ "x-openvibe-input": {++ "$ref": "#/components/schemas/video.playlist-read-request.v1"++ },++ "parameters": [++ {++ "name": "limit",++ "in": "query",++ "required": false,++ "schema": {++ "type": "integer",++ "minimum": 1,++ "maximum": 50++ }++ },++ {++ "name": "cursor",++ "in": "query",++ "required": false,++ "schema": {++ "type": "string",++ "maxLength": 400++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-read-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ },++ "post": {++ "operationId": "post_api_v1_video_playlists",++ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",++ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",++ "tags": [++ "video.playlist"++ ],++ "x-openvibe-capabilities": [++ "video.playlist.manage"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "video-write",++ "security": [++ {++ "openvibeToken": [++ "video.playlist.manage"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-request.v1"++ }++ }++ }++ },++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },++ "/api/v1/video/playlists/{id}": {++ "delete": {++ "operationId": "delete_api_v1_video_playlists_id",++ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",++ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",++ "tags": [++ "video.playlist"++ ],++ "x-openvibe-capabilities": [++ "video.playlist.manage"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "video-write",++ "security": [++ {++ "openvibeToken": [++ "video.playlist.manage"++ ]++ }++ ],++ "x-openvibe-input": {++ "$ref": "#/components/schemas/video.playlist-manage-request.v1"++ },++ "parameters": [++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ },++ "get": {++ "operationId": "get_api_v1_video_playlists_id",++ "summary": "Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or cli",++ "description": "**video.playlist.read** (public): Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or clip ids from OpenVibe.Live). A private playlist answers 404 to anyone but its owner. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download, the media hub's) needs this one.",++ "tags": [++ "video.playlist"++ ],++ "x-openvibe-capabilities": [++ "video.playlist.read"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "video-read",++ "security": [++ {++ "openvibeToken": [++ "video.playlist.read"++ ]++ }++ ],++ "x-openvibe-input": {++ "$ref": "#/components/schemas/video.playlist-read-request.v1"++ },++ "parameters": [++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "limit",++ "in": "query",++ "required": false,++ "schema": {++ "type": "integer",++ "minimum": 1,++ "maximum": 50++ }++ },++ {++ "name": "cursor",++ "in": "query",++ "required": false,++ "schema": {++ "type": "string",++ "maxLength": 400++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-read-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ },++ "patch": {++ "operationId": "patch_api_v1_video_playlists_id",++ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",++ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",++ "tags": [++ "video.playlist"++ ],++ "x-openvibe-capabilities": [++ "video.playlist.manage"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "video-write",++ "security": [++ {++ "openvibeToken": [++ "video.playlist.manage"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-request.v1"++ }++ }++ }++ },++ "parameters": [++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },++ "/api/v1/video/playlists/{id}/items": {++ "patch": {++ "operationId": "patch_api_v1_video_playlists_id_items",++ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",++ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",++ "tags": [++ "video.playlist"++ ],++ "x-openvibe-capabilities": [++ "video.playlist.manage"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "video-write",++ "security": [++ {++ "openvibeToken": [++ "video.playlist.manage"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-request.v1"++ }++ }++ }++ },++ "parameters": [++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ },++ "post": {++ "operationId": "post_api_v1_video_playlists_id_items",++ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",++ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",++ "tags": [++ "video.playlist"++ ],++ "x-openvibe-capabilities": [++ "video.playlist.manage"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "video-write",++ "security": [++ {++ "openvibeToken": [++ "video.playlist.manage"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-request.v1"++ }++ }++ }++ },++ "parameters": [++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },++ "/api/v1/video/playlists/{id}/items/{kind}/{itemId}": {++ "delete": {++ "operationId": "delete_api_v1_video_playlists_id_items_kind_itemId",++ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",++ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",++ "tags": [++ "video.playlist"++ ],++ "x-openvibe-capabilities": [++ "video.playlist.manage"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "video-write",++ "security": [++ {++ "openvibeToken": [++ "video.playlist.manage"++ ]++ }++ ],++ "x-openvibe-input": {++ "$ref": "#/components/schemas/video.playlist-manage-request.v1"++ },++ "parameters": [++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "kind",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "itemId",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/video.playlist-manage-result.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ }++ },++ "components": {++ "schemas": {++ "errors.problem.v1": {++ "title": "Problem",++ "description": "RFC 9457 problem details (application/problem+json) with a stable OpenVibe error code and trace identifiers. The legacy 'error' string is allowed during migration so existing clients keep working.",++ "type": "object",++ "required": [++ "type",++ "title",++ "status",++ "code"++ ],++ "additionalProperties": true,++ "properties": {++ "type": {++ "type": "string",++ "format": "uri-reference"++ },++ "title": {++ "type": "string",++ "minLength": 1++ },++ "status": {++ "type": "integer",++ "minimum": 400,++ "maximum": 599++ },++ "detail": {++ "type": "string"++ },++ "instance": {++ "type": "string",++ "format": "uri-reference"++ },++ "code": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)*$"++ },++ "request_id": {++ "type": "string"++ },++ "trace_id": {++ "type": "string",++ "pattern": "^[0-9a-f]{32}$"++ },++ "errors": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "message"++ ],++ "properties": {++ "path": {++ "type": "string"++ },++ "message": {++ "type": "string"++ }++ }++ }++ },++ "error": {++ "type": "string",++ "description": "Deprecated compatibility field: same text as title/detail for clients that read {error}."++ }++ }++ },++ "video.playlist-manage-request.v1": {++ "title": "VideoPlaylistManageRequest",++ "description": "video.playlist-manage-request@1: bodies of video.playlist.manage on openvibe.video. POST /api/v1/video/playlists { title, description?, visibility? } creates one (default private; 422 playlist.invalid_title over 120 characters, playlist.invalid_description over 2,000, playlist.invalid_visibility, playlist.limit at 100 per owner). PATCH /api/v1/video/playlists/:id { title?, description?, visibility? }. POST /api/v1/video/playlists/:id/items { kind, id } adds one (409 playlist.item_duplicate; 422 playlist.invalid_kind, playlist.invalid_item, playlist.items_limit at 500). PATCH /api/v1/video/playlists/:id/items { items: [{ kind, id }, ...] } reorders: the full list, each item once (422 playlist.invalid_items). DELETE /api/v1/video/playlists/:id and /items/:kind/:itemId take no body. Another owner's playlist answers 404 playlist.not_found.",++ "anyOf": [++ {++ "type": "object",++ "minProperties": 1,++ "additionalProperties": false,++ "properties": {++ "title": {++ "type": "string",++ "minLength": 1++ },++ "description": {++ "type": "string"++ },++ "visibility": {++ "enum": [++ "public",++ "unlisted",++ "private"++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "anyOf": [++ {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ {++ "type": "string",++ "pattern": "^[1-9][0-9]{0,15}$"++ }++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "items"++ ],++ "properties": {++ "items": {++ "type": "array",++ "maxItems": 500,++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "anyOf": [++ {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ {++ "type": "string",++ "pattern": "^[1-9][0-9]{0,15}$"++ }++ ]++ }++ }++ }++ }++ }++ }++ ]++ },++ "video.playlist-manage-result.v1": {++ "title": "VideoPlaylistManageResult",++ "description": "video.playlist-manage-result@1: { playlist } after a create (201, Location) or an edit, { item } after an add (201), { items } after a reorder; a delete answers 204 with no body.",++ "anyOf": [++ {++ "type": "object",++ "required": [++ "playlist"++ ],++ "properties": {++ "playlist": {++ "$ref": "#/components/schemas/video.playlist.v1"++ }++ }++ },++ {++ "type": "object",++ "required": [++ "item"++ ],++ "properties": {++ "item": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ },++ {++ "type": "object",++ "required": [++ "items"++ ],++ "properties": {++ "items": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ }++ }++ ]++ },++ "video.playlist-read-request.v1": {++ "title": "VideoPlaylistReadRequest",++ "description": "video.playlist-read-request@1: video.playlist.read takes no body. GET /api/v1/video/playlists (the caller's own), GET /api/v1/video/playlists/:id (the owner sees a private one; anyone a public or unlisted one; otherwise 404 playlist.not_found, never 403) and the open GET /api/v1/video/users/:username/playlists, whose query is { limit?, cursor? } (limit 1-50, default 20; cursor is the previous page's next_cursor; 404 user.not_found).",++ "type": "object",++ "properties": {++ "limit": {++ "type": "integer",++ "minimum": 1,++ "maximum": 50++ },++ "cursor": {++ "type": "string",++ "maxLength": 400++ }++ }++ },++ "video.playlist-read-result.v1": {++ "title": "VideoPlaylistReadResult",++ "description": "video.playlist-read-result@1: a list ({ playlists, next_cursor? }) or one playlist with its ordered items ({ playlist, items }).",++ "anyOf": [++ {++ "type": "object",++ "required": [++ "playlists"++ ],++ "properties": {++ "playlists": {++ "type": "array",++ "items": {++ "$ref": "#/components/schemas/video.playlist.v1"++ }++ },++ "next_cursor": {++ "type": [++ "string",++ "null"++ ]++ }++ }++ },++ {++ "type": "object",++ "required": [++ "playlist",++ "items"++ ],++ "properties": {++ "playlist": {++ "$ref": "#/components/schemas/video.playlist.v1"++ },++ "items": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "kind",++ "id",++ "position",++ "added_at"++ ],++ "properties": {++ "kind": {++ "enum": [++ "vod",++ "clip"++ ],++ "description": "An OpenVibe.Live recording (vod) or clip."++ },++ "id": {++ "type": "integer",++ "minimum": 1,++ "description": "The item's OpenVibe.Live id."++ },++ "position": {++ "type": "integer",++ "minimum": 0++ },++ "added_at": {++ "type": "string",++ "description": "ISO 8601 time."++ }++ }++ }++ }++ }++ }++ ]++ },++ "video.playlist.v1": {++ "title": "VideoPlaylist",++ "description": "video.playlist@1: one playlist on openvibe.video as the API returns it. `owner` is present on reads of one playlist: a person (kind user, with their username when known) or an app, agent or service (never named).",++ "type": "object",++ "required": [++ "id",++ "title",++ "description",++ "visibility",++ "item_count",++ "created_at",++ "updated_at"++ ],++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^vpl_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "A playlist id (vpl_ + ULID)."++ },++ "title": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "description": {++ "type": "string",++ "maxLength": 2000++ },++ "visibility": {++ "enum": [++ "public",++ "unlisted",++ "private"++ ]++ },++ "item_count": {++ "type": "integer",++ "minimum": 0++ },++ "created_at": {++ "type": "string",++ "description": "ISO 8601 time."++ },++ "updated_at": {++ "type": "string",++ "description": "ISO 8601 time."++ },++ "owner": {++ "type": "object",++ "required": [++ "kind"++ ],++ "properties": {++ "kind": {++ "enum": [++ "user",++ "app",++ "agent",++ "service"++ ]++ },++ "username": {++ "type": [++ "string",++ "null"++ ]++ }++ }++ }++ }++ }++ },++ "securitySchemes": {++ "openvibeToken": {++ "type": "http",++ "scheme": "bearer",++ "bearerFormat": "JWT",++ "description": "An OpenVibe Network token for this service: a person's token, an app token (client credentials, audience of the service) or a first-party service token. Its `cap` claim must include the capability the operation names."++ }++ }++ }++}@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Media API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Network API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.News API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenRestream API",-- "version": "0.151.0",-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Reviews API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Run API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Search API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Services API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Sources API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Space API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tips API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tools API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Trade API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.VIP API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Watch API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Wiki API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Work API",-- "version": "0.151.0",-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.152.0",++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -173584,3 +173584,140 @@ export interface SpaceDomainVerifiedPayload {*/hostname: string;}++++/** [email protected] (owner: media-hub) */++/**++ * video.playlist@1: one playlist on openvibe.video as the API returns it. `owner` is present on reads of one playlist: a person (kind user, with their username when known) or an app, agent or service (never named).++ */++export interface VideoPlaylist {++ /**++ * A playlist id (vpl_ + ULID).++ */++ id: string;++ title: string;++ description: string;++ visibility: "public" | "unlisted" | "private";++ item_count: number;++ /**++ * ISO 8601 time.++ */++ created_at: string;++ /**++ * ISO 8601 time.++ */++ updated_at: string;++ owner?: {++ kind: "user" | "app" | "agent" | "service";++ username?: string | null;++ };++}++++/** [email protected] (owner: media-hub) */++/**++ * video.playlist-read-request@1: video.playlist.read takes no body. GET /api/v1/video/playlists (the caller's own), GET /api/v1/video/playlists/:id (the owner sees a private one; anyone a public or unlisted one; otherwise 404 playlist.not_found, never 403) and the open GET /api/v1/video/users/:username/playlists, whose query is { limit?, cursor? } (limit 1-50, default 20; cursor is the previous page's next_cursor; 404 user.not_found).++ */++export interface VideoPlaylistReadRequest {++ limit?: number;++ cursor?: string;++}++++/** [email protected] (owner: media-hub) */++/**++ * video.playlist-read-result@1: a list ({ playlists, next_cursor? }) or one playlist with its ordered items ({ playlist, items }).++ */++export type VideoPlaylistReadResult =++ | {++ playlists: VideoPlaylist[];++ next_cursor?: string | null;++ }++ | {++ playlist: VideoPlaylist;++ items: {++ /**++ * An OpenVibe.Live recording (vod) or clip.++ */++ kind: "vod" | "clip";++ /**++ * The item's OpenVibe.Live id.++ */++ id: number;++ position: number;++ /**++ * ISO 8601 time.++ */++ added_at: string;++ }[];++ };++++/** [email protected] (owner: media-hub) */++/**++ * video.playlist-manage-request@1: bodies of video.playlist.manage on openvibe.video. POST /api/v1/video/playlists { title, description?, visibility? } creates one (default private; 422 playlist.invalid_title over 120 characters, playlist.invalid_description over 2,000, playlist.invalid_visibility, playlist.limit at 100 per owner). PATCH /api/v1/video/playlists/:id { title?, description?, visibility? }. POST /api/v1/video/playlists/:id/items { kind, id } adds one (409 playlist.item_duplicate; 422 playlist.invalid_kind, playlist.invalid_item, playlist.items_limit at 500). PATCH /api/v1/video/playlists/:id/items { items: [{ kind, id }, ...] } reorders: the full list, each item once (422 playlist.invalid_items). DELETE /api/v1/video/playlists/:id and /items/:kind/:itemId take no body. Another owner's playlist answers 404 playlist.not_found.++ */++export type VideoPlaylistManageRequest =++ | {++ title?: string;++ description?: string;++ visibility?: "public" | "unlisted" | "private";++ }++ | {++ /**++ * An OpenVibe.Live recording (vod) or clip.++ */++ kind: "vod" | "clip";++ id: number | string;++ }++ | {++ /**++ * @maxItems 500++ */++ items: {++ /**++ * An OpenVibe.Live recording (vod) or clip.++ */++ kind: "vod" | "clip";++ id: number | string;++ }[];++ };++++/** [email protected] (owner: media-hub) */++/**++ * video.playlist-manage-result@1: { playlist } after a create (201, Location) or an edit, { item } after an add (201), { items } after a reorder; a delete answers 204 with no body.++ */++export type VideoPlaylistManageResult =++ | {++ playlist: VideoPlaylist;++ }++ | {++ item: {++ /**++ * An OpenVibe.Live recording (vod) or clip.++ */++ kind: "vod" | "clip";++ /**++ * The item's OpenVibe.Live id.++ */++ id: number;++ position: number;++ /**++ * ISO 8601 time.++ */++ added_at: string;++ };++ }++ | {++ items: {++ /**++ * An OpenVibe.Live recording (vod) or clip.++ */++ kind: "vod" | "clip";++ /**++ * The item's OpenVibe.Live id.++ */++ id: number;++ position: number;++ /**++ * ISO 8601 time.++ */++ added_at: string;++ }[];++ };@@@ -2,10 +2,10 @@"id": "video.playlist.manage","version": "1.0","owner": "media-hub",-- "status": "planned",++ "status": "active","visibility": "public","sensitive": true,-- "description": "PLANNED: create, rename, reorder and delete a playlist on openvibe.video as the acting person (plan T10 D6). Account-only.",++ "description": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.","permissions": ["video:write"],@@@ -14,5 +14,14 @@],"quotaClass": "video-write","events": [],-- "implementedBy": []++ "implementedBy": [++ "POST /api/v1/video/playlists",++ "PATCH /api/v1/video/playlists/:id",++ "DELETE /api/v1/video/playlists/:id",++ "POST /api/v1/video/playlists/:id/items",++ "PATCH /api/v1/video/playlists/:id/items",++ "DELETE /api/v1/video/playlists/:id/items/:kind/:itemId"++ ],++ "inputSchema": "video.playlist-manage-request@1",++ "outputSchema": "video.playlist-manage-result@1"}@@@ -2,9 +2,9 @@"id": "video.playlist.read","version": "1.0","owner": "media-hub",-- "status": "planned",++ "status": "active","visibility": "public",-- "description": "PLANNED: read a playlist and its ordered items on openvibe.video (a new table; playlists do not exist anywhere today, plan T10 D6).",++ "description": "Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or clip ids from OpenVibe.Live). A private playlist answers 404 to anyone but its owner. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download, the media hub's) needs this one.","permissions": ["video:read"],@@@ -13,5 +13,10 @@],"quotaClass": "video-read","events": [],-- "implementedBy": []++ "implementedBy": [++ "GET /api/v1/video/playlists",++ "GET /api/v1/video/playlists/:id"++ ],++ "inputSchema": "video.playlist-read-request@1",++ "outputSchema": "video.playlist-read-result@1"}@@@ -87,7 +87,7 @@"none": "no claims: one process serves the three domains"}},-- "notes": "Port 4990, unit openvibe-media-hub.service, one process for openvibe.download, openvibe.pics and openvibe.video (plan T10 D4, by Host header). v1: openvibe.download is a private drive — account-only uploads streamed into OpenVibe.Media (app media-hub; a plain form up to 256 MB, resumable multipart beyond), private files and folders with per-person limits, share links that expire, need a signed-in downloader and may name accounts (matched by subject), reports that suspend a share for staff, and sandboxed attachment downloads. openvibe.pics and openvibe.video answer with coming pages: their uploads wait for scanning and abuse intake (the video.*/pics.*/download.* capabilities stay planned until an app may call them). Consumes OpenVibe.Network (SSO with PKCE S256 as OAuth client media-hub, JWKS, identity.subject.resolve) and OpenVibe.Media; answers account export and deletion (ADR-033). Since 2026-10-12 the same process serves openvibe.video, OpenVibe.Video v1: public, read-only watch pages for OpenVibe.Live's stream recordings and clips (read from Live's public API, files on OpenVibe.Media), with WebVTT captions from the AI transcript and chapters from the AI moments. video.* stays planned until an app may call it; openvibe.pics stays parked.",++ "notes": "Port 4990, unit openvibe-media-hub.service, one process for openvibe.download, openvibe.pics and openvibe.video (plan T10 D4, by Host header). v1: openvibe.download is a private drive — account-only uploads streamed into OpenVibe.Media (app media-hub; a plain form up to 256 MB, resumable multipart beyond), private files and folders with per-person limits, share links that expire, need a signed-in downloader and may name accounts (matched by subject), reports that suspend a share for staff, and sandboxed attachment downloads. openvibe.pics and openvibe.video answer with coming pages: their uploads wait for scanning and abuse intake (the video.*/pics.*/download.* capabilities stay planned until an app may call them). Consumes OpenVibe.Network (SSO with PKCE S256 as OAuth client media-hub, JWKS, identity.subject.resolve) and OpenVibe.Media; answers account export and deletion (ADR-033). Since 2026-10-12 the same process serves openvibe.video, OpenVibe.Video v1: public, read-only watch pages for OpenVibe.Live's stream recordings and clips (read from Live's public API, files on OpenVibe.Media), with WebVTT captions from the AI transcript and chapters from the AI moments. Its playlists (MediaHub#31) have an API for people and apps since 0.152.0 (video.playlist.read, video.playlist.manage; MediaHub#33); video.vod.read stays planned (the watch pages are public HTML). openvibe.pics stays parked.","health": "/api/health","ready": "/api/ready","internalOrigin": "http://127.0.0.1:4990",@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.151.0",++ "version": "0.152.0","description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.","main": "index.js","types": "generated/typescript/index.d.ts",
@@ -4,6 +4,16 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
@@ -4,6 +4,16 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
the notes were in the tag and commit messages (`git tag -n1`).
+## 0.152.0 — 2026-10-12
+
+- **`video.playlist.read` and `video.playlist.manage` are active.** openvibe.video's playlist API (MediaHub#33) takes a
+ person's Network token, an app/agent/service token with one of these, or no token for a public or unlisted playlist
+ by id and a person's public list (`GET /api/v1/video/users/:username/playlists`). An app owns playlists under its own
+ requester and project and never touches a person's.
+- New schemas (owner media-hub): `video.playlist@1`, `video.playlist-read-request@1`, `video.playlist-read-result@1`,
+ `video.playlist-manage-request@1` and `video.playlist-manage-result@1`, with fixtures; the two capabilities name them.
+ Additive only (compat vs 0.151.0: no breaking changes).
+
## 0.151.0 — 2026-10-12
## 0.151.0 — 2026-10-12
- The media-hub site is named **Video** (tagline "Past streams, clips and your drive"): its public origin is openvibe.video,
- The media-hub site is named **Video** (tagline "Past streams, clips and your drive"): its public origin is openvibe.video,
@@ -7013,6 +7013,51 @@
@@ -7013,6 +7013,51 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active",
"status": "active",
"adr": "ADR-004"
"adr": "ADR-004"
+ },
+ {
+ "id": "video.playlist",
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "schema": "video/playlist.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "video.playlist-read-request",
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "schema": "video/playlist-read-request.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "video.playlist-read-result",
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "schema": "video/playlist-read-result.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "video.playlist-manage-request",
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "schema": "video/playlist-manage-request.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "video.playlist-manage-result",
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "schema": "video/playlist-manage-result.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
}
}
]
]
}
}
new file mode 100644
new file mode 100644
@@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist-manage-request.v1.json",
+ "title": "VideoPlaylistManageRequest",
+ "description": "video.playlist-manage-request@1: bodies of video.playlist.manage on openvibe.video. POST /api/v1/video/playlists { title, description?, visibility? } creates one (default private; 422 playlist.invalid_title over 120 characters, playlist.invalid_description over 2,000, playlist.invalid_visibility, playlist.limit at 100 per owner). PATCH /api/v1/video/playlists/:id { title?, description?, visibility? }. POST /api/v1/video/playlists/:id/items { kind, id } adds one (409 playlist.item_duplicate; 422 playlist.invalid_kind, playlist.invalid_item, playlist.items_limit at 500). PATCH /api/v1/video/playlists/:id/items { items: [{ kind, id }, ...] } reorders: the full list, each item once (422 playlist.invalid_items). DELETE /api/v1/video/playlists/:id and /items/:kind/:itemId take no body. Another owner's playlist answers 404 playlist.not_found.",
+ "anyOf": [
+ {
+ "type": "object",
+ "minProperties": 1,
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "visibility": {
+ "enum": [
+ "public",
+ "unlisted",
+ "private"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ {
+ "type": "string",
+ "pattern": "^[1-9][0-9]{0,15}$"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "items": {
+ "type": "array",
+ "maxItems": 500,
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ {
+ "type": "string",
+ "pattern": "^[1-9][0-9]{0,15}$"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,100 @@
@@ -0,0 +1,100 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist-manage-result.v1.json",
+ "title": "VideoPlaylistManageResult",
+ "description": "video.playlist-manage-result@1: { playlist } after a create (201, Location) or an edit, { item } after an add (201), { items } after a reorder; a delete answers 204 with no body.",
+ "anyOf": [
+ {
+ "type": "object",
+ "required": [
+ "playlist"
+ ],
+ "properties": {
+ "playlist": {
+ "$ref": "playlist.v1.json"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "item"
+ ],
+ "properties": {
+ "item": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist-read-request.v1.json",
+ "title": "VideoPlaylistReadRequest",
+ "description": "video.playlist-read-request@1: video.playlist.read takes no body. GET /api/v1/video/playlists (the caller's own), GET /api/v1/video/playlists/:id (the owner sees a private one; anyone a public or unlisted one; otherwise 404 playlist.not_found, never 403) and the open GET /api/v1/video/users/:username/playlists, whose query is { limit?, cursor? } (limit 1-50, default 20; cursor is the previous page's next_cursor; 404 user.not_found).",
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 50
+ },
+ "cursor": {
+ "type": "string",
+ "maxLength": 400
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist-read-result.v1.json",
+ "title": "VideoPlaylistReadResult",
+ "description": "video.playlist-read-result@1: a list ({ playlists, next_cursor? }) or one playlist with its ordered items ({ playlist, items }).",
+ "anyOf": [
+ {
+ "type": "object",
+ "required": [
+ "playlists"
+ ],
+ "properties": {
+ "playlists": {
+ "type": "array",
+ "items": {
+ "$ref": "playlist.v1.json"
+ }
+ },
+ "next_cursor": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "playlist",
+ "items"
+ ],
+ "properties": {
+ "playlist": {
+ "$ref": "playlist.v1.json"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist.v1.json",
+ "title": "VideoPlaylist",
+ "description": "video.playlist@1: one playlist on openvibe.video as the API returns it. `owner` is present on reads of one playlist: a person (kind user, with their username when known) or an app, agent or service (never named).",
+ "type": "object",
+ "required": [
+ "id",
+ "title",
+ "description",
+ "visibility",
+ "item_count",
+ "created_at",
+ "updated_at"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^vpl_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "A playlist id (vpl_ + ULID)."
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 2000
+ },
+ "visibility": {
+ "enum": [
+ "public",
+ "unlisted",
+ "private"
+ ]
+ },
+ "item_count": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "created_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ },
+ "updated_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ },
+ "owner": {
+ "type": "object",
+ "required": [
+ "kind"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "user",
+ "app",
+ "agent",
+ "service"
+ ]
+ },
+ "username": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ }
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
+{
+ "kind": "stream",
+ "id": 1
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
+{
+ "kind": "clip",
+ "id": 441
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
+{
+ "title": "Best of the week",
+ "visibility": "public"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
+{
+ "items": [
+ {
+ "kind": "clip",
+ "id": 441
+ },
+ {
+ "kind": "vod",
+ "id": 5717
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "item": {
+ "kind": "vod",
+ "id": 0,
+ "position": 0,
+ "added_at": "2026-10-12T19:01:00.000Z"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "item": {
+ "kind": "vod",
+ "id": 5717,
+ "position": 0,
+ "added_at": "2026-10-12T19:01:00.000Z"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
+{
+ "playlist": {
+ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "public",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "items": [
+ {
+ "kind": "vod",
+ "id": 5717,
+ "position": 0,
+ "added_at": "2026-10-12T19:01:00.000Z"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
+{
+ "limit": 51
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{}
new file mode 100644
new file mode 100644
@@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
+{
+ "limit": 20,
+ "cursor": "eyJ1cGRhdGVkX2F0IjoiMjAyNiJ9"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "playlist": {
+ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "public",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z"
+ },
+ "items": [
+ {
+ "kind": "stream",
+ "id": 5717,
+ "position": 0,
+ "added_at": "2026-10-12T19:01:00.000Z"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
+{
+ "playlists": [
+ {
+ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "public",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z"
+ }
+ ],
+ "next_cursor": null
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
+{
+ "playlist": {
+ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "public",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z",
+ "owner": {
+ "kind": "user",
+ "username": "kim"
+ }
+ },
+ "items": [
+ {
+ "kind": "vod",
+ "id": 5717,
+ "position": 0,
+ "added_at": "2026-10-12T19:01:00.000Z"
+ },
+ {
+ "kind": "clip",
+ "id": 441,
+ "position": 1,
+ "added_at": "2026-10-12T19:01:00.000Z"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
+{
+ "id": "pl_1",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "public",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
+{
+ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "friends",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
+{
+ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "public",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z",
+ "owner": {
+ "kind": "app"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
+{
+ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "public",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
+{
+ "id": "vpl_01K7A1B2C3D4E5F6G7H8J9K0MN",
+ "title": "Best of the week",
+ "description": "",
+ "visibility": "public",
+ "item_count": 2,
+ "created_at": "2026-10-12T19:00:00.000Z",
+ "updated_at": "2026-10-12T19:05:00.000Z",
+ "owner": {
+ "kind": "user",
+ "username": "kim"
+ }
+}
@@ -78643,6 +78643,395 @@
@@ -78643,6 +78643,395 @@
}
}
}
}
}
}
+ },
+ "video.playlist": {
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist.v1.json",
+ "title": "VideoPlaylist",
+ "description": "video.playlist@1: one playlist on openvibe.video as the API returns it. `owner` is present on reads of one playlist: a person (kind user, with their username when known) or an app, agent or service (never named).",
+ "type": "object",
+ "required": [
+ "id",
+ "title",
+ "description",
+ "visibility",
+ "item_count",
+ "created_at",
+ "updated_at"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^vpl_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "A playlist id (vpl_ + ULID)."
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 2000
+ },
+ "visibility": {
+ "enum": [
+ "public",
+ "unlisted",
+ "private"
+ ]
+ },
+ "item_count": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "created_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ },
+ "updated_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ },
+ "owner": {
+ "type": "object",
+ "required": [
+ "kind"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "user",
+ "app",
+ "agent",
+ "service"
+ ]
+ },
+ "username": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "video.playlist-read-request": {
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist-read-request.v1.json",
+ "title": "VideoPlaylistReadRequest",
+ "description": "video.playlist-read-request@1: video.playlist.read takes no body. GET /api/v1/video/playlists (the caller's own), GET /api/v1/video/playlists/:id (the owner sees a private one; anyone a public or unlisted one; otherwise 404 playlist.not_found, never 403) and the open GET /api/v1/video/users/:username/playlists, whose query is { limit?, cursor? } (limit 1-50, default 20; cursor is the previous page's next_cursor; 404 user.not_found).",
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 50
+ },
+ "cursor": {
+ "type": "string",
+ "maxLength": 400
+ }
+ }
+ }
+ },
+ "video.playlist-read-result": {
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist-read-result.v1.json",
+ "title": "VideoPlaylistReadResult",
+ "description": "video.playlist-read-result@1: a list ({ playlists, next_cursor? }) or one playlist with its ordered items ({ playlist, items }).",
+ "anyOf": [
+ {
+ "type": "object",
+ "required": [
+ "playlists"
+ ],
+ "properties": {
+ "playlists": {
+ "type": "array",
+ "items": {
+ "$ref": "playlist.v1.json"
+ }
+ },
+ "next_cursor": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "playlist",
+ "items"
+ ],
+ "properties": {
+ "playlist": {
+ "$ref": "playlist.v1.json"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "video.playlist-manage-request": {
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist-manage-request.v1.json",
+ "title": "VideoPlaylistManageRequest",
+ "description": "video.playlist-manage-request@1: bodies of video.playlist.manage on openvibe.video. POST /api/v1/video/playlists { title, description?, visibility? } creates one (default private; 422 playlist.invalid_title over 120 characters, playlist.invalid_description over 2,000, playlist.invalid_visibility, playlist.limit at 100 per owner). PATCH /api/v1/video/playlists/:id { title?, description?, visibility? }. POST /api/v1/video/playlists/:id/items { kind, id } adds one (409 playlist.item_duplicate; 422 playlist.invalid_kind, playlist.invalid_item, playlist.items_limit at 500). PATCH /api/v1/video/playlists/:id/items { items: [{ kind, id }, ...] } reorders: the full list, each item once (422 playlist.invalid_items). DELETE /api/v1/video/playlists/:id and /items/:kind/:itemId take no body. Another owner's playlist answers 404 playlist.not_found.",
+ "anyOf": [
+ {
+ "type": "object",
+ "minProperties": 1,
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "visibility": {
+ "enum": [
+ "public",
+ "unlisted",
+ "private"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ {
+ "type": "string",
+ "pattern": "^[1-9][0-9]{0,15}$"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "items": {
+ "type": "array",
+ "maxItems": 500,
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ {
+ "type": "string",
+ "pattern": "^[1-9][0-9]{0,15}$"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ },
+ "video.playlist-manage-result": {
+ "version": "1.0.0",
+ "owner": "media-hub",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/video/playlist-manage-result.v1.json",
+ "title": "VideoPlaylistManageResult",
+ "description": "video.playlist-manage-result@1: { playlist } after a create (201, Location) or an edit, { item } after an add (201), { items } after a reorder; a delete answers 204 with no body.",
+ "anyOf": [
+ {
+ "type": "object",
+ "required": [
+ "playlist"
+ ],
+ "properties": {
+ "playlist": {
+ "$ref": "playlist.v1.json"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "item"
+ ],
+ "properties": {
+ "item": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
}
}
}
}
}
}
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Actor API",
"title": "OpenVibe.Actor API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.AI API",
"title": "OpenVibe.AI API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Billing API",
"title": "OpenVibe.Billing API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Blog API",
"title": "OpenVibe.Blog API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bot API",
"title": "OpenVibe.Bot API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Chat API",
"title": "OpenVibe.Chat API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Community API",
"title": "OpenVibe.Community API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Coupons API",
"title": "OpenVibe.Coupons API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Deals API",
"title": "OpenVibe.Deals API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Events API",
"title": "OpenVibe.Events API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Food API",
"title": "OpenVibe.Food API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Games API",
"title": "OpenVibe.Games API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Host API",
"title": "OpenVibe.Host API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -113,6 +113,13 @@
@@ -113,6 +113,13 @@
"operations": 9,
"operations": 9,
"capabilities": 6
"capabilities": 6
},
},
+ {
+ "service": "media-hub",
+ "name": "OpenVibe.MediaHub",
+ "origin": "https://openvibe.video",
+ "operations": 8,
+ "capabilities": 2
+ },
{
{
"service": "network",
"service": "network",
"name": "OpenVibe.Network",
"name": "OpenVibe.Network",
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Inventory API",
"title": "OpenVibe.Inventory API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Live API",
"title": "OpenVibe.Live API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
new file mode 100644
new file mode 100644
@@ -0,0 +1,980 @@
@@ -0,0 +1,980 @@
+{
+ "openapi": "3.1.0",
+ "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
+ "info": {
+ "title": "OpenVibe.MediaHub API",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "license": {
+ "name": "MIT",
+ "identifier": "MIT"
+ }
+ },
+ "servers": [
+ {
+ "url": "https://openvibe.video"
+ }
+ ],
+ "paths": {
+ "/api/v1/video/playlists": {
+ "get": {
+ "operationId": "get_api_v1_video_playlists",
+ "summary": "Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or cli",
+ "description": "**video.playlist.read** (public): Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or clip ids from OpenVibe.Live). A private playlist answers 404 to anyone but its owner. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download, the media hub's) needs this one.",
+ "tags": [
+ "video.playlist"
+ ],
+ "x-openvibe-capabilities": [
+ "video.playlist.read"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "video-read",
+ "security": [
+ {
+ "openvibeToken": [
+ "video.playlist.read"
+ ]
+ }
+ ],
+ "x-openvibe-input": {
+ "$ref": "#/components/schemas/video.playlist-read-request.v1"
+ },
+ "parameters": [
+ {
+ "name": "limit",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 50
+ }
+ },
+ {
+ "name": "cursor",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "maxLength": 400
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-read-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "post_api_v1_video_playlists",
+ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",
+ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",
+ "tags": [
+ "video.playlist"
+ ],
+ "x-openvibe-capabilities": [
+ "video.playlist.manage"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "video-write",
+ "security": [
+ {
+ "openvibeToken": [
+ "video.playlist.manage"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-request.v1"
+ }
+ }
+ }
+ },
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/v1/video/playlists/{id}": {
+ "delete": {
+ "operationId": "delete_api_v1_video_playlists_id",
+ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",
+ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",
+ "tags": [
+ "video.playlist"
+ ],
+ "x-openvibe-capabilities": [
+ "video.playlist.manage"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "video-write",
+ "security": [
+ {
+ "openvibeToken": [
+ "video.playlist.manage"
+ ]
+ }
+ ],
+ "x-openvibe-input": {
+ "$ref": "#/components/schemas/video.playlist-manage-request.v1"
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "get": {
+ "operationId": "get_api_v1_video_playlists_id",
+ "summary": "Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or cli",
+ "description": "**video.playlist.read** (public): Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or clip ids from OpenVibe.Live). A private playlist answers 404 to anyone but its owner. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download, the media hub's) needs this one.",
+ "tags": [
+ "video.playlist"
+ ],
+ "x-openvibe-capabilities": [
+ "video.playlist.read"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "video-read",
+ "security": [
+ {
+ "openvibeToken": [
+ "video.playlist.read"
+ ]
+ }
+ ],
+ "x-openvibe-input": {
+ "$ref": "#/components/schemas/video.playlist-read-request.v1"
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 50
+ }
+ },
+ {
+ "name": "cursor",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "maxLength": 400
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-read-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "patch": {
+ "operationId": "patch_api_v1_video_playlists_id",
+ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",
+ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",
+ "tags": [
+ "video.playlist"
+ ],
+ "x-openvibe-capabilities": [
+ "video.playlist.manage"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "video-write",
+ "security": [
+ {
+ "openvibeToken": [
+ "video.playlist.manage"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-request.v1"
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/v1/video/playlists/{id}/items": {
+ "patch": {
+ "operationId": "patch_api_v1_video_playlists_id_items",
+ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",
+ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",
+ "tags": [
+ "video.playlist"
+ ],
+ "x-openvibe-capabilities": [
+ "video.playlist.manage"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "video-write",
+ "security": [
+ {
+ "openvibeToken": [
+ "video.playlist.manage"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-request.v1"
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "post_api_v1_video_playlists_id_items",
+ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",
+ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",
+ "tags": [
+ "video.playlist"
+ ],
+ "x-openvibe-capabilities": [
+ "video.playlist.manage"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "video-write",
+ "security": [
+ {
+ "openvibeToken": [
+ "video.playlist.manage"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-request.v1"
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/v1/video/playlists/{id}/items/{kind}/{itemId}": {
+ "delete": {
+ "operationId": "delete_api_v1_video_playlists_id_items_kind_itemId",
+ "summary": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns.",
+ "description": "**video.playlist.manage** (public): Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",
+ "tags": [
+ "video.playlist"
+ ],
+ "x-openvibe-capabilities": [
+ "video.playlist.manage"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "video-write",
+ "security": [
+ {
+ "openvibeToken": [
+ "video.playlist.manage"
+ ]
+ }
+ ],
+ "x-openvibe-input": {
+ "$ref": "#/components/schemas/video.playlist-manage-request.v1"
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "kind",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "itemId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/video.playlist-manage-result.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "errors.problem.v1": {
+ "title": "Problem",
+ "description": "RFC 9457 problem details (application/problem+json) with a stable OpenVibe error code and trace identifiers. The legacy 'error' string is allowed during migration so existing clients keep working.",
+ "type": "object",
+ "required": [
+ "type",
+ "title",
+ "status",
+ "code"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "type": {
+ "type": "string",
+ "format": "uri-reference"
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "status": {
+ "type": "integer",
+ "minimum": 400,
+ "maximum": 599
+ },
+ "detail": {
+ "type": "string"
+ },
+ "instance": {
+ "type": "string",
+ "format": "uri-reference"
+ },
+ "code": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)*$"
+ },
+ "request_id": {
+ "type": "string"
+ },
+ "trace_id": {
+ "type": "string",
+ "pattern": "^[0-9a-f]{32}$"
+ },
+ "errors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "message"
+ ],
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "error": {
+ "type": "string",
+ "description": "Deprecated compatibility field: same text as title/detail for clients that read {error}."
+ }
+ }
+ },
+ "video.playlist-manage-request.v1": {
+ "title": "VideoPlaylistManageRequest",
+ "description": "video.playlist-manage-request@1: bodies of video.playlist.manage on openvibe.video. POST /api/v1/video/playlists { title, description?, visibility? } creates one (default private; 422 playlist.invalid_title over 120 characters, playlist.invalid_description over 2,000, playlist.invalid_visibility, playlist.limit at 100 per owner). PATCH /api/v1/video/playlists/:id { title?, description?, visibility? }. POST /api/v1/video/playlists/:id/items { kind, id } adds one (409 playlist.item_duplicate; 422 playlist.invalid_kind, playlist.invalid_item, playlist.items_limit at 500). PATCH /api/v1/video/playlists/:id/items { items: [{ kind, id }, ...] } reorders: the full list, each item once (422 playlist.invalid_items). DELETE /api/v1/video/playlists/:id and /items/:kind/:itemId take no body. Another owner's playlist answers 404 playlist.not_found.",
+ "anyOf": [
+ {
+ "type": "object",
+ "minProperties": 1,
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "visibility": {
+ "enum": [
+ "public",
+ "unlisted",
+ "private"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ {
+ "type": "string",
+ "pattern": "^[1-9][0-9]{0,15}$"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "items": {
+ "type": "array",
+ "maxItems": 500,
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ {
+ "type": "string",
+ "pattern": "^[1-9][0-9]{0,15}$"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ "video.playlist-manage-result.v1": {
+ "title": "VideoPlaylistManageResult",
+ "description": "video.playlist-manage-result@1: { playlist } after a create (201, Location) or an edit, { item } after an add (201), { items } after a reorder; a delete answers 204 with no body.",
+ "anyOf": [
+ {
+ "type": "object",
+ "required": [
+ "playlist"
+ ],
+ "properties": {
+ "playlist": {
+ "$ref": "#/components/schemas/video.playlist.v1"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "item"
+ ],
+ "properties": {
+ "item": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "items"
+ ],
+ "properties": {
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ "video.playlist-read-request.v1": {
+ "title": "VideoPlaylistReadRequest",
+ "description": "video.playlist-read-request@1: video.playlist.read takes no body. GET /api/v1/video/playlists (the caller's own), GET /api/v1/video/playlists/:id (the owner sees a private one; anyone a public or unlisted one; otherwise 404 playlist.not_found, never 403) and the open GET /api/v1/video/users/:username/playlists, whose query is { limit?, cursor? } (limit 1-50, default 20; cursor is the previous page's next_cursor; 404 user.not_found).",
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 50
+ },
+ "cursor": {
+ "type": "string",
+ "maxLength": 400
+ }
+ }
+ },
+ "video.playlist-read-result.v1": {
+ "title": "VideoPlaylistReadResult",
+ "description": "video.playlist-read-result@1: a list ({ playlists, next_cursor? }) or one playlist with its ordered items ({ playlist, items }).",
+ "anyOf": [
+ {
+ "type": "object",
+ "required": [
+ "playlists"
+ ],
+ "properties": {
+ "playlists": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/video.playlist.v1"
+ }
+ },
+ "next_cursor": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": [
+ "playlist",
+ "items"
+ ],
+ "properties": {
+ "playlist": {
+ "$ref": "#/components/schemas/video.playlist.v1"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "kind",
+ "id",
+ "position",
+ "added_at"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "vod",
+ "clip"
+ ],
+ "description": "An OpenVibe.Live recording (vod) or clip."
+ },
+ "id": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The item's OpenVibe.Live id."
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "added_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ "video.playlist.v1": {
+ "title": "VideoPlaylist",
+ "description": "video.playlist@1: one playlist on openvibe.video as the API returns it. `owner` is present on reads of one playlist: a person (kind user, with their username when known) or an app, agent or service (never named).",
+ "type": "object",
+ "required": [
+ "id",
+ "title",
+ "description",
+ "visibility",
+ "item_count",
+ "created_at",
+ "updated_at"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^vpl_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "A playlist id (vpl_ + ULID)."
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 2000
+ },
+ "visibility": {
+ "enum": [
+ "public",
+ "unlisted",
+ "private"
+ ]
+ },
+ "item_count": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "created_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ },
+ "updated_at": {
+ "type": "string",
+ "description": "ISO 8601 time."
+ },
+ "owner": {
+ "type": "object",
+ "required": [
+ "kind"
+ ],
+ "properties": {
+ "kind": {
+ "enum": [
+ "user",
+ "app",
+ "agent",
+ "service"
+ ]
+ },
+ "username": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "securitySchemes": {
+ "openvibeToken": {
+ "type": "http",
+ "scheme": "bearer",
+ "bearerFormat": "JWT",
+ "description": "An OpenVibe Network token for this service: a person's token, an app token (client credentials, audience of the service) or a first-party service token. Its `cap` claim must include the capability the operation names."
+ }
+ }
+ }
+}
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Media API",
"title": "OpenVibe.Media API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Network API",
"title": "OpenVibe.Network API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.News API",
"title": "OpenVibe.News API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenRestream API",
"title": "OpenRestream API",
- "version": "0.151.0",
- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Reviews API",
"title": "OpenVibe.Reviews API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Run API",
"title": "OpenVibe.Run API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Search API",
"title": "OpenVibe.Search API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Services API",
"title": "OpenVibe.Services API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Sources API",
"title": "OpenVibe.Sources API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Space API",
"title": "OpenVibe.Space API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tips API",
"title": "OpenVibe.Tips API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tools API",
"title": "OpenVibe.Tools API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Trade API",
"title": "OpenVibe.Trade API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.VIP API",
"title": "OpenVibe.VIP API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Watch API",
"title": "OpenVibe.Watch API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Wiki API",
"title": "OpenVibe.Wiki API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Work API",
"title": "OpenVibe.Work API",
- "version": "0.151.0",
- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.151.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.152.0",
+ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.152.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -173584,3 +173584,140 @@ export interface SpaceDomainVerifiedPayload {
@@ -173584,3 +173584,140 @@ export interface SpaceDomainVerifiedPayload {
*/
*/
hostname: string;
hostname: string;
}
}
+
+/** [email protected] (owner: media-hub) */
+/**
+ * video.playlist@1: one playlist on openvibe.video as the API returns it. `owner` is present on reads of one playlist: a person (kind user, with their username when known) or an app, agent or service (never named).
+ */
+export interface VideoPlaylist {
+ /**
+ * A playlist id (vpl_ + ULID).
+ */
+ id: string;
+ title: string;
+ description: string;
+ visibility: "public" | "unlisted" | "private";
+ item_count: number;
+ /**
+ * ISO 8601 time.
+ */
+ created_at: string;
+ /**
+ * ISO 8601 time.
+ */
+ updated_at: string;
+ owner?: {
+ kind: "user" | "app" | "agent" | "service";
+ username?: string | null;
+ };
+}
+
+/** [email protected] (owner: media-hub) */
+/**
+ * video.playlist-read-request@1: video.playlist.read takes no body. GET /api/v1/video/playlists (the caller's own), GET /api/v1/video/playlists/:id (the owner sees a private one; anyone a public or unlisted one; otherwise 404 playlist.not_found, never 403) and the open GET /api/v1/video/users/:username/playlists, whose query is { limit?, cursor? } (limit 1-50, default 20; cursor is the previous page's next_cursor; 404 user.not_found).
+ */
+export interface VideoPlaylistReadRequest {
+ limit?: number;
+ cursor?: string;
+}
+
+/** [email protected] (owner: media-hub) */
+/**
+ * video.playlist-read-result@1: a list ({ playlists, next_cursor? }) or one playlist with its ordered items ({ playlist, items }).
+ */
+export type VideoPlaylistReadResult =
+ | {
+ playlists: VideoPlaylist[];
+ next_cursor?: string | null;
+ }
+ | {
+ playlist: VideoPlaylist;
+ items: {
+ /**
+ * An OpenVibe.Live recording (vod) or clip.
+ */
+ kind: "vod" | "clip";
+ /**
+ * The item's OpenVibe.Live id.
+ */
+ id: number;
+ position: number;
+ /**
+ * ISO 8601 time.
+ */
+ added_at: string;
+ }[];
+ };
+
+/** [email protected] (owner: media-hub) */
+/**
+ * video.playlist-manage-request@1: bodies of video.playlist.manage on openvibe.video. POST /api/v1/video/playlists { title, description?, visibility? } creates one (default private; 422 playlist.invalid_title over 120 characters, playlist.invalid_description over 2,000, playlist.invalid_visibility, playlist.limit at 100 per owner). PATCH /api/v1/video/playlists/:id { title?, description?, visibility? }. POST /api/v1/video/playlists/:id/items { kind, id } adds one (409 playlist.item_duplicate; 422 playlist.invalid_kind, playlist.invalid_item, playlist.items_limit at 500). PATCH /api/v1/video/playlists/:id/items { items: [{ kind, id }, ...] } reorders: the full list, each item once (422 playlist.invalid_items). DELETE /api/v1/video/playlists/:id and /items/:kind/:itemId take no body. Another owner's playlist answers 404 playlist.not_found.
+ */
+export type VideoPlaylistManageRequest =
+ | {
+ title?: string;
+ description?: string;
+ visibility?: "public" | "unlisted" | "private";
+ }
+ | {
+ /**
+ * An OpenVibe.Live recording (vod) or clip.
+ */
+ kind: "vod" | "clip";
+ id: number | string;
+ }
+ | {
+ /**
+ * @maxItems 500
+ */
+ items: {
+ /**
+ * An OpenVibe.Live recording (vod) or clip.
+ */
+ kind: "vod" | "clip";
+ id: number | string;
+ }[];
+ };
+
+/** [email protected] (owner: media-hub) */
+/**
+ * video.playlist-manage-result@1: { playlist } after a create (201, Location) or an edit, { item } after an add (201), { items } after a reorder; a delete answers 204 with no body.
+ */
+export type VideoPlaylistManageResult =
+ | {
+ playlist: VideoPlaylist;
+ }
+ | {
+ item: {
+ /**
+ * An OpenVibe.Live recording (vod) or clip.
+ */
+ kind: "vod" | "clip";
+ /**
+ * The item's OpenVibe.Live id.
+ */
+ id: number;
+ position: number;
+ /**
+ * ISO 8601 time.
+ */
+ added_at: string;
+ };
+ }
+ | {
+ items: {
+ /**
+ * An OpenVibe.Live recording (vod) or clip.
+ */
+ kind: "vod" | "clip";
+ /**
+ * The item's OpenVibe.Live id.
+ */
+ id: number;
+ position: number;
+ /**
+ * ISO 8601 time.
+ */
+ added_at: string;
+ }[];
+ };
@@ -2,10 +2,10 @@
@@ -2,10 +2,10 @@
"id": "video.playlist.manage",
"id": "video.playlist.manage",
"version": "1.0",
"version": "1.0",
"owner": "media-hub",
"owner": "media-hub",
- "status": "planned",
+ "status": "active",
"visibility": "public",
"visibility": "public",
"sensitive": true,
"sensitive": true,
- "description": "PLANNED: create, rename, reorder and delete a playlist on openvibe.video as the acting person (plan T10 D6). Account-only.",
+ "description": "Create, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.",
"permissions": [
"permissions": [
"video:write"
"video:write"
],
],
@@ -14,5 +14,14 @@
@@ -14,5 +14,14 @@
],
],
"quotaClass": "video-write",
"quotaClass": "video-write",
"events": [],
"events": [],
- "implementedBy": []
+ "implementedBy": [
+ "POST /api/v1/video/playlists",
+ "PATCH /api/v1/video/playlists/:id",
+ "DELETE /api/v1/video/playlists/:id",
+ "POST /api/v1/video/playlists/:id/items",
+ "PATCH /api/v1/video/playlists/:id/items",
+ "DELETE /api/v1/video/playlists/:id/items/:kind/:itemId"
+ ],
+ "inputSchema": "video.playlist-manage-request@1",
+ "outputSchema": "video.playlist-manage-result@1"
}
}
@@ -2,9 +2,9 @@
@@ -2,9 +2,9 @@
"id": "video.playlist.read",
"id": "video.playlist.read",
"version": "1.0",
"version": "1.0",
"owner": "media-hub",
"owner": "media-hub",
- "status": "planned",
+ "status": "active",
"visibility": "public",
"visibility": "public",
- "description": "PLANNED: read a playlist and its ordered items on openvibe.video (a new table; playlists do not exist anywhere today, plan T10 D6).",
+ "description": "Read playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or clip ids from OpenVibe.Live). A private playlist answers 404 to anyone but its owner. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download, the media hub's) needs this one.",
"permissions": [
"permissions": [
"video:read"
"video:read"
],
],
@@ -13,5 +13,10 @@
@@ -13,5 +13,10 @@
],
],
"quotaClass": "video-read",
"quotaClass": "video-read",
"events": [],
"events": [],
- "implementedBy": []
+ "implementedBy": [
+ "GET /api/v1/video/playlists",
+ "GET /api/v1/video/playlists/:id"
+ ],
+ "inputSchema": "video.playlist-read-request@1",
+ "outputSchema": "video.playlist-read-result@1"
}
}
@@ -87,7 +87,7 @@
@@ -87,7 +87,7 @@
"none": "no claims: one process serves the three domains"
"none": "no claims: one process serves the three domains"
}
}
},
},
- "notes": "Port 4990, unit openvibe-media-hub.service, one process for openvibe.download, openvibe.pics and openvibe.video (plan T10 D4, by Host header). v1: openvibe.download is a private drive — account-only uploads streamed into OpenVibe.Media (app media-hub; a plain form up to 256 MB, resumable multipart beyond), private files and folders with per-person limits, share links that expire, need a signed-in downloader and may name accounts (matched by subject), reports that suspend a share for staff, and sandboxed attachment downloads. openvibe.pics and openvibe.video answer with coming pages: their uploads wait for scanning and abuse intake (the video.*/pics.*/download.* capabilities stay planned until an app may call them). Consumes OpenVibe.Network (SSO with PKCE S256 as OAuth client media-hub, JWKS, identity.subject.resolve) and OpenVibe.Media; answers account export and deletion (ADR-033). Since 2026-10-12 the same process serves openvibe.video, OpenVibe.Video v1: public, read-only watch pages for OpenVibe.Live's stream recordings and clips (read from Live's public API, files on OpenVibe.Media), with WebVTT captions from the AI transcript and chapters from the AI moments. video.* stays planned until an app may call it; openvibe.pics stays parked.",
+ "notes": "Port 4990, unit openvibe-media-hub.service, one process for openvibe.download, openvibe.pics and openvibe.video (plan T10 D4, by Host header). v1: openvibe.download is a private drive — account-only uploads streamed into OpenVibe.Media (app media-hub; a plain form up to 256 MB, resumable multipart beyond), private files and folders with per-person limits, share links that expire, need a signed-in downloader and may name accounts (matched by subject), reports that suspend a share for staff, and sandboxed attachment downloads. openvibe.pics and openvibe.video answer with coming pages: their uploads wait for scanning and abuse intake (the video.*/pics.*/download.* capabilities stay planned until an app may call them). Consumes OpenVibe.Network (SSO with PKCE S256 as OAuth client media-hub, JWKS, identity.subject.resolve) and OpenVibe.Media; answers account export and deletion (ADR-033). Since 2026-10-12 the same process serves openvibe.video, OpenVibe.Video v1: public, read-only watch pages for OpenVibe.Live's stream recordings and clips (read from Live's public API, files on OpenVibe.Media), with WebVTT captions from the AI transcript and chapters from the AI moments. Its playlists (MediaHub#31) have an API for people and apps since 0.152.0 (video.playlist.read, video.playlist.manage; MediaHub#33); video.vod.read stays planned (the watch pages are public HTML). openvibe.pics stays parked.",
"health": "/api/health",
"health": "/api/health",
"ready": "/api/ready",
"ready": "/api/ready",
"internalOrigin": "http://127.0.0.1:4990",
"internalOrigin": "http://127.0.0.1:4990",
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.151.0",
+ "version": "0.152.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
"types": "generated/typescript/index.d.ts",