> This page is for version v1.3 (default).
> For other versions, use one of these documentation indexes:
> - v1.3 (default): https://docs.twelvelabs.io/v1.3/llms.txt

> 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 Marengo 3.0 to Marengo 3.5

> Migrate your embedding calls from Marengo 3.0 to Marengo 3.5.

This guide shows how to migrate your embedding calls to Marengo 3.5. It focuses on SDK migrations, but it also includes cURL examples for the capabilities that Marengo 3.5 adds.

Marengo 3.0 continues to work without changes. The platform uses it when you omit the `model_name` parameter. Migrate when you want the capabilities that Marengo 3.5 adds.

> **Note**
>
> Marengo 3.5 embeddings are not compatible with Marengo 3.0 embeddings. To move to Marengo 3.5, regenerate your embeddings with Marengo 3.5.

# 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 your Python input classes

Skip this step if you use the Node.js SDK, or if you do not type-check your Python code.

In the Python SDK, the `AsyncVideoInputRequest` and `AsyncAudioInputRequest` classes replace `VideoInputRequest` and `AudioInputRequest` on the [`embed.v_2.tasks.create`](/v1.3/sdk-reference/python/create-embeddings-v-2/create-async-embeddings#create-an-async-embedding-task) method. The SDK accepts both the old and the new classes, so your existing code continues to work after you upgrade. Update it to clear the type-checker errors.

**Before**:

**`Python`**

```python Python maxLines=12
from twelvelabs.types import VideoInputRequest, MediaSource

task = client.embed.v_2.tasks.create(
    input_type="video",
    model_name="marengo3.0",
    video=VideoInputRequest(media_source=MediaSource(asset_id="<YOUR_ASSET_ID>")),
)
```

**After**:

**`Python`**

```python Python maxLines=12
from twelvelabs.types import AsyncVideoInputRequest, MediaSource

task = client.embed.v_2.tasks.create(
    input_type="video",
    model_name="marengo3.0",
    video=AsyncVideoInputRequest(media_source=MediaSource(asset_id="<YOUR_ASSET_ID>")),
)
```

#### Update your synchronous calls

Set the model to Marengo 3.5. Marengo 3.5 accepts a single input type on the synchronous method: `multi_input`. Replace the per-type input objects with a single combined input. Provide your text, your media sources, or both.

Marengo 3.0 accepts images as media sources. Marengo 3.5 also accepts video and audio.

#### Python

Set the `input_type` parameter to `multi_input` and pass a `MultiInputRequest` object to the `multi_input` parameter.

**Before**:

**`Python`**

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

response = client.embed.v_2.create(
    input_type="text",
    model_name="marengo3.0",
    text=TextInputRequest(input_text="<YOUR_TEXT>"),
)
```

**After**:

**`Python`**

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

response = client.embed.v_2.create(
    input_type="multi_input",
    model_name="marengo3.5",
    multi_input=MultiInputRequest(input_text="<YOUR_TEXT>"),
)
```

To embed an image, pass a `MultiInputMediaSource` object in the `media_sources` field instead of using the `image` parameter.

#### Node.js

Set the `inputType` parameter to `multi_input` and pass an object to the `multiInput` parameter.

**Before**:

**`Node.js`**

```javascript Node.js maxLines=12
const response = await client.embed.v2.create({
  inputType: "text",
  modelName: "marengo3.0",
  text: { inputText: "<YOUR_TEXT>" },
});
```

**After**:

**`Node.js`**

```javascript Node.js maxLines=12
const response = await client.embed.v2.create({
  inputType: "multi_input",
  modelName: "marengo3.5",
  multiInput: { inputText: "<YOUR_TEXT>" },
});
```

To embed an image, pass an object in the `mediaSources` field instead of using the `image` parameter.

> **Note**
>
> With Marengo 3.5, video and audio can be up to 30 seconds on the synchronous method. For longer files, use the asynchronous method. Your text can be up to 2,000 tokens, and each media source can be up to 32 MB. Set the `auto_truncate` parameter to `true` to truncate text above this limit instead of receiving a `400` error.

#### Update your asynchronous calls

Set the model to Marengo 3.5. This version also accepts documents and images as input types.

Marengo 3.5 changes two defaults. For video, the `embedding_option` field defaults to `["visual", "audio"]` instead of `["visual", "audio", "transcription"]`. For audio, it defaults to `["audio"]` instead of `["audio", "transcription"]`. The `transcription` value requires Marengo 3.0. With Marengo 3.5, the `audio` value includes speech, music, and non-dialog audio.

Marengo 3.5 also changes the structure of the `segmentation` field. Place your settings in a `temporal` object. For details, see the [Video embeddings](/v1.3/docs/guides/create-embeddings/at-scale/video) guide.

#### Python

In this example, the model name is the only change.

**Before**:

**`Python`**

```python Python maxLines=12
task = client.embed.v_2.tasks.create(
    input_type="video",
    model_name="marengo3.0",
    video=AsyncVideoInputRequest(media_source=MediaSource(asset_id="<YOUR_ASSET_ID>")),
)
```

**After**:

**`Python`**

```python Python maxLines=12
task = client.embed.v_2.tasks.create(
    input_type="video",
    model_name="marengo3.5",
    video=AsyncVideoInputRequest(media_source=MediaSource(asset_id="<YOUR_ASSET_ID>")),
)
```

#### Node.js

In this example, the model name is the only change.

**Before**:

**`Node.js`**

```javascript Node.js maxLines=12
const task = await client.embed.v2.tasks.create({
  inputType: "video",
  modelName: "marengo3.0",
  video: { mediaSource: { assetId: "<YOUR_ASSET_ID>" } },
});
```

**After**:

**`Node.js`**

```javascript Node.js maxLines=12
const task = await client.embed.v2.tasks.create({
  inputType: "video",
  modelName: "marengo3.5",
  video: { mediaSource: { assetId: "<YOUR_ASSET_ID>" } },
});
```

#### Regenerate your embeddings

Marengo 3.5 embeddings are not compatible with Marengo 3.0 embeddings. To move to Marengo 3.5, regenerate your embeddings with Marengo 3.5.

Re-embed the same source content with Marengo 3.5. Keep the two sets of embeddings apart until the new set is complete. Then point your application at the new set. For step-by-step instructions, see the [Embed content at scale](/v1.3/docs/guides/create-embeddings/at-scale) guides.

#### Use new Marengo 3.5 features

The following examples show each new capability.

**Composed queries with video and audio**

Combine text with up to 10 media sources into a single embedding. Marengo 3.0 accepts images as media sources. Marengo 3.5 also accepts video and audio. Reference a media source from your text with the `<@name>` format.

#### Python

**`Python`**

```python Python maxLines=12
from twelvelabs.types import MultiInputRequest, MultiInputMediaSource

response = client.embed.v_2.create(
    input_type="multi_input",
    model_name="marengo3.5",
    multi_input=MultiInputRequest(
        input_text="A crowd reacting like <@clip>",
        media_sources=[
            MultiInputMediaSource(
                name="clip",
                media_type="video",
                asset_id="<YOUR_ASSET_ID>",
            ),
        ],
    ),
)
```

#### Node.js

**`Node.js`**

```javascript Node.js maxLines=12
const response = await client.embed.v2.create({
  inputType: "multi_input",
  modelName: "marengo3.5",
  multiInput: {
    inputText: "A crowd reacting like <@clip>",
    mediaSources: [
      { name: "clip", mediaType: "video", assetId: "<YOUR_ASSET_ID>" },
    ],
  },
});
```

#### cURL

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/embed-v2 \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "input_type": "multi_input",
    "model_name": "marengo3.5",
    "multi_input": {
      "input_text": "A crowd reacting like <@clip>",
      "media_sources": [
        { "name": "clip", "media_type": "video", "asset_id": "<YOUR_ASSET_ID>" }
      ]
    }
  }'
