SearchByVideo API Documentation - Integration Guide

apr. 19, 2025

SearchByVideo API Documentation

Build powerful video search capabilities into your application using the SearchByVideo REST API. This guide covers authentication, endpoints, and integration examples.

Overview

The SearchByVideo API allows you to:

  • Upload and analyze videos programmatically
  • Search for moments using natural language queries
  • Retrieve video metadata and analysis data
  • Export video clips
  • Manage your video library
  • Automate video processing workflows

Base URL: https://api.searchbyvideo.net/v1

Authentication: Bearer token (provided in dashboard)

Authentication

Getting Your API Key

  1. Log in to your SearchByVideo account
  2. Go to Settings → API Keys
  3. Click "Generate New Key"
  4. Copy the token (keep it secret!)

Using Your API Key

Include the API key in request headers:

Authorization: Bearer YOUR_API_KEY_HERE

Rate Limiting

API requests are rate-limited based on your plan:

  • Free Trial: 10 requests/minute, 100/day
  • Pro: 100 requests/minute, 10,000/day
  • Enterprise: Custom limits

Rate limit headers in response:

  • X-RateLimit-Limit — Requests allowed per window
  • X-RateLimit-Remaining — Requests left
  • X-RateLimit-Reset — Unix timestamp when limit resets

Core Endpoints

1. Upload Video

POST /videos/upload

Upload a video file for analysis.

Request

curl -X POST https://api.searchbyvideo.net/v1/videos/upload \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@video.mp4" \
  -F "title=My Video" \
  -F "description=Optional description"

Parameters

ParameterTypeRequiredDescription
fileFileYesVideo file (MP4, MOV, WebM, MKV, AVI, FLV)
titleStringNoVideo title (max 255 chars)
descriptionStringNoVideo description (max 1000 chars)

Response (201 Created)

{
  "id": "vid_abc123xyz",
  "title": "My Video",
  "status": "uploading",
  "duration_ms": 120000,
  "created_at": "2025-04-19T10:30:00Z",
  "analysis_status": "queued",
  "download_url": "https://..."
}

2. Get Video Details

GET /videos/{video_id}

Retrieve video metadata and analysis status.

Request

curl https://api.searchbyvideo.net/v1/videos/vid_abc123xyz \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (200 OK)

{
  "id": "vid_abc123xyz",
  "title": "My Video",
  "status": "ready",
  "duration_ms": 120000,
  "size_bytes": 52428800,
  "format": "mp4",
  "resolution": "1920x1080",
  "framerate": 30,
  "created_at": "2025-04-19T10:30:00Z",
  "analysis_status": "completed",
  "analysis_completed_at": "2025-04-19T10:32:45Z"
}

3. Search Video

POST /videos/{video_id}/search

Search for moments in a video using natural language queries.

Request

curl -X POST https://api.searchbyvideo.net/v1/videos/vid_abc123xyz/search \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "person laughing",
    "search_type": "deep",
    "limit": 10
  }'

Parameters

ParameterTypeRequiredDescription
queryStringYesNatural language search query
search_typeStringNo"instant" or "deep" (default: "deep")
limitIntegerNoMax results to return (1-100, default: 10)

Response (200 OK)

{
  "video_id": "vid_abc123xyz",
  "query": "person laughing",
  "results": [
    {
      "id": "result_123",
      "start_ms": 5000,
      "end_ms": 8000,
      "confidence": 0.95,
      "description": "Person laughing loudly"
    },
    {
      "id": "result_124",
      "start_ms": 45000,
      "end_ms": 48000,
      "confidence": 0.87,
      "description": "Person smiling and laughing"
    }
  ],
  "total_results": 2,
  "search_time_ms": 1250
}

4. Get Search Suggestions

POST /videos/{video_id}/search-suggestion

Get keyword suggestions when a search returns no results.

Request

curl -X POST https://api.searchbyvideo.net/v1/videos/vid_abc123xyz/search-suggestion \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "person flying"
  }'

Parameters

ParameterTypeRequiredDescription
queryStringYesOriginal search query

Response (200 OK)

{
  "original_query": "person flying",
  "suggestion": {
    "keyword": "person jumping",
    "confidence": 78,
    "reason": "Similar action concept found in video"
  }
}

5. Export Clip

POST /videos/{video_id}/export

Export a specific moment as a video file.

Request

curl -X POST https://api.searchbyvideo.net/v1/videos/vid_abc123xyz/export \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "start_ms": 5000,
    "end_ms": 8000,
    "format": "mp4",
    "resolution": "1080p",
    "quality": "high"
  }'

