Draft: these docs describe OctaVideo as it will be at launch; some features may not be live yet.
OctaVideoDocs

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-data

Send 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:

201 Created
{
  "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.

StatusCodeMeaning
400bad_requestThe body isn't multipart/form-data, or it is malformed.
400validation_failedThe file part is missing, or title is over 255 characters.
401unauthorizedThe AccessKey header is missing or the key is invalid.
413payload_too_largeThe 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/json

Prop

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:

202 Accepted
{
  "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 name is 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:

What's next

On this page