VideoHub uses a two-step upload process to handle large video files without running into HTTP timeout issues. The first request reserves a MongoDB ObjectId without touching the database. The second request immediately creates a database record marked as hidden, then fires off an asynchronous Cloudinary upload in the background — so your client gets a fast response while the heavy processing continues server-side. Once Cloudinary finishes, the record is automatically flipped to published.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/barcode8/VideoHub/llms.txt
Use this file to discover all available pages before exploring further.
Two-Step Upload Flow
Initialize — reserve a video ID
Call
POST /api/v1/videos/init to generate a fresh MongoDB ObjectId. No database record is created at this point; the ID is purely in-memory. Hold on to the returned videoId — you will use it in the next step.Publish — upload the file and metadata
Call
POST /api/v1/videos/:videoId with the videoId from the previous step. The server creates a database record immediately with isPublished: false and responds right away. A background process then uploads the video (and optional thumbnail) to Cloudinary. Once processing is complete the record’s isPublished field is set to true and the real Cloudinary URLs replace the temporary "processing" placeholders.POST /api/v1/videos/init
Generates a MongoDB ObjectId to be used as the video’s_id in the subsequent publish call. No database write occurs.
Authentication: Required (verifyJwt)
Request
No request body is needed.Response
Example
POST /api/v1/videos/:videoId
Creates a video document withisPublished: false and immediately returns. Cloudinary upload and processing run asynchronously in the background. Once complete, isPublished is set to true and the real URLs are stored.
Authentication: Required (verifyJwt)
If no
thumbnail file is provided, VideoHub auto-generates one from the video using Cloudinary’s so_auto transformation. The thumbnail URL is constructed by splitting the Cloudinary video URL on /upload/, inserting so_auto/ after it, and replacing the .mp4 extension with .jpg.Path Parameters
The MongoDB ObjectId returned by
POST /api/v1/videos/init. Using a valid ObjectId that was not generated by the init endpoint is allowed, but doing so risks ID collisions.Request Body (multipart/form-data)
The video file to upload. Passed as a binary file field in the multipart form. Supported formats depend on your Cloudinary plan.
The display title of the video. The controller explicitly validates that this field is present and non-empty.
A description of the video’s content. The controller does not explicitly validate this field, but the Mongoose schema marks it
required: true — omitting it will cause the database write to fail. Always provide a non-empty value.An optional image file to use as the video thumbnail. If omitted, a thumbnail is auto-generated from the video using Cloudinary’s
so_auto transformation.Response
Returns the video document as it exists immediately after the database insert — before background processing completes. ThevideoFile and thumbnail fields will read "processing" at this stage.
Example — Full Two-Step Flow
GET /api/v1/videos
Returns a paginated feed of published videos. Supports full-text search, sorting, and filtering by channel owner. When auserId filter is applied and the authenticated requester is that user, unpublished videos are also included — useful for a creator’s own dashboard.
Authentication: Optional (verifyJWTIfAvailable)
Query Parameters
The page number for pagination. Must be a positive integer.
The number of videos to return per page. Must be a positive integer.
A search string matched case-insensitively against both the
title and description fields using a regex filter.The document field to sort results by — for example
createdAt or views. When omitted, results default to createdAt descending (newest first).Sort direction. Accepts
"asc" (ascending) or "desc" (descending). Any value other than "asc" is treated as descending.A MongoDB ObjectId belonging to a channel owner. When provided, only that user’s videos are returned. If the authenticated requester matches this
userId, their unpublished videos are included as well. Returns a 400 if the value is not a valid ObjectId.Response
Returns a paginated result object produced bymongoose-aggregate-paginate-v2. Each video document includes an embedded ownerDetails object containing the owner’s username and avatar (resolved via $lookup on the users collection).