Upload with the API
Upload video files, import them from a URL, Google Drive or OneDrive, and group them into collections.
Your server can add videos to a library without the console, by uploading a file or by asking OctaVideo to fetch one.
Upload a file
POST https://api.octavideo.tech/api/v1/videos/upload
AccessKey: ovk_your_private_key
Content-Type: multipart/form-dataSend the video as multipart/form-data with two parts, in this order:
Prop
Type
Send title before file
OctaVideo streams the file straight into storage as it arrives, so it reads parts only until the file. A title sent after the file is ignored, and the video gets the file name instead.
An upload can take up to 2 hours, so give your HTTP client a long timeout. Each example reads the key from the OCTAVIDEO_KEY environment variable:
curl -X POST "https://api.octavideo.tech/api/v1/videos/upload" \
-H "AccessKey: $OCTAVIDEO_KEY" \
-F "title=Lesson 1: Introduction" \
-F "file=@lesson-1.mp4"The Python example uses the third-party requests package, which places data fields before files. It builds the whole request body in memory, so for very large files use a streaming client.
A successful upload returns 201 Created with the new video, in the queued status:
{
"data": {
"id": "6f1c2b9e-4a7d-4f3e-9b8a-2d5c7e1f0a34",
"library_id": "0b8e5d3a-1c2f-4e6a-8b7d-9f0a1b2c3d4e",
"title": "Lesson 1: Introduction",
"description": "",
"encoding_status": "queued",
"progress": 0,
"duration_seconds": 0,
"size_bytes": 412337152,
"chapters": [],
"created_at": "2026-10-25T09:30:00Z"
}
}The video is ready to play once processing finishes. See Processing status.
| Status | Code | Meaning |
|---|---|---|
400 | bad_request | The body isn't multipart/form-data, or it is malformed. |
400 | validation_failed | The file part is missing, or title is over 255 characters. |
401 | unauthorized | The AccessKey header is missing or the key is invalid. |
413 | payload_too_large | The file is over 10 GiB. |
Import from a link
Instead of sending the file, you can ask OctaVideo to fetch it:
POST https://api.octavideo.tech/api/v1/videos/import
AccessKey: ovk_your_private_key
Content-Type: application/jsonProp
Type
curl -X POST "https://api.octavideo.tech/api/v1/videos/import" \
-H "AccessKey: $OCTAVIDEO_KEY" \
-H "Content-Type: application/json" \
-d '{"source": "url", "source_ref": "https://example.com/lessons/intro.mp4", "title": "Lesson 1: Introduction"}'The import runs in the background. The response is 202 Accepted with a job_id and the new video in the queued status:
{
"data": {
"job_id": "3c9d1e7a-5b2f-4a8e-9d6c-1f0b2a3c4d5e",
"video": {
"id": "6f1c2b9e-4a7d-4f3e-9b8a-2d5c7e1f0a34",
"library_id": "0b8e5d3a-1c2f-4e6a-8b7d-9f0a1b2c3d4e",
"title": "Lesson 1: Introduction",
"description": "",
"encoding_status": "queued",
"progress": 0,
"duration_seconds": 0,
"size_bytes": 0,
"chapters": [],
"created_at": "2026-10-25T09:30:00Z"
}
}
}Keep the video's id: you follow the import through the video, like an upload. If the source can't be fetched or isn't a valid video, the video ends up failed with a failure_reason.
Group videos into collections
A collection groups videos of one library, such as the lessons of one course. Create it, then add videos to it:
curl -X POST "https://api.octavideo.tech/api/v1/collections" \
-H "AccessKey: $OCTAVIDEO_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Arabic grammar, level 1"}'- A collection
nameis up to 100 characters. - Each request adds 1 to 100 videos, and the IDs must be unique within the request.
GET /videos?collection_id=lists the videos in one collection, page by page.
Update a video
Once a video exists you can change it from your server too:
- Update video details: the title and description.
- Set video chapters: up to 200 chapters in time order.
- Transcribe a video: start a transcription of its speech.