Skip to content

Developer docs

Search travel footage from your product.

Two ways in, one library. Give an AI model the MCP server and it searches by itself, or call the REST API from your backend.

Before you start

There's no key or sign-in during early access, so both addresses work straight away. Every search is read by AI before it runs, so it takes two to five seconds and understands places, kinds of shot and what to leave out, in any language.

MCP server
https://api.studio.tbo.com/mcp
REST API · search
https://api.studio.tbo.com/api/v1/search
Try a search in the playground first

MCP server

The MCP server gives an AI model two tools. The model reads their descriptions when it connects and decides by itself when to search. It speaks Streamable HTTP without sessions, so every call is a single request.

Tools

library

What the library covers

Lists the countries, the places with the most footage and the common activities, with how many videos and hours the library holds. Assistants call it when they aren't sure a place is covered.

Takes no input.

search

Search travel footage

Finds footage from a plain description, best match first. It reads places, kinds of shot, time of day, what to leave out and how many results you want from the words themselves.

querytext, required
What to find, in any language. “Aerial shots of the Maasai Mara at sunset, no text on screen”.
limitnumber, optional
How many results to return, from 1 to 25. Ten if left out.

Both tools only read. They say so in their annotations, so assistants run them without asking the person each time.

Connect from code

Most model providers can use an MCP server directly. The lit lines are the ones that connect the model to the library.

Claude API

Claude connects to the server for you. Name the server once, and switch its tools on with a matching toolset.

TypeScript · @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk"; const TBO_MCP = "https://api.studio.tbo.com/mcp";const client = new Anthropic(); const response = await client.beta.messages.create({  model: "claude-opus-5-5",  max_tokens: 4096,  betas: ["mcp-client-2025-11-20"],  mcp_servers: [{ type: "url", url: TBO_MCP, name: "tbo-studios" }],  tools: [{ type: "mcp_toolset", mcp_server_name: "tbo-studios" }],  messages: [{ role: "user", content: "Show me a morning in the Masai Mara" }],});

OpenAI Responses API

OpenAI's servers call ours. Read-only tools are safe to run without asking for approval each time.

TypeScript · openai
import OpenAI from "openai"; const TBO_MCP = "https://api.studio.tbo.com/mcp";const client = new OpenAI(); const response = await client.responses.create({  model: "gpt-5",  tools: [{    type: "mcp", server_label: "tbo-studios", server_url: TBO_MCP, require_approval: "never",  }],  input: "Show me a morning in the Masai Mara",}); console.log(response.output_text);

Gemini, or any model, with the MCP library

Your code connects to the server and hands its tools to the model. This runs where your code runs, so it also works with a server on your own computer.

TypeScript · @google/genai + @modelcontextprotocol/sdk
import { GoogleGenAI, mcpToTool } from "@google/genai";import { Client } from "@modelcontextprotocol/sdk/client/index.js";import {  StreamableHTTPClientTransport,} from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const TBO_MCP = "https://api.studio.tbo.com/mcp"; const mcp = new Client({ name: "my-chatbot", version: "1.0.0" });await mcp.connect(new StreamableHTTPClientTransport(new URL(TBO_MCP))); const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });const response = await ai.models.generateContent({  model: "gemini-3.6-flash",  contents: "Show me a morning in the Masai Mara",  config: { tools: [mcpToTool(mcp)] },}); console.log(response.text);

Plain HTTP, from any language

Every call is one POST with a small JSON body. There's no session to open first, so a single request is enough.

Terminal · curl
curl -s https://api.studio.tbo.com/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",
                  "arguments": {"query": "elephants at a waterhole", "limit": 3}}}'
Adding it to Claude, ChatGPT, Cursor or VS Code instead

What search returns

Every answer comes twice: as text the model reads and repeats, and as structured data for your code. Each result is a chapter of a video, with the scenes in it that match. This is a real answer to “lions at sunrise”, shortened to one result.

What the model reads
Search: "lions at sunrise"
Understood as: Looking for lions at sunrise. Filters: golden hour.
Found 2 matching chapters. Showing 2, best first.

