Replace Video

Replace an existing video asset without changing its playback URL

Use this flow when you need to upload a new source file for an existing video asset while keeping the same asset ID and playback URL.

Prefer the official SDKs when available:

Using REST API (Replace Video)

1. Create a replace request

Start the replacement by calling the Update Asset API with the existing asset_id and the input path in this format:

{workspace_id}/{asset_id}/origin-{asset_id}

Replace <WORKSPACE_ID> with the workspace that owns the asset and <ASSET_ID> with the video you want to replace.

import Gumlet from '@gumlet/nodejs-sdk';

const client = new Gumlet({
  apiKey: process.env['API_KEY'],
});

const videoAsset = await client.videoAssets.update({
  asset_id: '<ASSET_ID>',
  input: '<WORKSPACE_ID>/<ASSET_ID>/origin-<ASSET_ID>',
});

console.log(videoAsset);
import os

from gumlet import Gumlet

client = Gumlet(
    api_key=os.environ.get("API_KEY"),
)

video_asset = client.video_assets.update(
    asset_id="<ASSET_ID>",
    input="<WORKSPACE_ID>/<ASSET_ID>/origin-<ASSET_ID>",
)

print(video_asset)
curl --request POST \
     --url https://api.gumlet.com/v1/video/assets/update \
     --header 'Authorization: Bearer <YOUR_API_KEY>' \
     --header 'Content-Type: application/json' \
     --data '{
       "asset_id": "<ASSET_ID>",
       "input": "<WORKSPACE_ID>/<ASSET_ID>/origin-<ASSET_ID>"
     }'

2. Split the new video into parts

Split the new source video into parts before uploading it. Keep each part at least 5 MB, except the final part.

3. Sign and upload each part

For every part, call the Single Part API using the same asset_id and a sequential part_number starting from 1. Upload the part binary to the returned part_upload_url with a PUT request, then store the ETag response header for that part. Repeat this step for every part of the replacement video.

import { readFile } from 'node:fs/promises';

const partNumber = '1';
const signed = await client.multipartUpload.retrievePartURL(partNumber, {
  asset_id: '<ASSET_ID>',
});

const partData = await readFile('part-1.bin');
const uploadResponse = await fetch(signed.part_upload_url, {
  method: 'PUT',
  body: partData,
});

if (!uploadResponse.ok) {
  throw new Error(`Part upload failed: ${uploadResponse.status}`);
}

const etag = uploadResponse.headers.get('etag');
// Store PartNumber + ETag for every part
import requests

part_number = "1"
signed = client.multipart_upload.retrieve_part_url(
    asset_id="<ASSET_ID>",
    part_number=part_number,
)

with open("part-1.bin", "rb") as part_file:
    upload_response = requests.put(signed.part_upload_url, data=part_file)

upload_response.raise_for_status()
etag = upload_response.headers["ETag"]
# Store PartNumber + ETag for every part
curl --request GET \
     --url https://api.gumlet.com/v1/video/assets/<ASSET_ID>/multipartupload/<PART_NUMBER>/sign \
     --header 'Authorization: Bearer <YOUR_API_KEY>' \
     --header 'Content-Type: application/json'

Upload the part using the part_upload_url:

curl -v -X PUT -T <PART_FILE> '<PART_UPLOAD_URL>'

4. Complete the multipart upload

After all parts are uploaded, call Complete Multipart Upload with the PartNumber and ETag collected for each part.

await client.multipartUpload.complete('<ASSET_ID>', {
  parts: [
    { PartNumber: 1, ETag: '"<ETAG_PART_1>"' },
    { PartNumber: 2, ETag: '"<ETAG_PART_2>"' },
  ],
});
client.multipart_upload.complete(
    asset_id="<ASSET_ID>",
    parts=[
        {"part_number": 1, "e_tag": '"<ETAG_PART_1>"'},
        {"part_number": 2, "e_tag": '"<ETAG_PART_2>"'},
    ],
)
curl --request POST \
     --url https://api.gumlet.com/v1/video/assets/<ASSET_ID>/multipartupload/complete \
     --header 'Authorization: Bearer <YOUR_API_KEY>' \
     --header 'Content-Type: application/json' \
     --data '{
       "parts": [
         { "PartNumber": 1, "ETag": "\"<ETAG_PART_1>\"" },
         { "PartNumber": 2, "ETag": "\"<ETAG_PART_2>\"" }
       ]
     }'

5. Track processing

Use the Get Asset Status API to monitor the asset until processing completes.

const videoAsset = await client.videoAssets.retrieveDetails('<ASSET_ID>');
console.log(videoAsset);
video_asset = client.video_assets.retrieve_details(
    asset_id="<ASSET_ID>",
)
print(video_asset)
curl -L -X GET 'https://api.gumlet.com/v1/video/assets/<ASSET_ID>' \
-H 'Authorization: Bearer <YOUR_API_KEY>'

The replacement keeps the existing asset ID and playback URL. If your previous thumbnail or generated subtitles no longer match the new video, update them after the replacement finishes.