Documentation

Videos API Reference

Chunked multipart video uploads with progress tracking and analysis

Multipart Chunked Upload

  • Formats: MP4, MOV (QuickTime), M4V, WebM, AVI
  • Max size: 10GB per video
  • Chunk size: 10MB per chunk
  • Max chunks: 10,000 per upload
  • Process: Initiate → Upload chunks → Confirm chunks → Complete

Validation Rules

  • Filename: 1-255 characters
  • Content type: Must be one of: video/mp4, video/quicktime, video/x-m4v, video/webm, video/x-msvideo
  • File size: Must be greater than 0, maximum 10,737,418,240 bytes (10GB)
  • Tags: Maximum 20 tags, each 1-50 characters. Only letters, numbers, spaces, hyphens, and underscores allowed.
  • Title: Maximum 255 characters

Video Upload Workflow

POST/api/v2/video-uploads/initiate

Start a multipart video upload and get presigned URLs for each chunk. Returns 201 Created on success. Returns 413 if storage quota is exceeded.

Request

{
"filename": "inspection.mp4",
"content_type": "video/mp4",
"size_bytes": 524288000,
"title": "Site Inspection Video",
"tags": ["inspection", "site-a"],
"metadata": {
"project": "building-audit",
"location": "floor-3"
}
}
// Required fields: filename, content_type, size_bytes
// Optional fields: title, tags, metadata

Response

{
"media_id": "550e8400-e29b-41d4-a716-446655440000",
"upload_id": "multipart_upload_abc123",
"total_chunks": 50,
"chunk_size_bytes": 10485760,
"storage_path": "tenants/abc/videos/550e8400.mp4",
"chunks": [
{
"chunk_number": 1,
"size_bytes": 10485760,
"upload_url": "https://s3.amazonaws.com/bucket/chunk-1...",
"upload_method": "PUT",
"expires_at": "2025-01-15T10:40:00Z"
}
],
"expires_at": "2025-01-15T10:40:00Z",
"concurrent_upload_limit": 5,
"retry_attempts": 3
}
POST/api/v2/video-uploads/chunks/confirm

Confirm successful upload of a video chunk. Call this after each chunk is uploaded to S3 with the ETag returned by S3.

Request

{
"media_id": "550e8400-e29b-41d4-a716-446655440000",
"upload_id": "multipart_upload_abc123",
"chunk_number": 1,
"etag": "abc123def456",
"size_bytes": 10485760
}
// All fields are required
// chunk_number: 1-indexed, range 1-10000
// size_bytes: must be greater than 0

Response

{
"chunk_number": 1,
"status": "completed",
"chunks_completed": 1,
"total_chunks": 50,
"progress_percent": 2.0,
"estimated_time_remaining": 245
}
POST/api/v2/video-uploads/complete

Finalize multipart upload and trigger video analysis. Verifies all chunks are present, completes the S3 multipart upload, extracts video metadata, generates a thumbnail, and queues AI analysis if requested.

Request

{
"media_id": "550e8400-e29b-41d4-a716-446655440000",
"upload_id": "multipart_upload_abc123",
"auto_analyze": true,
"analysis_provider": "google",
"analysis_model": "gemini-3-flash-preview",
"analysis_type": "full_vlm"
}
// Required: media_id, upload_id
// Optional: auto_analyze (default: true),
// analysis_provider (default: "google", options: "google" | "openai" | "anthropic"),
// analysis_model (default: "gemini-3-flash-preview"),
// analysis_type (default: "full_vlm", options: "full_vlm" | "frame_sample" | "scene_detection" | "transcript")

Response

