Video Assets Server API reference
One search API for free stock video: b-roll, backgrounds, nature, cities, space and archive films, with licence verdicts. Version 0.1.0, base URL https://video.shep.bot. Machine-readable:OpenAPI 3.1 JSON. Want to send requests from the browser? Open theinteractive API playground.
- Authentication: none on the public server. Self-hosted servers may require
Authorization: Bearer <key>orx-api-key. - Rate limits: 120 requests per minute per client, announced in
RateLimit-Policy/RateLimitheaders;429comes withRetry-After. See versioning & rate limits. - Errors: JSON
{ "error": "message" }with a 4xx/5xx status.
Search
Find clips across every source in one call.
/v1/searchSearch every sourceFans out to every enabled source in parallel (each with its own timeout), then merges and ranks. Words like 4k, 1080p, vertical, 9:16, 10s, under 30 seconds, 60fps, timelapse in q become filters (see filters in the response); explicit parameters win. A single length (10s) means at least that long. Unknown orientation, resolution, length or fps stay in the list, ranked below known matches, unless strict=true. A slow or failing source never fails the search: it shows up in providers with its status.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| q | query | string | Short query, written like an editor would. |
| category | query | string | Comma-separated categories; a parent includes its children. Top level: nature, city, people, aerial, space, science, tech, transport, food, background, overlay, greenscreen, archive, other; children like nature.ocean, city.skyline, space.launch, overlay.light. |
| style | query | string | Comma-separated styles (ranked first; filtered only with strict=true): timelapse, slow-motion, loop, animation, visualization, black-white. |
| orientation | query | string | Comma-separated: landscape, portrait, square. |
| min_resolution | query | string | Short side at least: 720, 1080, 1440, 2160, or hd / fhd / 4k. |
| min_duration | query | number | Minimum length in seconds. |
| max_duration | query | number | Maximum length in seconds. |
| min_fps | query | number | Minimum frame rate. |
| audio | query | boolean | Only clips with (true) or without (false) a sound track. |
| commercial | query | boolean | Only clips whose licence verdict is yes or yes-with-credit. |
| free | query | boolean | Only free clips. |
| downloadable | query | boolean | Only clips with direct file links. |
| strict | query | boolean | Drop clips whose orientation, resolution, length, fps or audio is unknown when that filter is set. |
| providers | query | string | Comma-separated source ids (see /v1/providers). |
| limit | query | integer | Max results (default 24). |
| offset | query | integer | Per-source offset for paging (e.g. 24 for page 2). |
Responses
200Ranked results, the filters in force and a per-source report.SearchResponseheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset400Invalid parameters or unknown source id.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset401API key required (self-hosted servers only).Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://video.shep.bot/v1/search?category=nature.ocean&style=timelapse&orientation=portrait&min_resolution=1080&providers=nasa%2Cwikimediacommons"Clips
Details, renditions, downloads and credits for one clip.
/v1/clips/{id}Clip details, renditions and watch URLFull metadata, the licence with its verdict and credit line, every file (master, renditions, preview, poster, captions) and the file a browser player should stream.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Clip id <provider>:<nativeId> (URL-encode it: ids can contain spaces and slashes). |
Responses
200The clip and its files.ClipDetailsheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset400Malformed id or unknown source.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset404Unknown clip.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy501The source has no detail pages here; openurlon the source site.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset502The source site failed.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
Example
curl "https://video.shep.bot/v1/clips/wikimediacommons:Ocean_in_Sommaroy.webm"/v1/clips/{id}/filesPick the right fileThe best file for a resolution and container (the master by default), or every file with all=true, with sizes and the licence.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Clip id <provider>:<nativeId> (URL-encode it: ids can contain spaces and slashes). |
| height | query | integer | Wanted resolution as the short side in pixels (720, 1080, 2160): the smallest file at or above it, else the biggest below. |
| format | query | string | Preferred container: mp4, webm, mov, ogv. |
| role | query | "original" | "rendition" | "preview" | "poster" | "captions" | Only files with this role: original, rendition, preview, poster, captions. |
| all | query | boolean | Every file, including posters and captions. |
Responses
200Selected files and total size.FileSelectionheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset404Unknown clip.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://video.shep.bot/v1/clips/wikimediacommons:Ocean_in_Sommaroy.webm/files"/v1/clips/{id}/downloadDownload (redirect to the source)Answers 302 to the chosen file on the source's CDN: the video never passes through this server. height picks a rendition (the smallest at or above it), format a container. The licence and credit line come back as X-License and X-Attribution headers; get the credits as files from /v1/clips/{id}/credits.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Clip id <provider>:<nativeId> (URL-encode it: ids can contain spaces and slashes). |
| height | query | integer | Wanted resolution as the short side in pixels (720, 1080, 2160): the smallest file at or above it, else the biggest below. |
| format | query | string | Preferred container: mp4, webm, mov, ogv. |
| role | query | "original" | "rendition" | "preview" | "poster" | "captions" | Only files with this role: original, rendition, preview, poster, captions. |
Responses
302Redirect to the file.headers: Location, X-License, X-Attribution, RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset404Unknown clip, or no file matches.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset409No direct download: get it from the source page.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl -L -O "https://video.shep.bot/v1/clips/wikimediacommons:Ocean_in_Sommaroy.webm/download"/v1/clips/{id}/creditsCredits for a clipATTRIBUTION.md (default), credits.json, or a zip holding both. No video inside.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Clip id <provider>:<nativeId> (URL-encode it: ids can contain spaces and slashes). |
| format | query | "md" | "json" | "zip" |
Responses
200The credits.stringheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset404Unknown clip.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://video.shep.bot/v1/clips/wikimediacommons:Ocean_in_Sommaroy.webm/credits"Sequences
Turn a shot list into a b-roll sequence in one call.
/v1/sequencesPlan a b-roll sequence from a shot listOne clip per shot, matching the target orientation, at least 1080p where possible, long enough for its shot, commercial-safe by default and directly downloadable; alternatives per shot. Returns the plan and the files to save: an OpenTimelineIO timeline, an ffmpeg script that renders the sequence, a Remotion clip list and the credits.
Responses
200The plan and its exports.SequenceResponseheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset400Invalid body.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl -X POST "https://video.shep.bot/v1/sequences" \
-H "content-type: application/json" -H "accept: application/json, text/event-stream" \
-d '{}'Sources
The video sites this server searches, what they hold, and how the server is used.
/v1/providersList sourcesEvery clip site with the categories it carries, pricing, licence, the filters it applies itself and whether files can be downloaded directly.
Responses
200Sources.objectheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://video.shep.bot/v1/providers"/v1/catalogCatalog censusHow many clips every source holds, counted once a day: listings per source, by top-level category, licence and the source's own categories, free counts, listings added in the last 30 days, and highlights such as the most downloaded clip. atLeast: true marks lower bounds (sources that cap their counts). Sources whose count failed today keep their last good numbers with stale. The same file is at /catalog.json; one point per day is in /catalog-history.json.
Responses
200Catalog census.Catalogheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset404The census has not been built on this server.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://video.shep.bot/v1/catalog"/v1/statsUsage statisticsAggregate usage of this server: searches by surface (web, API, MCP), downloads, MCP tool calls, the client families and categories searched most, and per-source health (success rate, p50/p95 latency). Counts come from Prometheus (source: prometheus, last 24 hours and 7 days) or, when it is unavailable, from this process since it started (source: process). No queries, IPs or user agents are exposed. Cached for 60 seconds.
Responses
200Usage statistics.Statsheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://video.shep.bot/v1/stats"MCP
Model Context Protocol endpoint for AI agents.
/mcpMCP endpoint (Streamable HTTP)Stateless Model Context Protocol endpoint for AI agents. Tools: search_videos, get_video, build_sequence, list_sources (and download_video on local installs, which saves files with their credits). Point any MCP client at this URL; see /docs/mcp for per-client setup.
Responses
200JSON-RPC 2.0 response.objectheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl -X POST "https://video.shep.bot/mcp" \
-H "content-type: application/json" -H "accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_videos","arguments":{"query":"ocean waves at sunset","orientation":"portrait","min_resolution":1080,"commercial_only":true}}}'System
Health and machine-readable descriptions.
/healthHealth checkResponses
200OKobject
Example
curl "https://video.shep.bot/health"/openapi.jsonThis OpenAPI documentResponses
200OpenAPI 3.1object
Example
curl "https://video.shep.bot/openapi.json"Schemas
Category
One of: nature, nature.ocean, nature.water, nature.sky, nature.forest, nature.mountain, nature.animals, city, city.street, city.skyline, people, people.work, people.lifestyle, people.sport, aerial, space, space.earth, space.launch, space.planets, science, tech, transport, food, background, background.abstract, overlay, overlay.light, overlay.particles, overlay.film, greenscreen, archive, archive.newsreel, archive.film, other
VideoStyle
One of: timelapse, slow-motion, loop, animation, visualization, black-white
Orientation
One of: landscape, portrait, square
CommercialVerdict
One of: yes, yes-with-credit, restricted, clearance-required, check-terms, no
NativeFilter
One of: categories, styles, orientation, resolution, duration, fps, audio, commercialOnly, freeOnly
License
| id * | string | SPDX id where one exists (CC0-1.0, CC-BY-4.0…), else LicenseRef-*. |
| name * | string | |
| url | string (uri) | |
| commercialUse | boolean | |
| attributionRequired | boolean | |
| shareAlike | boolean | |
| redistribution | boolean | May the clip itself be re-uploaded or passed on? |
| editorial | boolean | People, insignia or brands without releases: fine for news and documentary, not for ads. |
| assertedBy * | "source" | "site" | "uploader" | uploader = an unverified claim (verdict capped at check-terms). |
| verdict * | CommercialVerdict | |
| note | string |
Price
| free * | boolean | |
| amount | number | |
| currency | string |
Clip
| id * | string | <provider>:<nativeId> |
| provider * | string | |
| nativeId * | string | |
| title * | string | |
| description | string | |
| url * | string (uri) | The clip's page on the source site. |
| author | string | |
| authorUrl | string (uri) | |
| tags * | string[] | |
| category * | Category | |
| categoryEvidence | object | |
| styles | VideoStyle[] | |
| orientation | Orientation | |
| width | integer | Frame width of the best version. |
| height | integer | |
| fps | number | |
| durationSec | number | |
| hasAudio | boolean | |
| year | integer | Year the footage was made (archive films). |
| posterUrl | string (uri) | Still frame, on the source's CDN. |
| previewUrl | string (uri) | Small playable version (mp4/webm) on the source's CDN. |
| previewType | string | |
| formats | string[] | |
| license | License | |
| attribution | string | Ready-to-paste credit line when the licence asks for one. |
| price | Price | |
| requiresAccount | boolean | |
| downloadable * | boolean | |
| createdAt | string (date-time) | |
| popularity | number | |
| sameAs | string[] | |
| score | number |
ClipFile
| url * | string (uri) | |
| filename * | string | |
| format * | string | Container: mp4, webm, mov, ogv, mpeg… (Commons originals are WebM/Ogg, never MP4). |
| mime | string | |
| role * | "original" | "rendition" | "preview" | "poster" | "captions" | |
| width | integer | |
| height | integer | |
| fps | number | |
| codec | string | |
| sizeBytes | integer | |
| bitrate | integer | |
| requiresAuth | boolean |
ClipDetails
Clip & object
ClipFilters
| categories | Category[] | |
| styles | VideoStyle[] | |
| orientations | Orientation[] | |
| minResolution | integer | Short side in pixels. |
| duration | object | |
| minFps | number | |
| hasAudio | boolean | |
| commercialOnly | boolean | |
| freeOnly | boolean |
ProviderSearchReport
| provider * | string | |
| name * | string | |
| status * | "ok" | "error" | "timeout" | "skipped" | "link" | link = the source can only be searched on its own site: open searchUrl. |
| count * | integer | |
| total | integer | |
| searchUrl | string (uri) | |
| error | string | |
| filteredLocally | NativeFilter[] | |
| tookMs * | integer |
SearchResponse
| query * | string | The words searched after the filters were parsed out. |
| filters * | ClipFilters | |
| results * | Clip[] | |
| providers * | ProviderSearchReport[] |
Provider
| id * | string | |
| name * | string | |
| homepage * | string (uri) | |
| description * | string | |
| categories * | Category[] | Top-level categories the source carries. |
| access * | "api" | "static" | "scrape" | "link" | api official API; static a curated manifest filtered locally; scrape public pages; link deep links only (paid/partner API, no key yet, or terms that forbid aggregation). |
| pricing * | "free" | "freemium" | "paid" | |
| license | License | |
| apiKeyEnv | string | Environment variable holding the source's API key on a self-hosted server. |
| supportsDownload * | boolean | |
| nativeFilters | NativeFilter[] | Filters the source applies itself; the rest are applied locally. |
| enabled | boolean |
FileSelection
| id * | string | |
| license | License | |
| attribution | string | |
| totalBytes | integer | |
| files * | ClipFile[] |
SequenceRequest
| shots * | object | |
| orientation | Orientation | |
| width | integer | |
| height | integer | |
| fps | number | |
| totalDuration | number | Seconds, split over shots without their own length (default 4 s each). |
| commercialOnly | boolean | |
| providers | string[] | |
| alternatives | integer | |
| name | string |
SequenceShot
| index * | integer | |
| description * | string | |
| durationSec * | number | |
| inSec * | number | In-point in the source clip (skips title cards on long films). |
| clip | Clip | |
| file | ClipFile | |
| alternatives * | Clip[] | |
| note | string |
SequenceResponse
| plan * | object | |
| exports * | object | File contents, ready to save: an OpenTimelineIO timeline, an ffmpeg render script, a Remotion clip list and the credits. Media URLs point at the sources. |
CountWithBound
| count * | integer | |
| atLeast | boolean | The count is a lower bound. |
SourceCensus
| id * | string | |
| name * | string | |
| homepage * | string (uri) | |
| license | string | The source's single licence id, when uniform. |
| pricing | "free" | "freemium" | "paid" | |
| supportsDownload | boolean | |
| total * | integer | Listings on the source (free and paid). |
| atLeast | boolean | |
| free | integer | |
| byCategory * | object | Listings per top-level category; each listing counts once. |
| byLicense | object | |
| categories | object | The source's own categories or tags (may overlap). |
| unit | "clips" | "packs" | |
| addedLast30Days | integer | |
| downloads | integer | Total downloads, when the source publishes them. |
| highlights | object[] | |
| method * | string | How the source was counted. |
| countedAt * | string (date-time) | |
| stale | object |
Catalog
| countedAt * | string (date-time) | |
| totals * | object | |
| byCategory * | object | Listings per top-level category across sources. |
| byLicense * | object | |
| sources * | SourceCensus[] | |
| linked | object[] |
UsageWindow
| key * | string | 24h, 7d, or process (since the last restart). |
| label * | string | |
| searches * | integer | |
| searchesWithResults * | integer | |
| bySurface * | object | |
| clipViews * | integer | |
| downloads * | integer | |
| toolCalls * | integer | MCP tool calls. |
| pageViews * | integer | Website pages served. |
Ranked
| name * | string | |
| count * | integer |
ProviderHealth
| provider * | string | |
| requests * | integer | Searches that reached the source. |
| ok * | integer | |
| errors * | integer | |
| timeouts * | integer | |
| okRate * | number | null | |
| p50Ms * | integer | null | |
| p95Ms * | integer | null |
Stats
| generatedAt * | string (date-time) | |
| source * | "prometheus" | "process" | |
| since | string (date-time) | Start of counting for source: process. |
| windows * | UsageWindow[] | |
| breakdownLabel * | string | Period covered by clients, tools and assetTypes. |
| clients * | Ranked[] | Searches by client family (claude-code, cursor, browser, curl…). |
| tools * | Ranked[] | MCP tool calls by tool. |
| assetTypes * | Ranked[] | Searches by category filter (any = no filter). |
| providers * | ProviderHealth[] | Per-source health over the last 24 hours. |
| catalog * | object |
Error
| error * | string | |
| url | string (uri) | The clip's page on the source, when the file must be fetched there. |
| requiresAccount | boolean | |
| retryAfter | integer |
AI agent? This page is also available as markdown.