Videos API
The Videos API provides endpoints for managing video content, including CRUD operations, metadata management, comments, and progress tracking.
Videos API
The Videos API provides endpoints for managing video content, including CRUD operations, metadata management, comments, and progress tracking.
Endpoints
List Videos
Retrieve a paginated list of videos with optional filtering.
GET /api/videos
Query Parameters:
organizationId(string, optional): Filter by organization IDchannelId(string, optional): Filter by channel IDseriesId(string, optional): Filter by series IDpage(integer, optional): Page number (default: 1)limit(integer, optional): Items per page (default: 20, max: 100)
Example Request:
GET /api/videos?organizationId=ws_123&page=1&limit=10
Response:
{
"success": true,
"data": {
"videos": [
{
"id": "video_123",
"title": "Team Meeting - Q1 Planning",
"description": "Quarterly planning session with the development team",
"duration": "00:45:30",
"thumbnailUrl": "https://example.com/thumbnail.jpg",
"videoUrl": "https://example.com/video.mp4",
"authorId": "user_456",
"organizationId": "ws_123",
"channelId": "ch_789",
"seriesId": "series_012",
"transcript": "Meeting transcript...",
"aiSummary": "Key points discussed...",
"createdAt": "2024-01-01T10:00:00Z",
"updatedAt": "2024-01-01T10:00:00Z",
"author": {
"id": "user_456",
"name": "John Doe",
"email": "john@example.com",
"avatarUrl": "https://example.com/avatar.jpg"
},
"organization": {
"id": "ws_123",
"name": "Development Team",
"slug": "dev-team"
},
"channel": {
"id": "ch_789",
"name": "Meetings",
"description": "Team meetings and discussions"
},
"series": {
"id": "series_012",
"name": "Q1 Planning",
"description": "Quarterly planning sessions"
}
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"totalPages": 3
}
}
}
Get Video
Retrieve a specific video with full details including comments.
GET /api/videos/{id}
Path Parameters:
id(string, required): Video ID
Example Request:
GET /api/videos/video_123
Response:
{
"success": true,
"data": {
"id": "video_123",
"title": "Team Meeting - Q1 Planning",
"description": "Quarterly planning session with the development team",
"duration": "00:45:30",
"thumbnailUrl": "https://example.com/thumbnail.jpg",
"videoUrl": "https://example.com/video.mp4",
"authorId": "user_456",
"organizationId": "ws_123",
"channelId": "ch_789",
"seriesId": "series_012",
"transcript": "Meeting transcript...",
"aiSummary": "Key points discussed...",
"createdAt": "2024-01-01T10:00:00Z",
"updatedAt": "2024-01-01T10:00:00Z",
"author": {
"id": "user_456",
"name": "John Doe",
"email": "john@example.com",
"avatarUrl": "https://example.com/avatar.jpg"
},
"organization": {
"id": "ws_123",
"name": "Development Team",
"slug": "dev-team"
},
"channel": {
"id": "ch_789",
"name": "Meetings",
"description": "Team meetings and discussions"
},
"series": {
"id": "series_012",
"name": "Q1 Planning",
"description": "Quarterly planning sessions"
},
"comments": [
{
"id": "comment_123",
"content": "Great discussion on the new features",
"timestamp": "00:15:30",
"authorId": "user_789",
"videoId": "video_123",
"parentId": null,
"createdAt": "2024-01-01T11:00:00Z",
"updatedAt": "2024-01-01T11:00:00Z",
"author": {
"id": "user_789",
"name": "Jane Smith",
"email": "jane@example.com",
"avatarUrl": "https://example.com/avatar2.jpg"
},
"replies": []
}
]
}
}
Create Video
Create a new video in a organization.
POST /api/videos
Content-Type: application/json
Request Body:
{
"title": "Team Meeting - Q1 Planning",
"description": "Quarterly planning session with the development team",
"duration": "00:45:30",
"thumbnailUrl": "https://example.com/thumbnail.jpg",
"videoUrl": "https://example.com/video.mp4",
"authorId": "user_456",
"organizationId": "ws_123",
"channelId": "ch_789",
"seriesId": "series_012"
}
Response:
{
"success": true,
"data": {
"id": "video_123",
"title": "Team Meeting - Q1 Planning",
"description": "Quarterly planning session with the development team",
"duration": "00:45:30",
"thumbnailUrl": "https://example.com/thumbnail.jpg",
"videoUrl": "https://example.com/video.mp4",
"authorId": "user_456",
"organizationId": "ws_123",
"channelId": "ch_789",
"seriesId": "series_012",
"transcript": null,
"aiSummary": null,
"createdAt": "2024-01-01T10:00:00Z",
"updatedAt": "2024-01-01T10:00:00Z",
"author": {
"id": "user_456",
"name": "John Doe",
"email": "john@example.com",
"avatarUrl": "https://example.com/avatar.jpg"
},
"organization": {
"id": "ws_123",
"name": "Development Team",
"slug": "dev-team"
},
"channel": {
"id": "ch_789",
"name": "Meetings",
"description": "Team meetings and discussions"
},
"series": {
"id": "series_012",
"name": "Q1 Planning",
"description": "Quarterly planning sessions"
}
}
}
Update Video
Update an existing video's metadata.
PUT /api/videos/{id}
Content-Type: application/json
Path Parameters:
id(string, required): Video ID
Request Body:
{
"title": "Updated Team Meeting - Q1 Planning",
"description": "Updated quarterly planning session with the development team",
"channelId": "ch_456",
"seriesId": "series_789"
}
Response:
{
"success": true,
"data": {
"id": "video_123",
"title": "Updated Team Meeting - Q1 Planning",
"description": "Updated quarterly planning session with the development team",
"duration": "00:45:30",
"thumbnailUrl": "https://example.com/thumbnail.jpg",
"videoUrl": "https://example.com/video.mp4",
"authorId": "user_456",
"organizationId": "ws_123",
"channelId": "ch_456",
"seriesId": "series_789",
"transcript": null,
"aiSummary": null,
"createdAt": "2024-01-01T10:00:00Z",
"updatedAt": "2024-01-01T12:00:00Z",
"author": {
"id": "user_456",
"name": "John Doe",
"email": "john@example.com",
"avatarUrl": "https://example.com/avatar.jpg"
},
"organization": {
"id": "ws_123",
"name": "Development Team",
"slug": "dev-team"
},
"channel": {
"id": "ch_456",
"name": "Announcements",
"description": "Team announcements"
},
"series": {
"id": "series_789",
"name": "Q2 Planning",
"description": "Second quarter planning sessions"
}
}
}
Delete Video
Delete a video from the organization.
DELETE /api/videos/{id}
Path Parameters:
id(string, required): Video ID
Response:
{
"success": true,
"data": {
"message": "Video deleted successfully"
}
}
Data Models
Video
interface Video {
id: string;
title: string;
description?: string;
duration: string;
thumbnailUrl?: string;
videoUrl?: string;
authorId: string;
organizationId: string;
channelId?: string;
seriesId?: string;
transcript?: string;
aiSummary?: string;
createdAt: string;
updatedAt: string;
}
Video with Details
interface VideoWithDetails extends Video {
author: User;
organization: Organization;
channel?: Channel;
series?: Series;
comments: CommentWithReplies[];
}
Comment
interface Comment {
id: string;
content: string;
timestamp?: string;
authorId: string;
videoId: string;
parentId?: string;
createdAt: string;
updatedAt: string;
}
Comment with Replies
interface CommentWithReplies extends Comment {
author: User;
replies: CommentWithReplies[];
}
Error Responses
Video Not Found
{
"success": false,
"error": "Video not found"
}
Invalid Request
{
"success": false,
"error": "Title is required"
}
Server Error
{
"success": false,
"error": "Failed to create video"
}
Authentication
All video endpoints require authentication. Include the session cookie or authorization header:
Authorization: Bearer <session_token>
Permissions
- Create Video: User must be a member of the organization
- Update Video: User must be the video author or organization admin
- Delete Video: User must be the video author or organization admin
- View Video: User must have access to the organization
Video Upload
For video file uploads, use a separate upload endpoint with multipart/form-data:
POST /api/videos/upload
Content-Type: multipart/form-data
{
"file": <video_file>,
"organizationId": "ws_123",
"title": "Meeting Recording",
"description": "Team meeting from today"
}
Video Processing
Videos undergo processing after upload:
- Thumbnail Generation: Automatic thumbnail extraction
- Transcription: Audio-to-text conversion
- AI Analysis: Summary and insights generation
- Encoding: Multiple quality formats
Video Progress Tracking
Track user viewing progress:
POST /api/videos/{id}/progress
Content-Type: application/json
{
"currentTime": "00:15:30",
"completed": false
}
Comments API
Add Comment
POST /api/videos/{id}/comments
Content-Type: application/json
{
"content": "Great discussion on the new features",
"timestamp": "00:15:30",
"parentId": null
}
Reply to Comment
POST /api/videos/{id}/comments
Content-Type: application/json
{
"content": "I agree with your point",
"parentId": "comment_123"
}
Update Comment
PUT /api/videos/{id}/comments/{commentId}
Content-Type: application/json
{
"content": "Updated comment content"
}
Delete Comment
DELETE /api/videos/{id}/comments/{commentId}
Search and Filtering
Search Videos
GET /api/videos/search?q=meeting&organizationId=ws_123
Filter by Tags
GET /api/videos?tags=meeting,planning&organizationId=ws_123
Filter by Date Range
GET /api/videos?startDate=2024-01-01&endDate=2024-01-31&organizationId=ws_123
Analytics
Video Statistics
GET /api/videos/{id}/stats
Response:
{
"success": true,
"data": {
"views": 42,
"uniqueViewers": 15,
"averageWatchTime": "00:22:15",
"comments": 8,
"likes": 12,
"shares": 3
}
}
Webhooks
Subscribe to video events:
video.created: New video uploadedvideo.updated: Video metadata changedvideo.deleted: Video removedvideo.processed: Video processing completedcomment.created: New comment added
Subtitles and Transcripts
List Subtitle Languages
Get available subtitle languages for a video.
GET /api/videos/{id}/subtitles
Response:
{
"success": true,
"data": {
"videoId": "video_123",
"hasTranscript": true,
"processingStatus": "completed",
"languages": [
{
"code": "en",
"name": "English",
"nativeName": "English",
"isOriginal": true,
"available": true,
"url": "/api/videos/video_123/subtitles/en.vtt"
},
{
"code": "es",
"name": "Spanish",
"nativeName": "Español",
"isOriginal": false,
"available": true,
"url": "/api/videos/video_123/subtitles/es.vtt"
}
]
}
}
Get Subtitle File
Get WebVTT or SRT subtitle file for a specific language.
GET /api/videos/{id}/subtitles/{lang}.vtt
GET /api/videos/{id}/subtitles/{lang}.srt
Path Parameters:
id(string, required): Video IDlang(string, required): Language code (e.g.,en,es,fr)
Response: WebVTT file content
WEBVTT
Kind: captions
Language: en
1
00:00:00.000 --> 00:00:05.230
Welcome to this video tutorial.
2
00:00:05.230 --> 00:00:10.450
Today we'll be discussing the new features.
Supported Languages:
English (en), Spanish (es), French (fr), German (de), Portuguese (pt), Italian (it), Dutch (nl), Polish (pl), Russian (ru), Japanese (ja), Chinese (zh), Korean (ko), Arabic (ar), Turkish (tr), Swedish (sv), Danish (da), Finnish (fi), Norwegian (nb), Greek (el), Czech (cs), Romanian (ro), Hungarian (hu), Ukrainian (uk), Indonesian (id), Vietnamese (vi), Thai (th)
Get Transcript
Get transcript data for a video.
GET /api/videos/{id}/transcript
Response:
{
"success": true,
"data": {
"videoId": "video_123",
"title": "Team Meeting",
"transcript": "Full transcript text...",
"segments": [
{
"startTime": 0,
"endTime": 5.23,
"text": "Welcome to this video tutorial.",
"confidence": 0.95
},
{
"startTime": 5.23,
"endTime": 10.45,
"text": "Today we'll be discussing the new features.",
"confidence": 0.92
}
],
"processingStatus": "completed"
}
}
Update Transcript
Update transcript segments (for corrections).
PUT /api/videos/{id}/transcript
Content-Type: application/json
Request Body:
{
"segments": [
{
"startTime": 0,
"endTime": 5.23,
"text": "Corrected transcript text.",
"confidence": 1.0
}
]
}
Validation Rules:
- Segments must be in chronological order
- Start time must be before end time
- Text cannot be empty
Response:
{
"success": true,
"data": {
"videoId": "video_123",
"segments": [...],
"message": "Transcript updated successfully"
}
}
Rate Limits
- Video Upload: 10 uploads per hour per user
- API Requests: 100 requests per minute per user
- Comment Creation: 30 comments per minute per user
- Translation Requests: 100 per hour (requires DeepL API key)
Examples
JavaScript/TypeScript
// Fetch videos
const response = await fetch("/api/videos?organizationId=ws_123");
const { data } = await response.json();
// Create video
const newVideo = await fetch("/api/videos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: "Team Meeting",
duration: "00:45:30",
organizationId: "ws_123",
authorId: "user_456",
}),
});
React Hook
import { useVideos } from "@/hooks/useVideos";
function VideoList({ organizationId }: { organizationId: string }) {
const { videos, loading, error } = useVideos({ organizationId });
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
{videos.map((video) => (
<VideoCard key={video.id} video={video} />
))}
</div>
);
}