---
title: "Get an edit | GPT-Video API reference"
description: "Returns the edit of a prepared Vibe Editing project: its videos, segments, texts, b-roll, captions and revision."
url: "https://www.gpt-video.com/developers/api/get-timeline"
operation: "get_timeline"
method: "GET"
path: "/v1/projects/{projectId}/timeline"
scope: "clips:read"
---

Do not assume endpoints have parameters other than the ones explicitly specified.

# Get an edit

Operation id `get_timeline`. Request `GET /v1/projects/{projectId}/timeline`.

Returns the edit of a prepared Vibe Editing project: its videos, segments, texts, b-roll, captions and revision.

Beta. This endpoint is supported and can gain new fields. If a change would break your code, we tell you before it takes effect and list it in the changelog.

## About

Call it after the preparation is done, and before each change: every change sends the revision you read here as expectedRevision. Times come in two bases, named in each field: sourceStartSec and sourceEndSec are seconds of the source video, outputStartSec and the others are seconds of the video that comes out. A file that the API cannot use keeps its place in the edit with assetId null. To export the edit, send compositionId to create_export (`POST /v1/compositions/{compositionId}/exports`).

## Example use

A script that edits interviews reads the timeline once the preparation is done, keeps the revision and the segment ids, and sends them in its next call to apply_timeline_operations (`POST /v1/projects/{projectId}/timeline/operations`).

## Endpoint

```text
GET https://api.gpt-video.com/v1/projects/{projectId}/timeline
```

- Scope `clips:read`.
- Rate limit 120 requests a minute for each key and 240 for each account, shared by every `read` call. See [rate limits](/developers/rate-limits.md).
- No `Idempotency-Key`.

## Parameters

### Path

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string | Required | The project id. It starts with prj_. Matches `^prj_[0-9a-f]{20}$`. |

## Request

Get an edit.

```bash title="curl"
curl "https://api.gpt-video.com/v1/projects/prj_b9c1f9c7873dcef51a57/timeline" \
  -H "Authorization: Bearer $GPT_VIDEO_API_KEY"
```

```ts title="TypeScript"
const res = await fetch("https://api.gpt-video.com/v1/projects/prj_b9c1f9c7873dcef51a57/timeline", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
```

```python title="Python"
import os

import requests

r = requests.get(
    "https://api.gpt-video.com/v1/projects/prj_b9c1f9c7873dcef51a57/timeline",
    headers={
        "Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
    },
)
data = r.json()
print(data)
```

```json title="MCP (Full)"
{
  "method": "tools/call",
  "params": {
    "name": "get_timeline",
    "arguments": {
      "projectId": "prj_b9c1f9c7873dcef51a57"
    }
  }
}
```

## Response

