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
- Log in to your SearchByVideo account
- Go to Settings → API Keys
- Click "Generate New Key"
- Copy the token (keep it secret!)
Using Your API Key
Include the API key in request headers:
Authorization: Bearer YOUR_API_KEY_HERERate 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 windowX-RateLimit-Remaining— Requests leftX-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
| Parameter | Type | Required | Description |
|---|---|---|---|
| file | File | Yes | Video file (MP4, MOV, WebM, MKV, AVI, FLV) |
| title | String | No | Video title (max 255 chars) |
| description | String | No | Video 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | String | Yes | Natural language search query |
| search_type | String | No | "instant" or "deep" (default: "deep") |
| limit | Integer | No | Max 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | String | Yes | Original 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| start_ms | Integer | Yes | Start time in milliseconds |
| end_ms | Integer | Yes | End time in milliseconds |
| format | String | No | "mp4", "mov", "webm" (default: "mp4") |
| resolution | String | No | "1080p", "720p", "480p" (default: "1080p") |
| quality | String | No | "high", "medium", "low" (default: "high") |
Response (200 OK - returns file)
Returns the exported video file with headers:
Content-Type: video/mp4Content-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
| Parameter | Type | Description |
|---|---|---|
| limit | Integer | Results per page (1-100, default: 20) |
| offset | Integer | Pagination offset (default: 0) |
| status | String | Filter 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
| Code | Error | Description |
|---|---|---|
| 400 | bad_request | Invalid request parameters |
| 401 | unauthorized | Invalid or missing API key |
| 403 | forbidden | Permission denied |
| 404 | not_found | Resource not found |
| 409 | conflict | Resource already exists |
| 429 | rate_limited | Too many requests |
| 500 | server_error | Internal server error |
| 503 | service_unavailable | Service 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
- Go to Settings → API → Webhooks
- Add webhook URL (must be HTTPS)
- Select events to subscribe to:
video.uploadedvideo.analysis.completedvideo.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 logic2. 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 None4. 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
- Documentation: https://docs.searchbyvideo.net
- API Status: https://status.searchbyvideo.net
- Email: api@searchbyvideo.net
- Discord: community.searchbyvideo.net
Ready to integrate SearchByVideo? Get your API key →