1. Wildlife safari at Mara Porini Camp
   Mara Porini Camp, Narok, Kenya · 50 s · from "MARA PORINI"
   Footage showcases a variety of African wildlife including hyenas, wildebeest, warthogs, jackals, vultures, zebras, giraffes, elephants, and lions. Tourists enjoy a game drive in a safari vehicle, spotting and photographing animals across the open savanna at sunset.
   Video: https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=0,50.1
   Thumbnail: https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/thumbs/0015.jpg
   Scenes:
   - 0:24 to 0:27 (wide): A male lion with a dark mane walks along a rocky riverbank at golden hour, with rushing water and a vehicle roof edge visible.
     Video: https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=24.2,27.2 · Thumbnail: https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/thumbs/0015.jpg
Structured data
{
  "query": "lions at sunrise",
  "understoodAs": "Looking for lions at sunrise. Filters: golden hour.",
  "status": "found",
  "total": 2,
  "notices": [],
  "results": [
    {
      "id": "chp_01M75H7ZDRJZZ7H4HG5V9M16RX_000",
      "title": "Wildlife safari at Mara Porini Camp",
      "url": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=0,50.1",
      "description": "Footage showcases a variety of African wildlife…",
      "place": "Mara Porini Camp",
      "state": "Narok",
      "country": "Kenya",
      "countryCode": "KE",
      "locationMatch": "certain",
      "startSec": 0,
      "endSec": 50.4,
      "durationSec": 50.4,
      "thumbnailUrl": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/thumbs/0015.jpg",
      "videoUrl": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=0,50.1",
      "sourceVideo": { "id": "ast_01M75H7ZDRJZZ7H4HG5V9M16RX", "name": "MARA PORINI" },
      "shareWithoutTextOrLogo": 0.93,
      "score": 0.759,
      "scenes": [
        {
          "id": "scn_01M75H7ZDRJZZ7H4HG5V9M16RX_0014",
          "description": "A male lion with a dark mane walks along a rocky riverbank at golden hour, with rushing water and a vehicle roof edge visible.",
          "startSec": 24.2,
          "endSec": 27.5,
          "durationSec": 3.3,
          "thumbnailUrl": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/thumbs/0015.jpg",
          "videoUrl": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=24.2,27.2",
          "shotType": "wide",
          "timeOfDay": "golden_hour",
          "people": null,
          "textOrLogoOnScreen": false,
          "matchesSearch": true
        }
      ]
    }
  ],
  "closest": [],
  "closestKind": null
}
Each result
title, descriptionWhat the chapter shows, written from the footage itself.
place, state, countryWhere it was filmed, when that's on record.
locationMatchWhen you named a place: certain, right country with the state unknown, or location unknown.
startSec, endSec, durationSecWhere the chapter sits in its source video, and how long it runs.
thumbnailUrlA still from the chapter.
videoUrlA link that plays only this chapter of the 480p preview.
sourceVideoThe id and name of the video it comes from.
shareWithoutTextOrLogoHow much of the chapter is free of added titles and logos, from 0 to 1.
scenesUp to three scenes that match, each with its own description, times, thumbnail, video link, shot type, time of day and how many people are in it.
Around the results
understoodAsHow the search was read, so the assistant can confirm it with you.
status, totalWhether anything matched, and how many chapters did in all.
noticesAnything worth passing on, such as a filter that was dropped to find something.
closestOnly when nothing matched: the nearest footage the library has. It's never a match, and assistants are told so.
  • They play the right moment

    A scene link opens the preview at the scene's first second and pauses at its last, in any browser.

  • They don't expire

    Each link asks our server for a fresh copy when it's opened, so a link in an old chat still works next month.

  • They're previews

    Links open the 480p copy of the footage. The original files are never linked.

  • Chats show them as links

    Claude and ChatGPT don't draw pictures from tool results into the chat, so thumbnails arrive as links you can open.

REST API

One endpoint searches the library. Send a POST with JSON, and get back ranked chapters of video with the scenes that match. Use it from a backend, a website or a data pipeline, wherever no AI model is choosing the searches for you.

Request

POST /api/v1/search
curl -s https://api.studio.tbo.com/api/v1/search \
  -H "Content-Type: application/json" \
  -d '{"text": "lion walking in the Maasai Mara", "limit": 1}'
Body
textWhat to find, in plain words and any language. Places, kinds of shot, time of day and what to leave out are read from the words.
limitHow many results a page holds, from 1 to 50. Twelve if left out.
offsetHow many results to skip, for the next page.
previousThe query object of the last answer, sent with a follow-up such as “only aerial shots”. The follow-up then adjusts that search instead of starting a new one.

