> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.twelvelabs.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.twelvelabs.io/_mcp/server.

# Search a knowledge store

> Upload videos and images, build a knowledge store, and search it with a natural-language query.

> **Research preview**
>
> Jockey is in research preview. Availability, limits, and API surface may change before general availability.

This guide shows how to upload videos and images, build a knowledge store, and search it with a natural-language query. The search returns matching video clips and images ranked by relevance.

# Key concepts

This section explains the key concepts and terminology used in this guide:

* **Asset**: Your uploaded content. Once created, you can reference the same asset across multiple operations without uploading the file again.
* **Knowledge store**: A persistent store of your videos and images plus the understanding the platform derives from them - spatiotemporal context, a typed ontology, and embeddings - that together enable corpus-level reasoning.
* **Knowledge store item**: An asset added to a knowledge store. The platform processes each item asynchronously. When the item reaches the `ready` status, you can use it in downstream tasks.

# Workflow

Upload your videos and images as assets, then create a knowledge store. Add the assets to the knowledge store. The platform indexes the content asynchronously. When the items reach the `ready` status, search the knowledge store with a natural-language query.

# Prerequisites

* To use the platform, you need an API key:

  If you don't have an account, [sign up](https://playground.twelvelabs.io/) for a free account.

  Go to the [API Keys](https://playground.twelvelabs.io/dashboard/api-keys) page.

  If you need to create a new key, select the **Create API Key** button. Enter a name and set the expiration period. The default is 12 months.

  Select the **Copy** icon next to your key to copy it to your clipboard.

* Depending on the programming language you are using, install the TwelveLabs SDK by entering one of the following commands:

  **`Python`**

  ```shell Python
  pip install --upgrade twelvelabs
  ```

  **`Node.js`**

  ```shell Node.js
  yarn add twelvelabs-js@latest # or npm install twelvelabs-js@latest
  ```

* Upload limits: Public video URLs up to 4 GB, local videos up to 200 MB, or images up to 32 MB. For local files up to 10 GB, see the [Upload content](/v1.3/agents/guides/upload-content) page.

# Starter code

Copy and paste the code below, replacing the placeholders surrounded by `<>` with your values.

**`Python`**

```python Python maxlines=38
from twelvelabs import TwelveLabs
import time

# Step 1: Initialize the client
client = TwelveLabs(api_key="<YOUR_API_KEY>")

# Step 2: Upload a video or an image
asset = client.assets.create(method="url", url="<YOUR_MEDIA_URL>")  # Use direct links to raw media files. Video hosting platforms and cloud storage sharing links are not supported
# Or use method="direct" and file=open("<YOUR_FILE_PATH>", "rb") to upload a local file up to 200 MB
print(f"Asset created: {asset.id}")

# Step 3: Check the status of the asset
while True:
    status = client.assets.retrieve(asset_id=asset.id).status
    if status == "ready":
        break
    elif status == "failed":
        raise Exception("Asset processing failed")
    print(f"Status: {status}, waiting...")
    time.sleep(5)
print("Asset ready")

# Step 4: Create a knowledge store
store = client.knowledge_stores.create(name="<YOUR_KNOWLEDGE_STORE_NAME>")
print(f"Knowledge store created: {store.id}")

# Step 5: Add the asset to the knowledge store
item = client.knowledge_store_items.create(
    knowledge_store_id=store.id,
    asset_id=asset.id,
    # asset_type="image",  # Uncomment if your asset is an image (the default is video)
)
print(f"Item added: {item.id}")

# Step 6: Check the status of the knowledge store item
while True:
    status = client.knowledge_store_items.retrieve(
        knowledge_store_id=store.id, item_id=item.id
    ).status
    if status == "ready":
        break
    elif status == "failed":
        raise Exception("Indexing failed")
    print(f"Status: {status}, waiting...")
    time.sleep(10)
print("Indexing complete")

# Step 7: Search the knowledge store
result = client.knowledge_stores.search(
    knowledge_store_id=store.id,
    query={"text": "<YOUR_QUERY>"},
    search_options={"video": {"modalities": ["visual", "audio"]}},
)
for hit in result.data:
    if hit.asset_type == "video":
        clip = hit.matches[0]
        print(f"Rank {hit.rank}: video {hit.item_id}  {clip.start_sec}s-{clip.end_sec}s")
    elif hit.asset_type == "image":
        print(f"Rank {hit.rank}: image {hit.item_id}")
```

**`Node.js`**

```javascript Node.js maxlines=38
import { TwelveLabs } from "twelvelabs-js";
// Uncomment the next line if uploading a local file
// import fs from "fs";

// Step 1: Initialize the client
const client = new TwelveLabs({ apiKey: "<YOUR_API_KEY>" });

// Step 2: Upload a video or an image
const asset = await client.assets.create({ method: "url", url: "<YOUR_MEDIA_URL>" }); // Use direct links to raw media files. Video hosting platforms and cloud storage sharing links are not supported
// Or use method: "direct" and file: fs.createReadStream("<YOUR_FILE_PATH>") to upload a local file up to 200 MB
console.log(`Asset created: ${asset.id}`);

// Step 3: Check the status of the asset
while (true) {
  const { status } = await client.assets.retrieve(asset.id);
  if (status === "ready") break;
  if (status === "failed") throw new Error("Asset processing failed");
  console.log(`Status: ${status}, waiting...`);
  await new Promise((r) => setTimeout(r, 5000));
}
console.log("Asset ready");

// Step 4: Create a knowledge store
const store = await client.knowledgeStores.create({ name: "<YOUR_KNOWLEDGE_STORE_NAME>" });
console.log(`Knowledge store created: ${store.id}`);

// Step 5: Add the asset to the knowledge store
const item = await client.knowledgeStoreItems.create(store.id, {
  assetId: asset.id,
  // assetType: "image", // Uncomment if your asset is an image (the default is video)
});
console.log(`Item added: ${item.id}`);

// Step 6: Check the status of the knowledge store item
while (true) {
  const { status } = await client.knowledgeStoreItems.retrieve(store.id, item.id);
  if (status === "ready") break;
  if (status === "failed") throw new Error("Indexing failed");
  console.log(`Status: ${status}, waiting...`);
  await new Promise((r) => setTimeout(r, 10000));
}
console.log("Indexing complete");

// Step 7: Search the knowledge store
const result = await client.knowledgeStores.search(store.id, {
  query: { text: "<YOUR_QUERY>" },
  searchOptions: { video: { modalities: ["visual", "audio"] } },
});
for (const hit of result.data ?? []) {
  if (hit.assetType === "video") {
    const clip = hit.matches[0];
    console.log(`Rank ${hit.rank}: video ${hit.itemId}  ${clip.startSec}s-${clip.endSec}s`);
  } else if (hit.assetType === "image") {
    console.log(`Rank ${hit.rank}: image ${hit.itemId}`);
  }
}
```

# Code explanation

#### Import the SDK and initialize the client

Create a client instance with your API key to interact with the platform.

#### Upload a video or an image

Upload a video or an image using a publicly accessible URL to create an asset. The same call handles both.

#### Check the status of the asset

Asset processing is asynchronous. Poll the status of the asset until it is `ready` before you use it.

#### Create a knowledge store

Create a knowledge store. You add the asset to it in the next step, and the platform indexes it.

#### Add the asset to the knowledge store

Add the asset to the knowledge store. This creates a knowledge store item that the platform indexes. Set the `asset_type` parameter to `image` when the asset is an image. It defaults to `video`.

#### Check the status of the knowledge store item

Check the status of the knowledge store item until it reaches the `ready` status. Indexing runs asynchronously and usually takes longer than the asset processing in step 3.

#### Search the knowledge store

Search the knowledge store with a natural-language query. The `data` array in the response contains the matches, ranked by relevance. The `asset_type` field identifies each match: a video match includes a `matches` array of clips with a time range, and an image match has no clip. This example prints each match to the standard output.

# Next steps

* [Search a knowledge store](/v1.3/agents/guides/search-a-knowledge-store) - the complete guide: filter results, group clips, and page through large result sets