> 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.

# Migrate from Pegasus 1.2 to Pegasus 1.5

> Migrate your applications from Pegasus 1.2 to Pegasus 1.5.

This guide shows how to migrate your application to Pegasus 1.5. It focuses on SDK migrations, but it also includes cURL examples for steps where the request shape changes.

TwelveLabs removed Pegasus 1.2 on August 18, 2026. The platform now rejects any request that specifies Pegasus 1.2, and uses Pegasus 1.5 by default when you omit the `model_name` parameter.

To use Pegasus 1.5, update your SDK to the latest version, or update your REST API calls as shown in the cURL examples. If you use structured responses, you may also need to update your code. See the [Update your structured responses](#update-your-structured-responses) section for details.

# Migration steps

#### Upgrade your SDK

#### Python

Install the latest version of the Python SDK.

**`Python`**

```bash Python
pip install --upgrade twelvelabs
```

#### Node.js

Install the latest version of the Node.js SDK.

**`Node.js`**

```bash Node.js
npm install twelvelabs-js@latest
```

#### Update how you provide the video

Skip this step if you already provide your video as an asset, URL, or base64 string.

If you use sync analysis, upload your video as an asset and provide the unique identifier of that asset instead. If you use async analysis, no changes are needed.

Pegasus 1.5 doesn't accept the unique identifier of a video you uploaded with a video indexing task. For a step-by-step guide, see [Analyze videos](/v1.3/docs/guides/analyze-videos).

#### Python

Replace the `video_id` parameter with a `VideoContext_AssetId` object passed to the `video` parameter.

**Before**:

**`Python`**

```python Python maxLines=12
result = client.analyze(
    video_id="<YOUR_VIDEO_ID>",
    prompt="<YOUR_PROMPT>",
)
```

**After**:

**`Python`**

```python Python maxLines=12
from twelvelabs.types import VideoContext_AssetId

result = client.analyze(
    video=VideoContext_AssetId(asset_id="<YOUR_ASSET_ID>"),
    prompt="<YOUR_PROMPT>",
)
```

#### Node.js

Replace the `videoId` parameter with a `video` object. Set the `type` field to `"asset_id"` and the `assetId` field to the unique identifier of your asset.

**Before**:

**`Node.js`**

```javascript Node.js maxLines=12
const result = await client.analyze({
  videoId: "<YOUR_VIDEO_ID>",
  prompt: "<YOUR_PROMPT>",
});
```

**After**:

**`Node.js`**

```javascript Node.js maxLines=12
const result = await client.analyze({
  video: { type: "asset_id", assetId: "<YOUR_ASSET_ID>" },
  prompt: "<YOUR_PROMPT>",
});
```

#### cURL

Replace the `video_id` field with a `video` object. Set the `type` field to `"asset_id"` and the `asset_id` field to the unique identifier of your asset.

**Before**:

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/analyze \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "video_id": "<YOUR_VIDEO_ID>",
    "prompt": "<YOUR_PROMPT>"
  }'
```

**After**:

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/analyze \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "video": { "type": "asset_id", "asset_id": "<YOUR_ASSET_ID>" },
    "prompt": "<YOUR_PROMPT>"
  }'
```

If you uploaded your video with the [Create a video indexing task](/v1.3/api-reference/upload-content/tasks/create) method, call the [Retrieve video information](/v1.3/api-reference/videos/retrieve) method. The response includes the unique identifier of your asset.

#### Update your structured responses

Skip this step if you do not use structured responses.

Structured responses now use separate types for synchronous and asynchronous analysis.

The examples below show the change for synchronous analysis. For asynchronous analysis, make the same change with the asynchronous type.

#### Python

Replace the `ResponseFormat` type with the `SyncResponseFormat` type.

**Before**:

**`Python`**

```python Python maxLines=12
from twelvelabs.types import ResponseFormat

result = client.analyze(
    video=VideoContext_AssetId(asset_id="<YOUR_ASSET_ID>"),
    prompt="<YOUR_PROMPT>",
    response_format=ResponseFormat(
        type="json_schema",
        json_schema={"type": "object", "properties": {"summary": {"type": "string"}}},
    ),
)
```

**After**:

**`Python`**