Response

A real answer, shortened to one result and the fields most apps use. Stills and previews come back as paths, such as /files/media/…, so put the API address in front of them. To play one scene of a preview, add its times in seconds to the link, as in #t=102.2,105.

Response, shortened
{
  "searchId": "srch_01M77MJWV3NQNPR77HXNNVYFCR",
  "status": "ok",
  "total": 38,
  "query": {
    "subject": "lion walking",
    "countries": [{ "code": "KE", "name": "Kenya" }],
    "places": ["Maasai Mara"],
    "interpretation": "Looking for lion walking in the Maasai Mara. Only from Kenya."
  },
  "notices": [],
  "results": [
    {
      "id": "chp_01M75H48116D2AXQ7YV6T9Y46F_002",
      "title": "Sounds of the Wild",
      "summary": "Observing lions, leopards, and evening campfires under the starry African sky.",
      "startMs": 72683,
      "endMs": 105041,
      "place": "Maasai Mara",
      "state": "Narok",
      "country": "Kenya",
      "locationMatch": "certain",
      "cleanShare": 1,
      "thumbnailUrl": "/files/media/ast_01M75H48116D2AXQ7YV6T9Y46F/thumbs/0061.jpg",
      "asset": {
        "id": "ast_01M75H48116D2AXQ7YV6T9Y46F",
        "name": "AFRICA ECO WILDERNESS",
        "proxyUrl": "/files/media/ast_01M75H48116D2AXQ7YV6T9Y46F/proxy.mp4"
      },
      "score": { "meaning": 0.806, "words": 0.04, "name": 0.06, "quality": 0.029, "total": 0.935 },
      "scenes": [
        {
          "id": "scn_01M75H48116D2AXQ7YV6T9Y46F_0060",
          "startMs": 102248,
          "endMs": 105041,
          "description": "A large male lion walks directly toward the camera along a grassy dirt path during the early morning light.",
          "thumbnailUrl": "/files/media/ast_01M75H48116D2AXQ7YV6T9Y46F/thumbs/0061.jpg",
          "shotType": "medium",
          "timeOfDay": "day",
          "people": "none",
          "clean": true,
          "matches": true
        }
      ],
      "moreScenes": 15
    }
  ],
  "closest": [],
  "tookMs": 1682
}
Fields
status, totalok when something matched, empty when nothing did, and how many chapters matched in all.
queryHow the text was understood: the subject, countries, named places and filters. interpretation says it in one sentence.
noticesThings worth showing the person, such as a filter that was dropped to find something.
results[]Chapters of video, best first. A chapter is a stretch of one video about one place or subject.
title, summaryWhat the chapter shows, written from the footage itself.
startMs, endMsWhere the chapter sits in its source video, in milliseconds.
place, state, countryWhere it was filmed, when that's on record. locationMatch says how sure that is.
cleanShareHow much of the chapter is free of added titles and logos, from 0 to 1.
thumbnailUrl, asset.proxyUrlA still and the 480p preview of the whole video. Both are paths: put the API address in front of them.
scenes[]The chapter's scenes that pass the search, best first, each with its times, description, still, shot type, time of day and whether people are in it. matches is true when the scene itself matches.
closestOnly when nothing matched: the nearest footage the library has. It's never a match.

Good to know

Do I need an account or a key?
Not during early access. The MCP server and the API are open while sign-in is built. Assistants will be asked to sign in once when keys arrive.
What does the library cover?
Ask your assistant “what does the TBO Studios library cover?”. The library tool answers from the live library, so the list is always current.
How fast is a search?
Usually two to five seconds, because each search is read by AI before it runs. Assistants often run two or three searches for one request.
What happens when nothing matches?
The answer says so plainly. When the library has something close, it's listed separately and marked as not a match.
Can I get the full-quality files?
Not through these links, which play 480p previews. Licensed downloads come with accounts. Tell us what you need through early access.
Who wrote the descriptions?
AI, from watching the footage. They're usually right about what's in the picture, and they can be wrong about names and places.
Are searches recorded?
Yes. The words of every search are kept so we can see what people look for and what the library is missing. Please don't put personal details in a search.