A successful call answers HTTP 200. Returns a [Timeline object](/developers/objects.md#timeline) in `timeline`.

### Fields to check

| Name | Type | Description |
| --- | --- | --- |
| `timeline.id` | string | The edit id. It starts with tml_. |
| `timeline.segments[].id` | string | The segment id. It starts with seg_. |
| `timeline.texts[].id` | string | The text id. It starts with ovl_. |
| `timeline.broll[].id` | string | The b-roll id. It starts with brl_. |

### Response example

```json title="HTTP 200"
{
  "timeline": {
    "id": "tml_bbe061171a8229f8daed",
    "projectId": "prj_b9c1f9c7873dcef51a57",
    "compositionId": "cmp_cfbdd85eaaff301fa997",
    "revision": 1,
    "durationSec": 60,
    "aspect": "9:16",
    "reframe": "off",
    "captions": {
      "enabled": true,
      "style": "bold-karaoke"
    },
    "music": null,
    "fadeInSec": 0,
    "fadeOutSec": 0,
    "clips": [
      {
        "assetId": "ast_3f9a1c7e5b2d4086a1c4",
        "title": "Interview with a founder",
        "durationSec": 1800,
        "state": "ready"
      }
    ],
    "segments": [
      {
        "id": "seg_7279fbb508f4a22e65a4",
        "assetId": "ast_3f9a1c7e5b2d4086a1c4",
        "sourceStartSec": 120,
        "sourceEndSec": 150,
        "zoom": 1,
        "muted": false,
        "volume": 1,
        "outputStartSec": 0,
        "outputEndSec": 30
      },
      {
        "id": "seg_a9dcee59c1fb9edb6751",
        "assetId": "ast_3f9a1c7e5b2d4086a1c4",
        "sourceStartSec": 300,
        "sourceEndSec": 330,
        "zoom": 1,
        "muted": false,
        "volume": 1,
        "outputStartSec": 30,
        "outputEndSec": 60
      }
    ],
    "texts": [
      {
        "id": "ovl_49f5239b9cd73496225d",
        "text": "Paid before the product",
        "preset": "headline",
        "outputStartSec": 0,
        "durationSec": 3,
        "xPercent": null,
        "yPercent": null
      }
    ],
    "broll": [
      {
        "id": "brl_f44d18e008ec4009bf10",
        "assetId": "ast_8ac5d8b97546145cdbf6",
        "outputStartSec": 12,
        "durationSec": 4,
        "fit": "cover"
      }
    ],
    "diagnostics": []
  }
}
```

**All response fields**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `timeline` | Timeline object | Required | Described in [Timeline object](/developers/objects.md#timeline). |

**More examples**

#### The edit is still being prepared

`GET /v1/projects/prj_37573e451e0ff7f863c8/timeline`

```json title="HTTP 409"
{
  "error": {
    "code": "NOT_READY",
    "message": "This edit is still being prepared.",
    "hint": "Wait the number of seconds in the Retry-After header, then send the same request again.",
    "requestId": "req_6f1c3a8e0d5b29e74c1a6f30"
  }
}
```

#### The edit was never prepared

`GET /v1/projects/prj_37573e451e0ff7f863c8/timeline`

```json title="HTTP 409"
{
  "error": {
    "code": "CONFLICT",
    "message": "This edit is not prepared yet. Prepare it with prepare_timeline.",
    "requestId": "req_3a9d7c1e5f0b84a26d9c3e15"
  }
}
```

## Errors

| Code | Status | When | What to do |
| --- | --- | --- | --- |
| [`NOT_FOUND`](/developers/errors.md#NOT_FOUND) | 404 | See the error reference. | Change the request, then send it again. |
| [`CONFLICT`](/developers/errors.md#CONFLICT) | 409 | The edit was never prepared | Read the resource again, then decide. Do not send the same request again. |
| [`NOT_READY`](/developers/errors.md#NOT_READY) | 409 | The edit is still being prepared | Wait for Retry-After, then send the same request again. |

Every call can also answer these errors. [`VALIDATION_FAILED`](/developers/errors.md#VALIDATION_FAILED), [`UNKNOWN_PARAMETER`](/developers/errors.md#UNKNOWN_PARAMETER), [`UNAUTHORIZED`](/developers/errors.md#UNAUTHORIZED), [`SCOPE_MISSING`](/developers/errors.md#SCOPE_MISSING), [`RATE_LIMITED`](/developers/errors.md#RATE_LIMITED), [`INTERNAL`](/developers/errors.md#INTERNAL), [`UNAVAILABLE`](/developers/errors.md#UNAVAILABLE).

## Cost

No credits are used.

## Related operations

- [`prepare_timeline`](/developers/api/prepare-timeline.md) (`POST /v1/projects/{projectId}/timeline/prepare`) Prepare an edit
- [`apply_timeline_operations`](/developers/api/apply-timeline-operations.md) (`POST /v1/projects/{projectId}/timeline/operations`) Change an edit
- [`add_timeline_clip`](/developers/api/add-timeline-clip.md) (`POST /v1/projects/{projectId}/timeline/clips`) Add a video to an edit
- [`list_timeline_revisions`](/developers/api/list-timeline-revisions.md) (`GET /v1/projects/{projectId}/timeline/revisions`) List the revisions of an edit
- [`create_export`](/developers/api/create-export.md) (`POST /v1/compositions/{compositionId}/exports`) Export a composition
- [`restore_timeline`](/developers/api/restore-timeline.md) (`POST /v1/projects/{projectId}/timeline/restore`) Restore a revision of an edit

## Questions

### Why is a clip in state failed?

Its video could not be prepared after several tries, and it is not prepared again by itself. Remove its segments with apply_timeline_operations (`POST /v1/projects/{projectId}/timeline/operations`); the rest of the edit keeps working.

### Why is an assetId null?

The file no longer exists or cannot be used through the API, for example a file made in another part of the GPT-Video app. The segment, b-roll or music keeps its place in the edit.