```python Python maxLines=12
from twelvelabs.types import SyncResponseFormat

result = client.analyze(
    video=VideoContext_AssetId(asset_id="<YOUR_ASSET_ID>"),
    prompt="<YOUR_PROMPT>",
    response_format=SyncResponseFormat(
        type="json_schema",
        json_schema={"type": "object", "properties": {"summary": {"type": "string"}}},
    ),
)
```

#### Node.js

If your TypeScript code names the `TwelvelabsApi.ResponseFormat` type explicitly, for example in a typed variable, function parameter, or type alias, replace it with the `TwelvelabsApi.SyncResponseFormat` type.
Inline `responseFormat` objects do not change.

**Before**:

**`Node.js`**

```javascript Node.js maxLines=12
import { TwelvelabsApi } from "twelvelabs-js";

const responseFormat: TwelvelabsApi.ResponseFormat = {
  type: "json_schema",
  jsonSchema: { type: "object", properties: { summary: { type: "string" } } },
};
```

**After**:

**`Node.js`**

```javascript Node.js maxLines=12
import { TwelvelabsApi } from "twelvelabs-js";

const responseFormat: TwelvelabsApi.SyncResponseFormat = {
  type: "json_schema",
  jsonSchema: { type: "object", properties: { summary: { type: "string" } } },
};
```

#### Update your analysis calls

These changes apply to both sync and async methods. The examples below show how to update your code for sync analysis. For async analysis, make similar changes.

#### Python

* Set the `model_name` parameter to `"pegasus1.5"`.
* Replace the `prompt` parameter with `prompt_v_2`. This parameter is now an object. Set the `input_text` field to your prompt text.

> **Note**
>
> The `prompt` parameter remains available, but TwelveLabs recommends the `prompt_v_2` parameter instead.

**Before**:

**`Python`**

```python Python maxLines=12
result = client.analyze(
    video=VideoContext_AssetId(asset_id="<YOUR_ASSET_ID>"),
    prompt="<YOUR_PROMPT>",
)
```

**After**:

**`Python`**

```python Python maxLines=12
from twelvelabs.types import AnalyzePromptV2

result = client.analyze(
    model_name="pegasus1.5",
    video=VideoContext_AssetId(asset_id="<YOUR_ASSET_ID>"),
    prompt_v_2=AnalyzePromptV2(
        input_text="<YOUR_PROMPT>",
    ),
)
```

#### Node.js

* Set the `modelName` parameter to `"pegasus1.5"`.
* Replace the `prompt` parameter with `promptV2`. This parameter is now an object. Set the `inputText` field to your prompt text.

> **Note**
>
> The `prompt` parameter remains available, but TwelveLabs recommends the `promptV2` parameter instead.

**Before**:

**`Node.js`**

```javascript Node.js maxLines=12
const result = await client.analyze({
  video: { type: "asset_id", assetId: "<YOUR_ASSET_ID>" },
  prompt: "<YOUR_PROMPT>",
});
```

**After**:

**`Node.js`**

```javascript Node.js maxLines=12
const result = await client.analyze({
  modelName: "pegasus1.5",
  video: { type: "asset_id", assetId: "<YOUR_ASSET_ID>" },
  promptV2: {
    inputText: "<YOUR_PROMPT>",
  },
});
```

#### cURL

* Set the `model_name` parameter to `"pegasus1.5"`.
* Replace the `prompt` parameter with `prompt_v2`. This parameter is now an object. Set the `input_text` field to your prompt text.

> **Note**
>
> The `prompt` parameter remains available, but TwelveLabs recommends the `prompt_v2` parameter instead.

**Before**:

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/analyze \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "video": { "type": "asset_id", "asset_id": "<YOUR_ASSET_ID>" },
    "prompt": "<YOUR_PROMPT>"
  }'
```

**After**:

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/analyze \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "pegasus1.5",
    "video": { "type": "asset_id", "asset_id": "<YOUR_ASSET_ID>" },
    "prompt_v2": {
      "input_text": "<YOUR_PROMPT>"
    }
  }'
```

