---
title: "Replace a project's timeline"
method: PUT
path: "/v1/studio/projects/{id}/timeline"
tags: ["Studio"]
---

# Replace a project's timeline

`PUT /v1/studio/projects/{id}/timeline`

## Request

- Base URL: `https://api.vidocu.ai`
- URL: `https://api.vidocu.ai/v1/studio/projects/{id}/timeline`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://vidocu.ai/oauth/authorize`, token URL `https://api.vidocu.ai/oauth/token`)

Whole-document replacement of tracks, clips and media. Validated against the editor's types and checked for referential integrity — every clip must sit on a track that exists, and media clips must point at media that exists. totalDuration is derived, not taken from the request.

**Scope:** `studio:write`

**Role permission:** `canEdit` (OAuth only — API keys carry full workspace permissions)

## Path parameters

- `id` string, required

## Request body

- object
  - `tracks` object[], required
    - `id` string, required
    - `type` 'main' | 'overlay' | 'audio', required
    - `name` string, required
    - `order` integer, required
    - `locked` boolean, required
    - `visible` boolean, required
    - `volume` number, required
  - `clips` object[], required
    - `id` string, required
    - `type` 'video' | 'image' | 'audio' | 'text' | 'shape' | 'emoji' | 'slide' | 'scene', required
    - `mediaId` string
    - `trackId` string, required
    - `startOnTimeline` number, required
    - `duration` number, required
    - `sourceStartTime` number, required
    - `sourceEndTime` number, required
    - `speed` number, required
    - `volume` number, required
    - `opacity` number, required
    - `fitMode` 'fill' | 'fit'
    - `fillZoom` number
    - `fillOffsetX` number
    - `fillOffsetY` number
    - `crop` object
      - `x` number, required
      - `y` number, required
      - `width` number, required
      - `height` number, required
    - `rotation` number
    - `flipH` boolean
    - `flipV` boolean
    - `brightness` number
    - `contrast` number
    - `saturation` number
    - `hueRotate` number
    - `sepia` number
    - `grayscale` number
    - `blur` number
    - `filterPreset` string
    - `fadeIn` number
    - `fadeOut` number
    - `duckUnderVoiceover` boolean
    - `duckVolume` number
    - `duckFade` number
    - `position` object
      - `x` number, required
      - `y` number, required
    - `size` object
      - `width` number, required
      - `height` number, required
    - `caption` boolean
    - `textStyle` object
    - `shapeStyle` object
    - `slide` object
    - `scene` object
    - `transition` object
    - `voiceover` object
    - `zoom` object
    - `zooms` object[]
  - `media` object[], required
    - `id` string, required
    - `name` string, required
    - `type` 'video' | 'image' | 'audio', required
    - `url` string, uri, required
    - `thumbnailUrl` string, uri
    - `duration` number
    - `width` integer
    - `height` integer
    - `fileSize` integer
    - `uploadedAt` union
      - string
      - string, date-time
    - `imported` boolean

## Response `200`

Success

## Other responses

- `400`: Validation error
- `401`: Invalid or missing credentials
- `403`: Missing scope (`insufficient_scope`), insufficient role (`insufficient_role`), or quota exhausted (`limit_exceeded`)
- `404`: Not found
- `429`: Rate limit exceeded (60 req/min)
- `500`: Server error

---

[API](https://skmtc.dev/vidocu/apis/vidocu-api.md) · [All operations](https://skmtc.dev/vidocu/apis/vidocu-api/llms.txt) · [OpenAPI document](https://skmtc.dev/vidocu/apis/vidocu-api/revisions/cc813d2ca5d2?raw)