Parameters

ParameterTypeRequiredDescription
start_msIntegerYesStart time in milliseconds
end_msIntegerYesEnd time in milliseconds
formatStringNo"mp4", "mov", "webm" (default: "mp4")
resolutionStringNo"1080p", "720p", "480p" (default: "1080p")
qualityStringNo"high", "medium", "low" (default: "high")

Response (200 OK - returns file)

Returns the exported video file with headers:

  • Content-Type: video/mp4
  • Content-Length: [file size]
  • Content-Disposition: attachment; filename="clip.mp4"

6. List Videos

GET /videos

List all videos in your account.

Request

curl https://api.searchbyvideo.net/v1/videos \
  -H "Authorization: Bearer YOUR_API_KEY"

Query Parameters

ParameterTypeDescription
limitIntegerResults per page (1-100, default: 20)
offsetIntegerPagination offset (default: 0)
statusStringFilter by status: "uploading", "ready", "error"

Response (200 OK)

{
  "videos": [
    {
      "id": "vid_abc123xyz",
      "title": "My Video",
      "status": "ready",
      "duration_ms": 120000,
      "created_at": "2025-04-19T10:30:00Z"
    }
  ],
  "total": 15,
  "limit": 20,
  "offset": 0
}

7. Delete Video

DELETE /videos/{video_id}

Delete a video and all associated analysis data.

Request

curl -X DELETE https://api.searchbyvideo.net/v1/videos/vid_abc123xyz \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (204 No Content)

Video successfully deleted.

Error Handling

All errors return JSON with status code and message:

{
  "error": "invalid_request",
  "message": "Video ID is required",
  "code": 400
}

Common Error Codes

CodeErrorDescription
400bad_requestInvalid request parameters
401unauthorizedInvalid or missing API key
403forbiddenPermission denied
404not_foundResource not found
409conflictResource already exists
429rate_limitedToo many requests
500server_errorInternal server error
503service_unavailableService temporarily down

Code Examples

Python

import requests
import time

API_KEY = "your_api_key_here"
BASE_URL = "https://api.searchbyvideo.net/v1"

def upload_video(filepath, title):
    headers = {"Authorization": f"Bearer {API_KEY}"}

    with open(filepath, 'rb') as f:
        files = {'file': f}
        data = {'title': title}
        response = requests.post(
            f"{BASE_URL}/videos/upload",
            headers=headers,
            files=files,
            data=data
        )

    return response.json()

def search_video(video_id, query):
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    }

    payload = {
        "query": query,
        "search_type": "deep",
        "limit": 10
    }

    response = requests.post(
        f"{BASE_URL}/videos/{video_id}/search",
        headers=headers,
        json=payload
    )

    return response.json()

def export_clip(video_id, start_ms, end_ms, output_file):
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    }

    payload = {
        "start_ms": start_ms,
        "end_ms": end_ms,
        "format": "mp4",
        "resolution": "1080p"
    }

    response = requests.post(
        f"{BASE_URL}/videos/{video_id}/export",
        headers=headers,
        json=payload
    )

    with open(output_file, 'wb') as f:
        f.write(response.content)

# Usage
video = upload_video("my_video.mp4", "Travel Vlog")
video_id = video['id']

# Wait for analysis to complete
while True:
    details = requests.get(
        f"{BASE_URL}/videos/{video_id}",
        headers={"Authorization": f"Bearer {API_KEY}"}
    ).json()

    if details['analysis_status'] == 'completed':
        break
    time.sleep(2)

# Search for moments
results = search_video(video_id, "person at beach")

# Export the best moment
best = results['results'][0]
export_clip(video_id, best['start_ms'], best['end_ms'], "best_moment.mp4")

JavaScript (Node.js)

const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');

const API_KEY = 'your_api_key_here';
const BASE_URL = 'https://api.searchbyvideo.net/v1';

const client = axios.create({
  baseURL: BASE_URL,
  headers: {
    'Authorization': `Bearer ${API_KEY}`
  }
});

async function uploadVideo(filepath, title) {
  const form = new FormData();
  form.append('file', fs.createReadStream(filepath));
  form.append('title', title);

  const response = await client.post('/videos/upload', form, {
    headers: form.getHeaders()
  });

  return response.data;
}

async function searchVideo(videoId, query) {
  const response = await client.post(`/videos/${videoId}/search`, {
    query,
    search_type: 'deep',
    limit: 10
  });

  return response.data;
}

