> ## Documentation Index
> Fetch the complete documentation index at: https://heygen-1fa696a7.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Filler word removal

> Remove filler words and overlong silences from a finished video with the HeyGen Filler Word Removal API — submit a video, get back one cleaned cut with removal statistics.

<img className="w-full h-44 object-cover rounded-xl" src="https://mintcdn.com/heygen-1fa696a7/hfMXXwJzjE7vBSYZ/images/theme/research-5.webp?fit=max&auto=format&n=hfMXXwJzjE7vBSYZ&q=85&s=422da140ece4b799d490f85bb2013ca5" alt="" noZoom width="1400" height="788" data-path="images/theme/research-5.webp" />

Submit a video and get back a cleaned version with the "um"s, "uh"s, and overlong silences cut out. The job transcribes the audio, detects filler words, removes them along with dead air, and renders one finished video — no review step, no edit decisions to make. It's built for recordings where a human spoke off the cuff: webinars, screen recordings, interviews, all-hands.

## Create a Removal Job

* Endpoint: [`POST /v3/filler-word-removals`](/reference/create-filler-word-removal)
* Purpose: Start a removal job for a source video. Returns a `filler_word_removal_id` to poll.

### Quick Example

```bash theme={null}
curl -X POST "https://api.heygen.com/v3/filler-word-removals" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video": { "type": "url", "url": "https://example.com/webinar.mp4" },
    "title": "Q3 webinar — cleaned"
  }'
```

```json Response theme={null}
{
  "data": {
    "filler_word_removal_id": "b4f0c2a91de843f6a2d07c5e8a913f27"
  }
}
```

The endpoint returns `202 Accepted` immediately; the job runs asynchronously.

### Request Body

| Parameter      | Type   | Required | Default          | Description                                                                                                                                                                                                                                                                           |
| -------------- | ------ | -------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `video`        | object | Yes      | —                | Source video with a speech audio track. Provide as `{ "type": "url", "url": "https://..." }` or `{ "type": "asset_id", "asset_id": "..." }` (from [`POST /v3/assets`](/reference/upload-asset) — see [Upload Assets](/docs/upload-assets)). Sources up to 2 hours long are supported. |
| `title`        | string | No       | `Filler Removal` | Display title for the job.                                                                                                                                                                                                                                                            |
| `callback_url` | string | No       | —                | [Webhook](/docs/webhooks) URL — receives a POST when the job completes or fails (`filler_word_removal.success` / `filler_word_removal.fail`).                                                                                                                                         |
| `callback_id`  | string | No       | —                | Arbitrary ID echoed back in the webhook payload.                                                                                                                                                                                                                                      |

### Idempotency

Pass an `Idempotency-Key` header to make retries safe — replaying the same key returns the original job instead of creating a duplicate.

## Get a Removal Job

* Endpoint: [`GET /v3/filler-word-removals/{filler_word_removal_id}`](/reference/get-filler-word-removal)
* Purpose: Fetch a job's live status and, once it completes, the cleaned video plus removal statistics.

### Quick Example

```bash theme={null}
curl -X GET "https://api.heygen.com/v3/filler-word-removals/b4f0c2a91de843f6a2d07c5e8a913f27" \
  -H "X-Api-Key: $HEYGEN_API_KEY"
```

### Path Parameters

| Parameter                | Type   | Required | Description                                                        |
| ------------------------ | ------ | -------- | ------------------------------------------------------------------ |
| `filler_word_removal_id` | string | Yes      | Unique job identifier returned by `POST /v3/filler-word-removals`. |

### Response

```json theme={null}
{
  "data": {
    "id": "b4f0c2a91de843f6a2d07c5e8a913f27",
    "title": "Q3 webinar — cleaned",
    "status": "completed",
    "progress": 100,
    "video_url": "https://files2.heygen.ai/filler-removal/.../output.mp4?Expires=...",
    "thumbnail_url": "https://resource2.heygen.ai/video/thumbnail/....webp",
    "original_duration": 512.6,
    "output_duration": 471.9,
    "num_cuts": 23,
    "reduction_pct": 7.9,
    "created_at": 1785650000
  }
}
```

### Response Fields