{
"media_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"processing_status": "queued",
"metadata": {
"duration_seconds": 120.5,
"resolution": "1920x1080",
"width": 1920,
"height": 1080,
"frame_rate": 30.0,
"video_codec": "h264",
"audio_codec": "aac",
"bitrate_kbps": 5000,
"file_size_bytes": 524288000,
"format_name": "mp4"
},
"video_url": "https://cdn.aionvision.tech/videos/...",
"thumbnail_url": "https://cdn.aionvision.tech/thumbnails/...",
"analysis_job_id": "990c2800-c62f-85b8-eb5a-880099880444",
"created_at": "2025-01-15T10:30:00Z"
}
// processing_status: "pending" | "queued" | "processing" | "completed" | "failed"
// audio_codec is null if the video has no audio track
// analysis_job_id is null if auto_analyze was false

Progress Tracking & Retry

GET/api/v2/video-uploads/progress/{media_id}

Get real-time upload progress including chunks completed, bytes uploaded, and estimated time remaining

Response

{
"media_id": "550e8400-e29b-41d4-a716-446655440000",
"upload_id": "multipart_upload_abc123",
"status": "uploading",
"chunks_completed": 25,
"total_chunks": 50,
"bytes_uploaded": 262144000,
"total_bytes": 524288000,
"progress_percent": 50.0,
"estimated_time_remaining": 120,
"current_chunk": 26,
"failed_chunks": [],
"last_updated": "2025-01-15T10:35:00Z"
}
// status: "uploading" | "processing" | "completed" | "failed" | "aborted"
POST/api/v2/video-uploads/chunks/retry

Get a new presigned URL for retrying a failed chunk upload. Retry limits are based on subscription tier.

Request

{
"media_id": "550e8400-e29b-41d4-a716-446655440000",
"upload_id": "multipart_upload_abc123",
"chunk_number": 5
}
// All fields are required
// chunk_number: 1-indexed, range 1-10000

Response

{
"chunk_number": 5,
"upload_url": "https://s3.amazonaws.com/bucket/retry-chunk-5...",
"expires_at": "2025-01-15T10:50:00Z",
"retry_attempt": 1,
"max_retries": 3
}
POST/api/v2/video-uploads/abort

Cancel an in-progress upload and clean up S3 resources. Aborts the S3 multipart upload, deletes chunk records, and soft deletes the media record.

Request

{
"media_id": "550e8400-e29b-41d4-a716-446655440000",
"upload_id": "multipart_upload_abc123",
"reason": "User cancelled"
}
// Required: media_id, upload_id
// Optional: reason (max 500 characters)

Response

{
"media_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "aborted",
"cleaned_up": true,
"chunks_removed": 25,
"s3_cleanup": true
}

Video Scenes

GET/api/v2/videos/{video_id}/scenes

List all scenes for a video with metadata. Returns scenes ordered by scene index with timestamps, descriptions, tags, and thumbnail URLs.

Response

{
"video_id": "550e8400-e29b-41d4-a716-446655440000",
"count": 3,
"scenes": [
{
"scene_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"scene_index": 0,
"start_time": 0.0,
"end_time": 45.0,
"time_range_formatted": "0:00-0:45",
"description": "Exterior view of the building entrance",
"tags": ["exterior", "entrance"],
"visible_text": "Building A - Main Entrance",
"confidence_score": 0.92,
"embedding_status": "completed",
"thumbnail_url": "/api/v2/video-scenes/a1b2c3d4-e5f6-7890-abcd-ef1234567890/thumbnail",
"created_at": "2025-01-15T10:45:00Z"
}
]
}
// Returns empty scenes array with count 0 if no scenes exist
// thumbnail_url is null if no thumbnail was generated for the scene
// visible_text may be null if no text was detected
// embedding_status: "pending" | "completed"
GET/api/v2/video-scenes/{scene_id}/thumbnail

Serve the thumbnail image for a specific video scene. Returns the JPEG image generated at the scene midpoint during analysis. Response is cached with a 1-year Cache-Control header.

Response

// Returns binary JPEG image data
// Content-Type: image/jpeg
// Cache-Control: public, max-age=31536000
// Content-Disposition: inline; filename="scene_{scene_id}.jpg"
// Returns 404 if scene not found or no thumbnail available