---
title: "Update a layer"
method: PUT
path: "/projects/{id}/layers/{layerId}"
tags: ["Layers"]
---

# Update a layer

`PUT /projects/{id}/layers/{layerId}`

## Request

- Base URL: `https://api.livereacting.com/v1/external`
- URL: `https://api.livereacting.com/v1/external/projects/{id}/layers/{layerId}`
- Auth: HTTP bearer

Update layer properties and settings. All fields are optional — send only what you want to change.

Supports three layer types: `video`, `videoPlaylist`, and `audioPlaylist`.

## Settings by Layer Type

Not all settings fields apply to every layer type. Use this table to see what's available:

| Field | video | videoPlaylist | audioPlaylist | Description |
|-------|:-----:|:-------------:|:-------------:|-------------|
| `fileId` | ✓ | | | Change the video file (resets playback state) |
| `volume` | ✓ | ✓ | ✓ | Audio volume (0-10) |
| `loop` | ✓ | ✓ | ✓ | Loop when playback ends |
| `shuffle` | | ✓ | ✓ | Enable shuffle/random playback order |
| `nextScene` | ✓ | ✓ | ✓ | Scene ID to auto-switch to when playback ends |
| `files` | | ✓ | ✓ | Replace playlist files (max 600) |
| `showFileName` | | ✓ | ✓ | Display file name overlay |
| `showProgressBar` | | ✓ | ✓ | Show playback progress bar |
| `namePosition` | | ✓ | | Position of file name overlay |
| `adPlaceholder` | | ✓ | | Video placeholder during ad breaks |
| `showCoverImage` | | | ✓ | Display album art/cover image |
| `coverImageSize` | | | ✓ | Cover image size in pixels (30-180) |
| `textStylePreset` | | ✓ | ✓ | Base style preset for text overlay |
| `textStyles` | | ✓ | ✓ | Custom text styling (partial updates supported) |

See the schema below for full field details, types, and constraints.

## Behavior Notes

**Partial updates:** Only send fields you want to change. Existing values are preserved — including nested `textStyles`.

**Changing a video file** (`fileId`): The file must be a video owned by you. Playback state is reset (`isPlaying`, `duration`, etc.).

