The SnapVid API is available on Business and Enterprise plans. Upload videos, manage content, and deliver video to your users programmatically.
https://api.snapvid.orgAll endpoints require HTTPS. HTTP requests will be rejected.
Here's a complete upload flow from start to finish:
# 1. Get a presigned upload URL
curl -X GET "https://api.snapvid.org/api/upload/presigned-url?filename=demo.mp4&filetype=video/mp4&filesize=52428800" \
-H "X-API-Key: sv_live_your_key_here"
# Response: { "uploadUrl": "https://s3...", "videoId": 123, "videoSlug": "1717000000_abc123" }
# 2. Upload the file directly to S3
curl -X PUT "UPLOAD_URL_FROM_STEP_1" \
-H "Content-Type: video/mp4" \
--data-binary @demo.mp4
# 3. Complete the upload with metadata
curl -X POST "https://api.snapvid.org/api/upload/complete" \
-H "X-API-Key: sv_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"video_id": 123,
"title": "Product Demo",
"description": "A walkthrough of our new feature",
"visibility": "unlisted"
}'
# Response includes shareable_slug — your watch URL is:
# https://snapvid.org/watch/{shareable_slug}SnapVid automatically processes your video into HLS adaptive streaming (360p, 480p, 720p, 1080p). Processing typically takes 1-3 minutes depending on file size.
const API_KEY = process.env.SNAPVID_API_KEY;
const BASE = "https://api.snapvid.org";
async function uploadVideo(file) {
// 1. Get presigned URL
const params = new URLSearchParams({
filename: file.name,
filetype: file.type,
filesize: String(file.size),
});
const { uploadUrl, videoId } = await fetch(
`${BASE}/api/upload/presigned-url?${params}`,
{ headers: { "X-API-Key": API_KEY } }
).then(r => r.json());
// 2. Upload file to S3
await fetch(uploadUrl, {
method: "PUT",
headers: { "Content-Type": file.type },
body: file,
});
// 3. Complete with metadata
const result = await fetch(`${BASE}/api/upload/complete`, {
method: "POST",
headers: {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
video_id: videoId,
title: "My Video",
visibility: "unlisted",
}),
}).then(r => r.json());
return result; // { success, video, shareable_slug }
}Authenticate all API requests using your API key. Pass it via the X-API-Key header.
curl -X GET "https://api.snapvid.org/api/my-videos" \
-H "X-API-Key: sv_live_your_api_key_here" \
-H "Content-Type: application/json"Security: Never expose your API key in client-side code, public repos, or frontend applications. Use environment variables on your server.
API keys follow the format sv_live_... and are 40+ characters long. You can have up to 5 active keys per account.
| Header | Value |
|---|---|
X-API-Key | Your API key |
Content-Type | application/json |
Uploading a video is a 3-step process: request a presigned URL, upload the file directly to storage, then finalize with metadata. This keeps your API key secure since the file never passes through our API server.
/api/upload/presigned-url| Parameter | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | Original filename (e.g. video.mp4) |
filetype | string | Yes | MIME type (video/mp4, video/quicktime, etc.) |
filesize | integer | No | File size in bytes (used for storage limit checks) |
{
"uploadUrl": "https://s3.amazonaws.com/...",
"key": "uploads/1717000000_abc123/1717000000_abc123.mp4",
"videoId": 456,
"videoSlug": "1717000000_abc123"
}| Field | Description |
|---|---|
uploadUrl | Presigned S3 URL. PUT your file here. Expires in 1 hour. |
key | Storage path (internal reference) |
videoId | Video record ID. Use this in step 3. |
videoSlug | Internal video identifier |
Upload your video file directly to the presigned URL using a PUT request. No authentication header needed for this step.
curl -X PUT "UPLOAD_URL_FROM_STEP_1" \
-H "Content-Type: video/mp4" \
--data-binary @your-video.mp4Supported formats: MP4, MOV, AVI, WebM. Max file size depends on your plan's storage limit.
/api/upload/complete{
"video_id": 456,
"title": "How to Make Jollof Rice",
"description": "Step-by-step jollof rice tutorial",
"tags": "cooking, tutorial, nigerian-food",
"visibility": "unlisted",
"download_enabled": false
}| Field | Type | Required | Description |
|---|---|---|---|
video_id | integer | Yes | The numeric videoId from step 1 |
title | string | No | Video title. Becomes part of the SEO-friendly URL. |
description | string | No | Video description |
tags | string | No | Comma-separated tags for organization |
visibility | string | No | public, unlisted, private, or password. Defaults to unlisted. |
download_enabled | boolean | No | Allow viewers to download the video. Defaults to false. |
password | string | No | Required when visibility is "password". |
expires_at | string | No | ISO date string for link expiry (Pro+ plans). |
{
"success": true,
"shareable_slug": "how-to-make-jollof-rice-1717000000",
"video": {
"id": 456,
"video_id": "1717000000_abc123",
"slug": "how-to-make-jollof-rice-1717000000",
"title": "How to Make Jollof Rice",
"status": "uploaded",
"visibility": "unlisted",
"hls_url": "https://cdn.snapvid.org/uploads/.../1717000000_abc123.m3u8",
"thumbnail_url": "https://cdn.snapvid.org/uploads/.../thumb.jpg"
}
}
// Your shareable URLs:
// Watch: https://snapvid.org/watch/how-to-make-jollof-rice-1717000000
// Embed: https://snapvid.org/embed/how-to-make-jollof-rice-1717000000Processing: After upload, SnapVid transcodes your video into adaptive streaming format (HLS). This typically takes 1-3 minutes. Check status via GET /api/videos/status/{video_id}.
/api/my-videosReturns your videos with pagination, sorted by newest first.
| Parameter | Default | Description |
|---|---|---|
page | 1 | Page number (starts at 1) |
page_size | 50 | Results per page (1–100) |
curl -X GET "https://api.snapvid.org/api/my-videos?page=1&page_size=20" \
-H "X-API-Key: sv_live_your_key_here"
// Response
{
"videos": [
{
"id": 456,
"video_id": "1717000000_abc123",
"slug": "how-to-make-jollof-rice-1717000000",
"title": "How to Make Jollof Rice",
"description": "Step-by-step tutorial",
"thumbnail_url": "https://cdn.snapvid.org/uploads/.../thumb.jpg",
"hls_url": "https://cdn.snapvid.org/uploads/.../master.m3u8",
"views": 342,
"visibility": "unlisted",
"status": "ready",
"download_enabled": false,
"created_at": "2025-04-15T10:30:00Z"
}
],
"total": 24,
"page": 1,
"page_size": 20,
"total_pages": 2
}Two IDs: Each video has a numeric id (e.g. 456) and a string video_id (e.g. "1717000000_abc123"). Most management endpoints use the numeric id. The privacy endpoint uses the string video_id. Each endpoint's docs specify which one to use.
| Field | Type | Description |
|---|---|---|
id | integer | Database ID (use for update/delete operations) |
slug | string | URL-friendly identifier. Used in watch/embed URLs. |
hls_url | string | HLS manifest URL for adaptive streaming playback |
thumbnail_url | string | Video thumbnail image URL |
status | string | processing, ready, or failed |
visibility | string | public, unlisted, private, or password |
views | integer | Total view count |
/api/videos/by-slug/{slug}Get a single video by its slug. Use this to check processing status or get the streaming URL.
curl -X GET "https://api.snapvid.org/api/videos/by-slug/how-to-make-jollof-rice-1717000000" \
-H "X-API-Key: sv_live_your_key_here"
// Response
{
"video_id": "1717000000_abc123",
"title": "How to Make Jollof Rice",
"description": "Step-by-step tutorial",
"hls_url": "https://cdn.snapvid.org/uploads/.../master.m3u8",
"thumbnail_url": "https://cdn.snapvid.org/uploads/.../thumb.jpg",
"views": 342,
"visibility": "unlisted",
"status": "ready",
"width": 1920,
"height": 1080,
"download_enabled": false
}/api/videos/status/{videoSlug}Poll this endpoint after upload to check when your video is ready for playback. Uses the videoSlug from step 1. Requires authentication.
curl -X GET "https://api.snapvid.org/api/videos/status/1717000000_abc123" \
-H "X-API-Key: YOUR_API_KEY"
// Response
{
"video_id": "1717000000_abc123",
"status": "ready",
"hls_url": "https://cdn.snapvid.org/uploads/.../1717000000_abc123.m3u8",
"thumbnail_url": "https://cdn.snapvid.org/uploads/.../thumb.jpg"
}| Status | Meaning |
|---|---|
processing | Video is being transcoded into streaming format |
ready | Video is ready to stream and embed |
failed | Processing failed. Try re-uploading. |
/api/videos/{video_id}/privacyChange who can access your video. Use the video's video_id field (the string ID, e.g. "1717000000_abc123").
curl -X PATCH "https://api.snapvid.org/api/videos/1717000000_abc123/privacy" \
-H "X-API-Key: sv_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"visibility": "password",
"password": "client-preview-2025",
"password_hint": "Ask your account manager"
}'
// Response
{
"success": true,
"message": "Video privacy updated to password",
"video_id": "1717000000_abc123",
"visibility": "password"
}| Value | Behavior |
|---|---|
public | Indexed by Google. Anyone with the URL can watch. |
unlisted | Not indexed. Only people with the link can watch. |
password | Requires password to watch. Great for client previews or paid content. |
private | Only visible to you in your dashboard. |
/api/videos/{id}/downloadEnable or disable the download button on your video player. Uses the numeric id field from the video object.
curl -X PATCH "https://api.snapvid.org/api/videos/456/download" \
-H "X-API-Key: sv_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "download_enabled": true }'
// Response
{
"success": true,
"message": "Download enabled for this video",
"video_id": "456",
"download_enabled": true
}Replace the auto-generated thumbnail with your own image. Requires Starter plan or higher.
/api/videos/{id}/thumbnail/presigned-urlUses the numeric id field from the video object.
curl -X POST "https://api.snapvid.org/api/videos/456/thumbnail/presigned-url" \
-H "X-API-Key: sv_live_your_key_here"
// Response
{
"uploadUrl": "https://s3.amazonaws.com/...",
"thumbnailUrl": "https://cdn.snapvid.org/uploads/.../custom_thumb.jpg",
"videoId": 456
}# Upload the image file (JPEG only)
curl -X PUT "UPLOAD_URL" \
-H "Content-Type: image/jpeg" \
--data-binary @thumbnail.jpg
# Then confirm the thumbnail update
curl -X PUT "https://api.snapvid.org/api/videos/456/thumbnail" \
-H "X-API-Key: sv_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "thumbnail_url": "THUMBNAIL_URL_FROM_STEP_1" }'/api/videos/{id}Permanently delete a video and all associated files. Uses the numeric id field. This action cannot be undone.
curl -X DELETE "https://api.snapvid.org/api/videos/456" \
-H "X-API-Key: sv_live_your_key_here"
// Response
{
"message": "Video deleted successfully"
}Warning: This permanently removes the video, streaming files, and thumbnail from storage. All existing links and embeds will stop working.
Access view counts, unique viewers, and top-performing videos. Analytics depth depends on your plan.
/api/analyticsGet aggregate analytics across all your videos.
curl -X GET "https://api.snapvid.org/api/analytics" \
-H "Authorization: Bearer YOUR_TOKEN"
// Response
{
"analytics_level": "advanced",
"summary": {
"total_views": 4821,
"unique_viewers": 1293,
"total_videos": 24,
"avg_views_per_video": 200.9,
"total_watch_time_seconds": 86420.5,
"avg_watch_time_seconds": 45.2,
"avg_completion_rate": 68.3,
"total_completions": 892
},
"top_videos": [
{
"video_id": "1717000000_abc123",
"slug": "how-to-make-jollof-rice-1717000000",
"title": "How to Make Jollof Rice",
"views": 342,
"status": "ready"
}
],
"views_trend": [
{ "date": "2025-04-28", "views": 45 },
{ "date": "2025-04-29", "views": 62 }
]
}Note: The analytics endpoint currently requires a Bearer session token (not API key). Analytics API key support is coming soon.
Embed SnapVid's adaptive streaming player on any website. The player handles quality switching automatically based on the viewer's network speed.
<iframe
src="https://snapvid.org/embed/{slug}"
width="100%"
height="100%"
style="aspect-ratio: 16/9; border: none;"
allow="autoplay; fullscreen; picture-in-picture"
allowfullscreen
></iframe>| Parameter | Default | Description |
|---|---|---|
autoplay | true | Auto-start video when player loads |
controls | true | Show playback controls |
loop | false | Loop video when it ends |
muted | false | Start muted (required for autoplay in most browsers) |
start | 0 | Start playback at this time (seconds) |
<iframe
src="https://snapvid.org/embed/product-demo-1717000000?autoplay=1&muted=1&loop=1"
width="100%"
height="100%"
style="aspect-ratio: 16/9; border: none;"
allow="autoplay; fullscreen; picture-in-picture"
allowfullscreen
></iframe>SnapVid works with WordPress, Wix, Squarespace, Webflow, and any platform that supports HTML embeds or REST APIs. No plugins required.
Add a Custom HTML block in the WordPress editor and paste your embed code. Works in both the Block Editor (Gutenberg) and Classic Editor.
Step 1 — Add a Custom HTML block
In WordPress Editor:
Click "+" → Search "Custom HTML" → Add blockStep 2 — Paste your SnapVid embed code
<iframe
src="https://snapvid.org/embed/your-video-slug"
width="100%"
height="100%"
style="aspect-ratio: 16/9; border: none;"
allow="autoplay; fullscreen; picture-in-picture"
allowfullscreen
></iframe>Call the SnapVid API from your WordPress theme or plugin using wp_remote_get. This lets you list videos, display them dynamically, or build custom video galleries.
List your videos (with pagination)
<?php
$page = 1;
$response = wp_remote_get(
'https://snapvid.org/api/my-videos?page=' . $page . '&page_size=20',
array(
'headers' => array(
'X-API-Key' => 'your_api_key_here',
),
)
);
if (!is_wp_error($response)) {
$data = json_decode(wp_remote_retrieve_body($response), true);
foreach ($data['videos'] as $video) {
echo '<div class="snapvid-video">';
echo '<h3>' . esc_html($video['title']) . '</h3>';
echo '<iframe src="https://snapvid.org/embed/' . esc_attr($video['slug']) . '"';
echo ' width="100%" style="aspect-ratio:16/9;border:none;"';
echo ' allow="autoplay;fullscreen" allowfullscreen></iframe>';
echo '</div>';
}
// Pagination info
// $data['total_pages'], $data['page'], $data['total']
}Upload a video via API
<?php
$file_path = '/path/to/video.mp4';
$response = wp_remote_post('https://snapvid.org/api/videos/upload', array(
'headers' => array(
'X-API-Key' => 'your_api_key_here',
),
'body' => array(
'title' => 'My Video Title',
'file' => new CURLFile($file_path, 'video/mp4', 'video.mp4'),
),
));
if (!is_wp_error($response)) {
$result = json_decode(wp_remote_retrieve_body($response), true);
// $result['slug'] — use this for the embed URL
}The iframe embed works anywhere you can add HTML. Here's where to paste it on popular platforms:
| Platform | How to embed |
|---|---|
| WordPress | Custom HTML block or Text tab in Classic Editor |
| Wix | Add Embed → Custom Element → Paste iframe |
| Squarespace | Code Block → Paste iframe |
| Webflow | Embed element → Paste iframe |
| Custom site | Paste iframe directly into your HTML |
| Code | Meaning |
|---|---|
200 | Request succeeded |
400 | Bad request. Check your request body or parameters. |
401 | Unauthorized. Your API key is missing or invalid. |
403 | Forbidden. Your plan doesn't include this feature, or you hit a limit. |
404 | Video not found, or you don't own it. |
429 | Rate limited. Wait and retry. |
500 | Server error. Contact support if this persists. |
// Simple error
{
"detail": "Video not found or you don't have permission"
}
// Plan limit error (403)
{
"detail": {
"error": "video_limit_exceeded",
"message": "Video limit reached. Upgrade your plan.",
"current_count": 50,
"plan": "starter",
"upgrade_url": "/pricing"
}
}
// Feature not available (403)
{
"detail": {
"error": "feature_not_available",
"feature": "custom_thumbnails",
"message": "Custom thumbnails require Starter plan or higher.",
"current_plan": "free"
}
}| Endpoint Category | Limit |
|---|---|
| Upload (presigned URL + complete) | 5 requests/minute |
| Video management (list, get, update, delete) | 60 requests/minute |
| Analytics | 30 requests/minute |
| Thumbnail upload | 10 requests/minute |
When rate limited, you'll receive a 429 response. Wait 60 seconds before retrying. Enterprise plans have custom rate limits.
We help teams integrate SnapVid into their applications. Reach out and we'll get you set up.