async function exportClip(videoId, startMs, endMs, outputFile) {
  const response = await client.post(
    `/videos/${videoId}/export`,
    {
      start_ms: startMs,
      end_ms: endMs,
      format: 'mp4',
      resolution: '1080p'
    },
    { responseType: 'arraybuffer' }
  );

  fs.writeFileSync(outputFile, response.data);
}

// Usage
(async () => {
  const video = await uploadVideo('my_video.mp4', 'Travel Vlog');
  const videoId = video.id;

  // Wait for analysis
  let completed = false;
  while (!completed) {
    const details = await client.get(`/videos/${videoId}`);
    if (details.data.analysis_status === 'completed') {
      completed = true;
    }
    await new Promise(r => setTimeout(r, 2000));
  }

  // Search
  const results = await searchVideo(videoId, 'person at beach');

  // Export
  const best = results.results[0];
  await exportClip(videoId, best.start_ms, best.end_ms, 'best_moment.mp4');
})();

cURL

#!/bin/bash

API_KEY="your_api_key_here"
BASE_URL="https://api.searchbyvideo.net/v1"

# Upload video
echo "Uploading video..."
VIDEO_RESPONSE=$(curl -s -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -F "file=@my_video.mp4" \
  -F "title=Travel Vlog" \
  "$BASE_URL/videos/upload")

VIDEO_ID=$(echo $VIDEO_RESPONSE | jq -r '.id')
echo "Video uploaded: $VIDEO_ID"

# Wait for analysis
echo "Waiting for analysis..."
while true; do
  STATUS=$(curl -s \
    -H "Authorization: Bearer $API_KEY" \
    "$BASE_URL/videos/$VIDEO_ID" | jq -r '.analysis_status')

  if [ "$STATUS" = "completed" ]; then
    break
  fi
  sleep 2
done

# Search for moments
echo "Searching for moments..."
SEARCH_RESPONSE=$(curl -s -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"person at beach"}' \
  "$BASE_URL/videos/$VIDEO_ID/search")

START_MS=$(echo $SEARCH_RESPONSE | jq -r '.results[0].start_ms')
END_MS=$(echo $SEARCH_RESPONSE | jq -r '.results[0].end_ms')

# Export clip
echo "Exporting clip..."
curl -s -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"start_ms\":$START_MS,\"end_ms\":$END_MS}" \
  "$BASE_URL/videos/$VIDEO_ID/export" \
  -o best_moment.mp4

echo "Done! Exported to best_moment.mp4"

Webhooks

Enterprise feature: Get real-time notifications when videos complete analysis.

Setting Up Webhooks

  1. Go to Settings → API → Webhooks
  2. Add webhook URL (must be HTTPS)
  3. Select events to subscribe to:
    • video.uploaded
    • video.analysis.completed
    • video.analysis.failed

Webhook Payload

{
  "event": "video.analysis.completed",
  "timestamp": "2025-04-19T10:32:45Z",
  "data": {
    "video_id": "vid_abc123xyz",
    "title": "My Video",
    "duration_ms": 120000,
    "analysis_time_ms": 165000
  }
}

Best Practices

1. Error Handling

Always handle errors gracefully:

try:
    result = search_video(video_id, query)
except requests.exceptions.RequestException as e:
    print(f"Search failed: {e}")
    # Implement retry logic

2. Batch Processing

For multiple videos, implement queue management:

def process_videos(filepaths):
    video_ids = []

    # Upload all
    for filepath in filepaths:
        video = upload_video(filepath, filepath)
        video_ids.append(video['id'])

    # Wait for all
    for video_id in video_ids:
        wait_for_analysis(video_id)

    # Process all
    for video_id in video_ids:
        results = search_video(video_id, "key moment")
        # Process results...

3. Store Analysis Data

Cache analysis results to avoid re-processing:

import json

def cache_analysis(video_id, results):
    with open(f"cache_{video_id}.json", 'w') as f:
        json.dump(results, f)

def get_cached_results(video_id):
    try:
        with open(f"cache_{video_id}.json", 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        return None

4. Rate Limit Awareness

Check rate limit headers and implement backoff:

def search_with_backoff(video_id, query):
    max_retries = 3
    retry_count = 0

    while retry_count < max_retries:
        response = requests.post(...)

        if response.status_code == 429:
            wait_time = int(response.headers.get('X-RateLimit-Reset'))
            time.sleep(wait_time - time.time() + 1)
            retry_count += 1
        else:
            return response.json()

Support


Ready to integrate SearchByVideo? Get your API key →