> **Note**
>
> Pegasus 1.5 supports responses up to 98,304 tokens, compared to 4,096 for Pegasus 1.2. The input and response must fit within the [context window](/v1.3/docs/concepts/models/pegasus#context-window). If your application validates or caps the maximum response length, update the limit.

#### Use new Pegasus 1.5 features

The following examples show each new capability.

**Video segmentation**

Pegasus 1.5 transforms raw videos into structured, timestamped data. Define the types of segments you want to detect and the custom fields you want to extract. Video segmentation requires the asynchronous analysis endpoint.

#### Python

The following example detects scene changes and extracts a sentiment field for each segment:

**`Python`**

```python Python maxLines=12
from twelvelabs.types import (
    VideoContext_Url,
    AsyncResponseFormat,
    SegmentDefinition,
    SegmentField,
)

task = client.analyze_async.tasks.create(
    model_name="pegasus1.5",
    video=VideoContext_Url(url="<YOUR_VIDEO_URL>"),
    analysis_mode="time_based_metadata",
    response_format=AsyncResponseFormat(
        type="segment_definitions",
        segment_definitions=[
            SegmentDefinition(
                id="scene",
                description="A distinct scene or setting change in the video",
                fields=[
                    SegmentField(
                        name="sentiment",
                        type="string",
                        description="The emotional tone of this segment",
                        enum=["positive", "negative", "neutral"],
                    ),
                ],
            ),
        ],
    ),
)
```

You can also restrict segment extraction to specific time windows by adding time ranges to individual segment definitions. The following example limits scene detection to two windows (0-30s and 60-90s):

**`Python`**

```python Python maxLines=12
from twelvelabs.types import (
    VideoContext_Url,
    AsyncResponseFormat,
    SegmentDefinition,
    AnalyzeTimeRange,
)

task = client.analyze_async.tasks.create(
    model_name="pegasus1.5",
    video=VideoContext_Url(url="<YOUR_VIDEO_URL>"),
    analysis_mode="time_based_metadata",
    response_format=AsyncResponseFormat(
        type="segment_definitions",
        segment_definitions=[
            SegmentDefinition(
                id="scene",
                description="A distinct scene or setting change",
                time_ranges=[
                    AnalyzeTimeRange(start_time=0.0, end_time=30.0),
                    AnalyzeTimeRange(start_time=60.0, end_time=90.0),
                ],
            ),
        ],
    ),
)
```

#### Node.js

The following example detects scene changes and extracts a sentiment field for each segment:

**`Node.js`**

```javascript Node.js maxLines=12
const { taskId } = await client.analyzeAsync.tasks.create({
  modelName: "pegasus1.5",
  video: { type: "url", url: "<YOUR_VIDEO_URL>" },
  analysisMode: "time_based_metadata",
  responseFormat: {
    type: "segment_definitions",
    segmentDefinitions: [
      {
        id: "scene",
        description: "A distinct scene or setting change in the video",
        fields: [
          {
            name: "sentiment",
            type: "string",
            description: "The emotional tone of this segment",
            enum: ["positive", "negative", "neutral"],
          },
        ],
      },
    ],
  },
});
```

You can also restrict segment extraction to specific time windows by adding time ranges to individual segment definitions. The following example limits scene detection to two windows (0-30s and 60-90s):

**`Node.js`**

```javascript Node.js maxLines=12
const { taskId } = await client.analyzeAsync.tasks.create({
  modelName: "pegasus1.5",
  video: { type: "url", url: "<YOUR_VIDEO_URL>" },
  analysisMode: "time_based_metadata",
  responseFormat: {
    type: "segment_definitions",
    segmentDefinitions: [
      {
        id: "scene",
        description: "A distinct scene or setting change",
        timeRanges: [
          { startTime: 0, endTime: 30 },
          { startTime: 60, endTime: 90 },
        ],
      },
    ],
  },
});
```

#### cURL

The following example detects scene changes and extracts a sentiment field for each segment:

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/analyze/tasks \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "pegasus1.5",
    "video": { "type": "url", "url": "<YOUR_VIDEO_URL>" },
    "analysis_mode": "time_based_metadata",
    "response_format": {
      "type": "segment_definitions",
      "segment_definitions": [
        {
          "id": "scene",
          "description": "A distinct scene or setting change in the video",
          "fields": [
            {
              "name": "sentiment",
              "type": "string",
              "description": "The emotional tone of this segment",
              "enum": ["positive", "negative", "neutral"]
            }
          ]
        }
      ]
    }
  }'
