POST /api/v1/video-resources
Publishes a resource in the video library, immediately published. Every
video is a video of the school's media library — find them with
List media (kind=video), then pass the media
ids in order. Links and uploads are added to the library from the school's
screens.
A video answer is not published here: it is born from a question, with Answer a video question.
| Role in the organization | This endpoint |
|---|---|
OWNER | Allowed |
ADMIN | Allowed |
MEMBER | Allowed for an assigned coach, whatever the scope; otherwise refused — 403 |
| Requirement | Rule for this endpoint |
|---|---|
| Business role | coach (any scope) for a MEMBER; a reviewer is refused |
| Resource scope | Program, media and resource of the key's organization |
| Participation | None |
| Resource state | The program is not archived |
| Header | Required | Description |
|---|---|---|
x-api-key | yes | API key created for this organization |
Idempotency-Key | yes | Stable key for this publication; a replay returns the first result |
X-Correlation-Id | no | Caller correlation id, returned or generated |
| Field | Type | Required | Nullable | Description |
|---|---|---|---|---|
programId | UUID | yes | no | Program of the school, not archived |
kind | string | yes | no | replay_other — video_answer is refused with 400 |
category | string | yes | no | replay (a live replay) or video (another video); shown as the resource's badge |
title | string | yes | no | 1 to 200 characters |
description | string | no | yes | Markdown, up to 10000 characters |
tags | string[] | no | no | Up to 10 tags of 1 to 40 characters; duplicates are removed regardless of case |
videos | object[] | yes | no | 1 to 20 distinct videos, in display order |
videos[].mediaId | UUID | yes | no | A video media of the school |
videos[].title | string | no | yes | Line title, up to 200 characters; otherwise the media title |
thumbnailMediaId | UUID | no | yes | An image media of the school; otherwise the first video's image |
{
"programId": "3a1f7c2e-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"kind": "replay_other",
"category": "video",
"title": "How to structure a service layer",
"tags": ["Architecture"],
"videos": [{"mediaId": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b", "title": "Part 1"}]
}curl -X POST "$COHORTE_API_BASE_URL/api/v1/video-resources" \
-H "x-api-key: $COHORTE_API_KEY" \
-H "Idempotency-Key: video-service-layer-001" \
-H "Content-Type: application/json" \
-d '{"programId":"3a1f7c2e-5b6d-4e8f-9a0b-1c2d3e4f5a6b","kind":"replay_other","category":"video","title":"How to structure a service layer","videos":[{"mediaId":"9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b"}]}'201 Created — the resource, published.200 OK — replayed: true: the key was already used, the original resource comes back.400 Bad Request — missing Idempotency-Key, invalid JSON, a field out of bounds, an unknown or archived program, a media that is not a video (or not an image for the thumbnail) of the school, the same video twice, a missing category, or kind video_answer.401 Unauthorized — missing, unknown or expired key.403 Forbidden — the bearer is neither OWNER, ADMIN nor an assigned coach.The fields of one item of
List video resources,
without programName, thumbnailUrl, videoCount and authorName. Read the
resource to get its videos.
{
"success": true,
"replayed": false,
"data": {
"id": "6f2b1c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"programId": "3a1f7c2e-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"kind": "replay_other",
"category": "video",
"title": "How to structure a service layer",
"description": null,
"tags": ["Architecture"],
"status": "published",
"thumbnailMediaId": null,
"createdBy": "0b1c2d3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
"publishedAt": "2026-10-18T10:00:00.000Z",
"unpublishedAt": null,
"createdAt": "2026-10-18T10:00:00.000Z",
"updatedAt": "2026-10-18T10:00:00.000Z"
},
"correlationId": "c0ffee00-1111-4222-8333-444455556666"
}video_resource.created event. No email and no in-app notification are sent.Idempotency-Key creates no second resource.