```

**Document embeddings**

Create embeddings from a PDF, plain text, or Markdown file. The default options embed a PDF file per rendered page, and a plain text or Markdown file as one embedding for the entire file. To embed documents, you must use the asynchronous method. For all the option and scope combinations, see the [Embed content at scale](/v1.3/docs/guides/create-embeddings/at-scale/document) guide.

#### Python

**`Python`**

```python Python maxLines=12
from twelvelabs.types import AsyncDocumentInputRequest, MediaSource

task = client.embed.v_2.tasks.create(
    input_type="document",
    model_name="marengo3.5",
    document=AsyncDocumentInputRequest(
        media_source=MediaSource(asset_id="<YOUR_ASSET_ID>"),
        embedding_scope=["local"],
    ),
)
```

#### Node.js

**`Node.js`**

```javascript Node.js maxLines=12
const task = await client.embed.v2.tasks.create({
  inputType: "document",
  modelName: "marengo3.5",
  document: {
    mediaSource: { assetId: "<YOUR_ASSET_ID>" },
    embeddingScope: ["local"],
  },
});
```

#### cURL

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/embed-v2/tasks \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "input_type": "document",
    "model_name": "marengo3.5",
    "document": {
      "media_source": { "asset_id": "<YOUR_ASSET_ID>" },
      "embedding_scope": ["local"]
    }
  }'
```