**Replacing playlist files** (`files`): Updating the `files` array resets all playback state. Behavior depends on whether the layer is currently active:
- **Active scene (currently playing):** Playback stops immediately. Call the [Play](#tag/Playback/operation/playbackPlay) endpoint to resume (e.g., `{ "index": 0 }` for the first file).
- **Inactive scene (not currently playing):** Playback will auto-start from the first file when the stream switches to that scene. No additional action needed.

**`loop` vs `nextScene`:** These are mutually exclusive. Setting `nextScene` auto-disables `loop`. Enabling `loop` while `nextScene` is set returns `LOOP_NEXT_SCENE_CONFLICT` — set `nextScene: null` first.

**Position coordinates:** Use the project's current resolution — full frame is `format.resolution` from Get project details (for example 1920x1080 for `16:9_1080p`).

**Auto-sync:** If the project has auto-sync enabled and is live, changes are automatically pushed to the stream. The response includes `synced: true/false`.

## Path parameters

- `id` string, required
- `layerId` string, required

## Request body

- UpdateLayerRequest: All fields are optional — send only what you want to change. See the endpoint description for which settings apply to each layer type.
  - `name` string: Layer name (1-19 characters)
  - `hide` boolean: Hide the layer from view
  - `pinned` boolean: Show layer on all scenes (not just current scene)
  - `locked` boolean: Prevent layer from being edited in UI
  - `position` object: Layer position and size in pixels of the project's resolution at the time of the request. Full frame is `x: 0, y: 0` with the width and height of `format.resolution` from Get project details (for example 1920x1080 for `16:9_1080p`). Values outside the frame are accepted. **Set the project's format before creating or updating layers.** A later resolution change does not resize layers: they keep their size relative to the frame, and their values scale. For example, 1920x1080 sent to a `16:9_720p` project is 1.5 times the frame, and stays that way after a switch to `16:9_1080p` (it reads back as 2880x1620).
    - `x` number: X position from left edge (pixels)
    - `y` number: Y position from top edge (pixels)
    - `width` number: Layer width in pixels
    - `height` number: Layer height in pixels
  - `settings` object: Layer-specific settings. Available fields depend on the layer type. **Video layers (`type: "video"`):** `fileId`, `volume`, `loop`, `nextScene` **Playlist layers (`type: "videoPlaylist"` or `"audioPlaylist"`):** `volume`, `loop`, `nextScene`, `files`, `showFileName`, `showProgressBar`, `textStylePreset`, `textStyles`, plus type-specific fields
    - `fileId` string: Video file ID to use for the layer (**video layers only**). The file must be a video owned by the authenticated user. Changing the file resets playback state (isPlaying, duration, etc.).
    - `volume` integer: Audio volume (0=muted, 10=max)
    - `loop` boolean: Loop when playback ends. Mutually exclusive with nextScene.
    - `nextScene` string, nullable: Scene ID (24-char hex) to auto-switch to when playback ends. Set to `null` to disable. Mutually exclusive with loop.
    - `showFileName` boolean: Display file name overlay
    - `showProgressBar` boolean: Show playback progress bar
    - `namePosition` 'bottom left' | 'top left' | 'bottom right' | 'top right' | 'center top' | 'center bottom', nullable: Position of filename overlay (videoPlaylist only)
    - `showCoverImage` boolean: Display album art/cover image (audioPlaylist only)
    - `coverImageSize` integer: Size of cover image in pixels (audioPlaylist only)
    - `shuffle` boolean: Enable shuffle/random playback order (audioPlaylist & videoPlaylist). Server auto-generates seed and resets position.
    - `adPlaceholder` object, nullable: Video placeholder during ad breaks (videoPlaylist only). Set `enabled: true` with a `fileId` to activate. Set `enabled: false` or `null` to disable/remove.
      - `enabled` boolean, required: Enable or disable the ad placeholder
      - `fileId` string: ID of a video file to use as placeholder (required when enabled=true)
    - `textStylePreset` 'preset_simple' | 'glassmorphism' | 'gradient_modern' | 'professional' | 'preset1' | 'neon_glow' | 'elegant_serif' | 'dark_contrast' | 'retro_80s' | 'preset6' | 'preset5' | 'preset4' | 'sport_dynamic': Text style preset. The API expands the preset into complete style values (font, colors, effects, etc.) on the server, replacing all existing text styles. If `textStyles` are also provided, they override the preset defaults.
    - `textStyles` object: Custom text styling for file name overlay. When sent with `textStylePreset`, these values override the preset defaults. When sent alone, only the specified fields change — existing values are preserved. **Colors:** Accept RGBA object `{ r: 255, g: 255, b: 255, a: 1 }` or string `"#FFFFFF"`.
      - `fontFamily` string: Font family from allowed list
      - `fontSize` integer
      - `fontWeight` integer
      - `color` union
        - object: RGBA color object (preferred)
          - `r` integer
          - `g` integer
          - `b` integer
          - `a` number
        - string: Hex (#RGB,
      - `backgroundColor` union
        - object
          - `r` integer
          - `g` integer
          - `b` integer
          - `a` number
        - string
      - `textAlign` 'left' | 'center' | 'right'
      - `padding` number
      - `borderRadius` number
      - `margin` number: Edge spacing in pixels
      - `letterSpacing` number
      - `textTransform` 'uppercase' | 'lowercase' | 'capitalize' | 'none'
      - `maxWidth` number
      - `backgroundGradient` string
      - `textShadow` object
        - `offsetX` number
        - `offsetY` number
        - `blur` number
        - `color` union
          - object
            - `r` integer
            - `g` integer
            - `b` integer
            - `a` number
          - string
      - `boxShadow` string
      - `border` object
        - `width` number
        - `color` union
          - object
            - `r` integer
            - `g` integer
            - `b` integer
            - `a` number
          - string
        - `style` 'solid' | 'dashed' | 'dotted' | 'none'
      - `backdropFilter` string
      - `bold` boolean
      - `italic` boolean
      - `underline` boolean
      - `crossed` boolean
    - `files` object[]: Playlist files (max 600). Replaces the entire playlist. **Configurable fields:** Only `fileId`, `name`, and `adPoints` can be set via this endpoint. **System-managed fields:** Response includes additional fields (`duration`, `isPlaying`, `playlistItemId`) that are read-only: - `duration` is automatically populated from file metadata - `isPlaying` is controlled via playback endpoints (`POST .../layers/{layerId}/play` and `.../stop`) - `playlistItemId` is a unique identifier for each playlist item To control playback, use the dedicated [Playback](#tag/Playback) endpoints instead of modifying this array.
      - `fileId` string, required: File ID from your library (must be owned by you)
      - `name` string: Custom display name. If omitted, uses the file's original name.
      - `adPoints` object[]: Ad break markers. Ad breaks fire when the broadcast streams to a YouTube channel connected through LiveReacting (OAuth), or when in-band ad markers (HLS/SRT SCTE-35, or native RTMP markers) are enabled. A custom RTMP stream key with neither cannot trigger YouTube ad breaks.
        - `timestamp` number, required: Start time in seconds (0 to file duration)
        - `duration` number, required: Duration in seconds (5-120, no overlap allowed)

## Response `200`

Layer updated successfully

- object
  - `layer` union
    - VideoPlaylistLayerDetail: Video playlist layer with multiple video files.
      - `id` string: Unique layer identifier
      - `name` string, nullable: Layer name
      - `hide` boolean: Whether layer is hidden
      - `pinned` boolean: Whether layer appears on all scenes
      - `locked` boolean: Whether layer is locked from editing
      - `position` object: Layer position and size in pixels of the project's current resolution. After a resolution change (for example 720p to 1080p), the values are scaled to the new one.
        - `x` number
        - `y` number
        - `width` number: Width in native resolution (e.g., 1920 for full-width on 1080p)
        - `height` number: Height in native resolution (e.g., 1080 for full-height on 1080p)
      - `type` 'videoPlaylist', required: Layer type identifier
      - `settings` object, required
        - `volume` integer: Audio volume (0-10)
        - `loop` boolean: Loop playlist when it ends
        - `nextScene` string, nullable: Scene ID to switch to when playlist ends
        - `showFileName` boolean: Display file name overlay
        - `showProgressBar` boolean: Show playback progress bar
        - `namePosition` 'bottom left' | 'top left' | 'bottom right' | 'top right' | 'center top' | 'center bottom', nullable: Position of the file name overlay
        - `textStylePreset` 'preset_simple' | 'glassmorphism' | 'gradient_modern' | 'professional' | 'preset1' | 'neon_glow' | 'elegant_serif' | 'dark_contrast' | 'retro_80s' | 'preset6' | 'preset5' | 'preset4' | 'sport_dynamic': Text style preset for file name overlay
        - `textStyles` object: Custom text styling (see UpdateLayerRequest for full schema)
        - `shuffle` boolean: Enable shuffle/random playback order
        - `adPlaceholder` object, nullable: Video placeholder shown during ad breaks. Null when not configured or disabled.
          - `enabled` boolean, required: Whether the ad placeholder is active
          - `fileId` string, required: ID of the placeholder video file
          - `fileName` string, required: Name of the placeholder video file
          - `duration` number, required: Duration of the placeholder video in seconds
        - `files` PlaylistFileItem[], required: Playlist files
          - `playlistItemId` string: Unique playlist item ID. Use this with the play endpoint for precise targeting.
          - `fileId` string: Reference to original File model (24-char hex ID)
          - `name` string: File display name
          - `duration` number: Duration in seconds
          - `isPlaying` boolean: Whether file is currently playing
          - `adPoints` object[]: Ad break points within this video
            - `timestamp` number: Start time in seconds
            - `duration` number: Duration in seconds (5-120)
    - AudioPlaylistLayerDetail: Audio playlist layer with multiple audio files.
      - `id` string: Unique layer identifier
      - `name` string, nullable: Layer name
      - `hide` boolean: Whether layer is hidden
      - `pinned` boolean: Whether layer appears on all scenes
      - `locked` boolean: Whether layer is locked from editing
      - `position` object: Layer position and size in pixels of the project's current resolution. After a resolution change (for example 720p to 1080p), the values are scaled to the new one.
        - `x` number
        - `y` number
        - `width` number: Width in native resolution (e.g., 1920 for full-width on 1080p)
        - `height` number: Height in native resolution (e.g., 1080 for full-height on 1080p)
      - `type` 'audioPlaylist', required: Layer type identifier
      - `settings` object, required
        - `volume` integer: Audio volume (0-10)
        - `loop` boolean: Loop playlist when it ends
        - `nextScene` string, nullable: Scene ID to switch to when playlist ends
        - `showFileName` boolean: Display file name overlay
        - `showProgressBar` boolean: Show playback progress bar
        - `showCoverImage` boolean: Display album art/cover image
        - `coverImageSize` integer: Size of cover image in pixels
        - `shuffle` boolean: Enable shuffle/random playback order
        - `textStylePreset` 'preset_simple' | 'glassmorphism' | 'gradient_modern' | 'professional' | 'preset1' | 'neon_glow' | 'elegant_serif' | 'dark_contrast' | 'retro_80s' | 'preset6' | 'preset5' | 'preset4' | 'sport_dynamic': Text style preset for file name overlay
        - `textStyles` object: Custom text styling (see UpdateLayerRequest for full schema)
        - `files` AudioPlaylistFileItem[], required: Playlist files
          - `playlistItemId` string: Unique playlist item ID
          - `fileId` string: Reference to original File model
          - `name` string: File display name
          - `duration` number: Duration in seconds
          - `isPlaying` boolean: Whether file is currently playing
    - VideoLayerDetail: Video layer with a single video file.
      - `id` string: Unique layer identifier
      - `name` string, nullable: Layer name
      - `hide` boolean: Whether layer is hidden
      - `pinned` boolean: Whether layer appears on all scenes
      - `locked` boolean: Whether layer is locked from editing
      - `position` object: Layer position and size in pixels of the project's current resolution. After a resolution change (for example 720p to 1080p), the values are scaled to the new one.
        - `x` number
        - `y` number
        - `width` number: Width in native resolution (e.g., 1920 for full-width on 1080p)
        - `height` number: Height in native resolution (e.g., 1080 for full-height on 1080p)
      - `type` 'video', required: Layer type identifier
      - `settings` object, required
        - `fileId` string, required: Video file ID (required)
        - `fileName` string, nullable: Video file name
        - `volume` integer: Audio volume (0-10)
        - `loop` boolean: Loop video when it ends
        - `nextScene` string, nullable: Scene ID to switch to when video ends. Cannot be used with loop=true.
        - `isPlaying` boolean: Current playback state (read-only)
        - `duration` number: Duration in seconds (read-only)
  - `synced` boolean: Whether changes were pushed to the live stream

## Other responses

- `400`: Validation error
- `401`: Authentication failed
- `404`: Project, layer, or file not found
- `429`: Rate limit exceeded

---

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