```

You can also restrict segment extraction to specific time windows by adding time ranges to individual segment definitions. The following example limits scene detection to two windows (0-30s and 60-90s):

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/analyze/tasks \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "pegasus1.5",
    "video": { "type": "url", "url": "<YOUR_VIDEO_URL>" },
    "analysis_mode": "time_based_metadata",
    "response_format": {
      "type": "segment_definitions",
      "segment_definitions": [
        {
          "id": "scene",
          "description": "A distinct scene or setting change",
          "time_ranges": [
            { "start_time": 0, "end_time": 30 },
            { "start_time": 60, "end_time": 90 }
          ]
        }
      ]
    }
  }'
```

**Structured prompts with reference images**

Reference up to 4 images in your prompt. Use `<@name>` placeholders in the prompt text and provide the referenced images. The following example asks whether a reference photo matches a person in the video:

#### Python

**`Python`**

```python Python maxLines=12
from twelvelabs.types import AnalyzePromptV2, SmeMediaSource, VideoContext_Url

result = client.analyze(
    model_name="pegasus1.5",
    video=VideoContext_Url(url="<YOUR_VIDEO_URL>"),
    prompt_v_2=AnalyzePromptV2(
        input_text="Does the person in the video resemble <@reference_photo>?",
        media_sources=[
            SmeMediaSource(
                name="reference_photo",
                media_type="image",
                url="<YOUR_IMAGE_URL>",
            ),
        ],
    ),
)
```

#### Node.js

**`Node.js`**

```javascript Node.js maxLines=12
const result = await client.analyze({
  modelName: "pegasus1.5",
  video: { type: "url", url: "<YOUR_VIDEO_URL>" },
  promptV2: {
    inputText: "Does the person in the video resemble <@reference_photo>?",
    mediaSources: [
      {
        name: "reference_photo",
        mediaType: "image",
        url: "<YOUR_IMAGE_URL>",
      },
    ],
  },
});
```

#### cURL

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/analyze \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "pegasus1.5",
    "video": { "type": "url", "url": "<YOUR_VIDEO_URL>" },
    "prompt_v2": {
      "input_text": "Does the person in the video resemble <@reference_photo>?",
      "media_sources": [
        {
          "name": "reference_photo",
          "media_type": "image",
          "url": "<YOUR_IMAGE_URL>"
        }
      ]
    }
  }'
```

**Video clipping**

Analyze a specific portion of a video by setting a start and end time. The following example analyzes a 60-second clip starting at timestamp `30`:

#### Python

**`Python`**

```python Python maxLines=12
from twelvelabs.types import AnalyzePromptV2, VideoContext_Url

result = client.analyze(
    model_name="pegasus1.5",
    video=VideoContext_Url(url="<YOUR_VIDEO_URL>"),
    prompt_v_2=AnalyzePromptV2(
        input_text="What happens in this clip?",
    ),
    start_time=30.0,
    end_time=90.0,
)
```

#### Node.js

**`Node.js`**

```javascript Node.js maxLines=12
const result = await client.analyze({
  modelName: "pegasus1.5",
  video: { type: "url", url: "<YOUR_VIDEO_URL>" },
  promptV2: {
    inputText: "What happens in this clip?",
  },
  startTime: 30,
  endTime: 90,
});
```

#### cURL

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/analyze \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "pegasus1.5",
    "video": { "type": "url", "url": "<YOUR_VIDEO_URL>" },
    "prompt_v2": {
      "input_text": "What happens in this clip?"
    },
    "start_time": 30,
    "end_time": 90
  }'
```

# Additional resources

#### [Analyze videos](/v1.3/docs/guides/analyze-videos)

#### [Segment videos](/v1.3/docs/guides/segment-videos)

#### [Python SDK Reference](/v1.3/sdk-reference/python/analyze-videos)

#### [Node.js SDK Reference](/v1.3/sdk-reference/node-js/analyze-videos)

#### [API Reference](/v1.3/api-reference/analyze-videos)