**Time-based metadata fusion**

Fold your own time-aligned text, such as a stats feed, into the fused embedding of the segments it overlaps in time. This capability requires the `fused_embedding` value in the `embedding_type` field, and it applies to audio and video on the asynchronous method.

#### Python

**`Python`**

```python Python maxLines=12
from twelvelabs.types import AsyncVideoInputRequest, MediaSource, TimeBasedMetadataEntry

task = client.embed.v_2.tasks.create(
    input_type="video",
    model_name="marengo3.5",
    video=AsyncVideoInputRequest(
        media_source=MediaSource(asset_id="<YOUR_ASSET_ID>"),
        embedding_option=["visual", "audio"],
        embedding_type=["separate_embedding", "fused_embedding"],
        time_based_metadata=[
            TimeBasedMetadataEntry(start=42.3, end=45.0, text="<YOUR_TEXT>"),
        ],
    ),
)
```

#### Node.js

**`Node.js`**

```javascript Node.js maxLines=12
const task = await client.embed.v2.tasks.create({
  inputType: "video",
  modelName: "marengo3.5",
  video: {
    mediaSource: { assetId: "<YOUR_ASSET_ID>" },
    embeddingOption: ["visual", "audio"],
    embeddingType: ["separate_embedding", "fused_embedding"],
    timeBasedMetadata: [
      { start: 42.3, end: 45.0, text: "<YOUR_TEXT>" },
    ],
  },
});
```

#### cURL

**`cURL`**

```shell cURL maxLines=12
curl -X POST https://api.twelvelabs.io/v1.3/embed-v2/tasks \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "input_type": "video",
    "model_name": "marengo3.5",
    "video": {
      "media_source": { "asset_id": "<YOUR_ASSET_ID>" },
      "embedding_option": ["visual", "audio"],
      "embedding_type": ["separate_embedding", "fused_embedding"],
      "time_based_metadata": [
        { "start": 42.3, "end": 45.0, "text": "<YOUR_TEXT>" }
      ]
    }
  }'
```

**Embedding uncertainty**

Set the `embedding_uncertainty` parameter to `true` to receive a per-dimension uncertainty vector alongside each embedding. A higher value shows lower confidence in that dimension.

On the synchronous method, set this parameter to `true` only when your request embeds text only, or media only. On the asynchronous method with audio or video input, exclude the `asset` scope from the `embedding_scope` field. For details, see the [Embed a query](/v1.3/docs/guides/create-embeddings/query) and [Embed content at scale](/v1.3/docs/guides/create-embeddings/at-scale) guides.

**Embedding dimension**

Set the `embedding_dimension` parameter to 128 or 256 to create shorter embeddings. The default is `512`. A shorter embedding consists of the first values of the full-length one. For example, a 256-value embedding is the beginning of a 512-value embedding of the same content. Shorter embeddings make your index smaller and similarity search faster, and longer embeddings produce higher retrieval quality.

The parameter applies to your entire request. Use the same value across an index, because similarity search requires embeddings of the same length. The `embedding_uncertainty` vector, if you request it, has the same length. On the asynchronous method, the platform sets the length when you create the task. To embed the same content at a different length, create a second task. For details, see the [`embedding_dimension`](/v1.3/api-reference/create-embeddings-v2/create-embeddings#request.body.embedding-dimension) parameter.

**Token usage**

Responses from Marengo 3.5 include a new object named `usage` that shows the token counts for your request.

**Automatic truncation**

Set the `auto_truncate` parameter to `true` to truncate text above the 2,000-token limit instead of receiving a `400` error. When the platform truncates your text, it sets the `usage.truncated` field to `true` in the response.

# Additional resources

#### [Embed a query](/v1.3/docs/guides/create-embeddings/query)

#### [Embed content at scale](/v1.3/docs/guides/create-embeddings/at-scale)

#### [Marengo 3.5](/v1.3/docs/concepts/models/marengo/marengo-3-5)

#### [Python SDK Reference](/v1.3/sdk-reference/python/create-embeddings-v-2)

#### [Node.js SDK Reference](/v1.3/sdk-reference/node-js/create-embeddings-v-2)

#### [API Reference](/v1.3/api-reference/create-embeddings-v2)