| Field               | Type            | Description                                                                                                                                           |
| ------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                | string          | Unique job identifier.                                                                                                                                |
| `title`             | string or null  | Display title for the job.                                                                                                                            |
| `status`            | string          | Job lifecycle status: `pending`, `running`, `completed`, or `failed`.                                                                                 |
| `progress`          | integer         | Approximate progress (0–100). `100` when completed.                                                                                                   |
| `video_url`         | string or null  | Pre-signed MP4 download URL of the cleaned video. Present when status is `completed`.                                                                 |
| `thumbnail_url`     | string or null  | Pre-signed thumbnail URL, when a thumbnail was generated.                                                                                             |
| `original_duration` | number or null  | Duration of the source video in seconds.                                                                                                              |
| `output_duration`   | number or null  | Duration of the cleaned video in seconds.                                                                                                             |
| `num_cuts`          | integer or null | Number of filler segments removed. Counts filler cuts only — a job that trimmed silences alone reports `num_cuts: 0` with a positive `reduction_pct`. |
| `reduction_pct`     | number or null  | Percentage of the source duration removed.                                                                                                            |
| `callback_id`       | string or null  | Client-provided callback ID echoed from the create request. Only present when you supplied one.                                                       |
| `created_at`        | integer         | Unix timestamp (seconds) of job creation.                                                                                                             |
| `failure_message`   | string or null  | Error description. Only present when status is `failed`.                                                                                              |

<Note>
  `video_url` is a pre-signed link with a limited lifetime. Download the file soon after the job completes, or re-fetch this endpoint for a fresh link.
</Note>

A completed job always carries a `video_url` — when the run finds nothing to cut, the output is a copy of the original video and the charge is automatically refunded, so your polling code never needs a special no-change branch.

## Polling Pattern

Removal jobs are processed asynchronously. Poll until status reaches `completed` or `failed`.

Status transitions: `pending` → `running` → `completed` | `failed`

```bash theme={null}
while true; do
  STATUS=$(curl -s "https://api.heygen.com/v3/filler-word-removals/$JOB_ID" \
    -H "X-Api-Key: $HEYGEN_API_KEY" | jq -r '.data.status')
  echo "Status: $STATUS"
  [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ] && break
  sleep 10
done
```

For long recordings, prefer a [`callback_url`](/docs/webhooks) over tight polling — HeyGen will POST you the finished job instead (`filler_word_removal.success` / `filler_word_removal.fail` [webhook events](/docs/webhook-events)). Treat the webhook as a completion signal and fetch the authoritative result from [`GET /v3/filler-word-removals/{filler_word_removal_id}`](/reference/get-filler-word-removal).

## Asset Inputs

The `video` field accepts two input formats:

**By URL** — any publicly accessible HTTPS link:

```json theme={null}
{ "type": "url", "url": "https://example.com/recording.mp4" }
```

**By asset ID** — reference a file previously uploaded via [`POST /v3/assets`](/reference/upload-asset) (see [Upload Assets](/docs/upload-assets)):

```json theme={null}
{ "type": "asset_id", "asset_id": "asset_xyz789" }
```

Either way, the source needs a speech audio track to transcribe and can be up to 2 hours long.

## Full Example

```python theme={null}
import time
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.heygen.com"
HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"}


def remove_fillers(video_url, title=None):
    """Start a removal job, wait for it, and return the finished job."""
    body = {"video": {"type": "url", "url": video_url}}
    if title:
        body["title"] = title

    job_id = requests.post(
        f"{BASE}/v3/filler-word-removals", headers=HEADERS, json=body
    ).json()["data"]["filler_word_removal_id"]

    while True:
        job = requests.get(
            f"{BASE}/v3/filler-word-removals/{job_id}", headers=HEADERS
        ).json()["data"]
        if job["status"] in ("completed", "failed"):
            break
        time.sleep(10)

    if job["status"] == "failed":
        raise RuntimeError(job.get("failure_message") or "removal job failed")
    return job


job = remove_fillers("https://example.com/webinar.mp4", title="Q3 webinar — cleaned")
print(f"{job['num_cuts']} cuts, {job['reduction_pct']}% shorter -> {job['video_url']}")
```

Cleaning a recording before repurposing it? Run filler removal first, then hand the cleaned video to [AI clipping](/ai-clipping) for highlights — and score the cuts with [background music](/background-music) and [sound effects](/sound-effects) from the same Tools suite.
