openapi: 3.0.3
info:
  title: 'Upstream.so API'
  description: "The Upstream.so API lets you create and run streams, manage your media library, and multistream to every platform — straight from your own code.\n\nThe Upstream.so API is organized around REST. It has predictable, resource-oriented URLs, accepts and returns JSON, and uses standard HTTP status codes, authentication, and verbs.\n\n<aside>As you scroll, you'll see ready-to-run code examples on the right (or inline on mobile). Use the tabs at the top right to switch between cURL, JavaScript, PHP and Python.</aside>\n\n## Response format\n\nEvery successful response wraps its payload in a `data` key:\n\n- A single resource returns a `data` **object**: `{\"data\": { ... }}`.\n- A collection returns a `data` **array**: `{\"data\": [ ... ]}`.\n\nRead your values from `data` — for example `response.data.id`, not `response.id`.\n\n## Pagination\n\nList endpoints that can grow — streams, media files, folders, and the stream queues — are paginated. Use the `page` and `per_page` (1–100, default 15) query parameters to page through them. Each paginated response includes two objects alongside `data`:\n\n- `links` — `first`, `last`, `prev` and `next` page URLs (`prev` and `next` are `null` at the ends).\n- `meta` — page counters: `current_page`, `last_page`, `per_page`, `total`, `from`, and `to`.\n\nShort, fixed lists — your tags and a stream's destinations — are returned in full and are not paginated.\n\n## Errors\n\nThe API uses standard HTTP status codes to indicate success or failure. Every error response includes a `message`, and validation errors (`422`) also include a field-keyed `errors` object.\n\n| Status | Meaning | Example body |\n|--------|---------|--------------|\n| `401` | Missing or invalid token | `{\"message\": \"Unauthenticated.\"}` |\n| `403` | Authenticated, but not allowed | `{\"message\": \"This action is unauthorized.\"}` |\n| `404` | Resource not found | `{\"message\": \"Resource not found.\"}` |\n| `405` | Method not allowed | `{\"message\": \"Method not allowed.\"}` |\n| `409` | Conflict with the resource's current state | `{\"message\": \"Stream cannot be started from its current state (installing).\"}` |\n| `422` | Validation failed | `{\"message\": \"The key field is required.\", \"errors\": {\"key\": [\"The key field is required.\"]}}` |\n| `429` | Rate limit exceeded | `{\"message\": \"Too Many Attempts.\"}` |\n| `500` | Unexpected server error | `{\"message\": \"Server Error.\"}` |\n\n## Rate limiting\n\nRequests are limited to 60 per minute per account. Each response includes `X-RateLimit-Limit` and `X-RateLimit-Remaining` headers. When you exceed the limit, the API returns a `429` response with a `Retry-After` header indicating how many seconds to wait before retrying.\n\n## Versioning\n\nThe current version is `v1`. Backwards-compatible changes — such as new endpoints and new optional fields — may be added at any time, so build your client to ignore fields it doesn't recognize. Any breaking change is released under a new version path."
  version: 1.0.0
servers:
  -
    url: 'https://studio.upstream.so'
tags:
  -
    name: Account
    description: ''
  -
    name: Streams
    description: ''
  -
    name: Multistreaming
    description: ''
  -
    name: Media
    description: ''
  -
    name: Folders
    description: ''
  -
    name: Tags
    description: ''
components:
  securitySchemes:
    default:
      type: http
      scheme: bearer
      description: 'Create an API key in your dashboard under <b>Account Settings → API Keys</b>, then send it as a bearer token in the `Authorization` header of every request: `Authorization: Bearer YOUR_API_TOKEN`.'
security:
  -
    default: []
paths:
  /api/v1/user:
    get:
      summary: 'Get the authenticated user'
      operationId: getTheAuthenticatedUser
      description: 'Returns the account that owns the API token used for this request.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1eb-15bb-439a-98e0-baa04e14c3b7
                    name: 'Dr. Enoch Harber II'
                    email: murazik.kacey@example.net
                    created_at: '2026-08-11T11:05:34+00:00'
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1eb-15bb-439a-98e0-baa04e14c3b7
                        description: "The account's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Dr. Enoch Harber II'
                        description: "The account holder's name."
                      email:
                        type: string
                        example: murazik.kacey@example.net
                        description: "The account's email address."
                      created_at:
                        type: string
                        example: '2026-08-11T11:05:34+00:00'
                        description: 'ISO 8601 time the account was created.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
      tags:
        - Account
  /api/v1/streams:
    get:
      summary: 'List streams'
      operationId: listStreams
      description: "Returns the streams owned by the authenticated account, paginated. Response\nfields are documented on the \"Get a stream\" endpoint (same resource shape)."
      parameters:
        -
          in: query
          name: page
          description: 'The page number to return. Defaults to 1.'
          example: 1
          required: false
          schema:
            type: integer
            description: 'The page number to return. Defaults to 1.'
            example: 1
        -
          in: query
          name: per_page
          description: 'Number of streams per page (1–100). Defaults to 15.'
          example: 15
          required: false
          schema:
            type: integer
            description: 'Number of streams per page (1–100). Defaults to 15.'
            example: 15
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: a279f1eb-d873-4efd-b098-6377ef09c61c
                      name: 'Annamarie Auer'
                      description: null
                      platform: youtube
                      type: video
                      url: dQw4w9WgXcQ
                      status: active
                      thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                      tags:
                        - lofi
                        - chill
                      encoding:
                        resolution: 1920x1080
                        frame_rate: '30'
                        bitrate: 8000
                        audio_bitrate: 128
                      volumes:
                        main: 70
                        secondary: 30
                        video: 100
                      playback:
                        mode: loop
                        video_order: loop
                        audio_order: loop
                        default_image_duration: 10
                      transitions:
                        fade_duration: 2
                        animation_type: null
                        animation_duration: null
                      video_fit:
                        object_fit: null
                        style: null
                        background_color: null
                      schedule:
                        is_scheduled: false
                        scheduled_at: null
                        is_scheduled_end: false
                        scheduled_end_at: null
                        repeat_schedule: false
                        mode: null
                        continuous_start_type: null
                        continuous_stop_type: null
                        continuous_stop_at: null
                        stream_duration_hours: null
                        stream_duration_minutes: null
                        break_duration_hours: null
                        break_duration_minutes: null
                        preserve_state: false
                      recording: null
                      multistream_destinations: []
                      started_at: null
                      created_at: '2026-08-11T11:05:35+00:00'
                      updated_at: '2026-08-11T11:05:35+00:00'
                    -
                      id: a279f1ec-c51c-4553-a18b-599ae6551bc5
                      name: 'Ruben Pouros'
                      description: null
                      platform: youtube
                      type: video
                      url: dQw4w9WgXcQ
                      status: active
                      thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                      tags:
                        - lofi
                        - chill
                      encoding:
                        resolution: 1920x1080
                        frame_rate: '30'
                        bitrate: 8000
                        audio_bitrate: 128
                      volumes:
                        main: 70
                        secondary: 30
                        video: 100
                      playback:
                        mode: loop
                        video_order: loop
                        audio_order: loop
                        default_image_duration: 10
                      transitions:
                        fade_duration: 2
                        animation_type: null
                        animation_duration: null
                      video_fit:
                        object_fit: null
                        style: null
                        background_color: null
                      schedule:
                        is_scheduled: false
                        scheduled_at: null
                        is_scheduled_end: false
                        scheduled_end_at: null
                        repeat_schedule: false
                        mode: null
                        continuous_start_type: null
                        continuous_stop_type: null
                        continuous_stop_at: null
                        stream_duration_hours: null
                        stream_duration_minutes: null
                        break_duration_hours: null
                        break_duration_minutes: null
                        preserve_state: false
                      recording: null
                      multistream_destinations: []
                      started_at: null
                      created_at: '2026-08-11T11:05:35+00:00'
                      updated_at: '2026-08-11T11:05:35+00:00'
                  links:
                    first: '/?page=1'
                    last: '/?page=1'
                    prev: null
                    next: null
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 1
                    path: /
                    per_page: 15
                    to: 2
                    total: 2
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: a279f1eb-d873-4efd-b098-6377ef09c61c
                        name: 'Annamarie Auer'
                        description: null
                        platform: youtube
                        type: video
                        url: dQw4w9WgXcQ
                        status: active
                        thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                        tags:
                          - lofi
                          - chill
                        encoding:
                          resolution: 1920x1080
                          frame_rate: '30'
                          bitrate: 8000
                          audio_bitrate: 128
                        volumes:
                          main: 70
                          secondary: 30
                          video: 100
                        playback:
                          mode: loop
                          video_order: loop
                          audio_order: loop
                          default_image_duration: 10
                        transitions:
                          fade_duration: 2
                          animation_type: null
                          animation_duration: null
                        video_fit:
                          object_fit: null
                          style: null
                          background_color: null
                        schedule:
                          is_scheduled: false
                          scheduled_at: null
                          is_scheduled_end: false
                          scheduled_end_at: null
                          repeat_schedule: false
                          mode: null
                          continuous_start_type: null
                          continuous_stop_type: null
                          continuous_stop_at: null
                          stream_duration_hours: null
                          stream_duration_minutes: null
                          break_duration_hours: null
                          break_duration_minutes: null
                          preserve_state: false
                        recording: null
                        multistream_destinations: []
                        started_at: null
                        created_at: '2026-08-11T11:05:35+00:00'
                        updated_at: '2026-08-11T11:05:35+00:00'
                      -
                        id: a279f1ec-c51c-4553-a18b-599ae6551bc5
                        name: 'Ruben Pouros'
                        description: null
                        platform: youtube
                        type: video
                        url: dQw4w9WgXcQ
                        status: active
                        thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                        tags:
                          - lofi
                          - chill
                        encoding:
                          resolution: 1920x1080
                          frame_rate: '30'
                          bitrate: 8000
                          audio_bitrate: 128
                        volumes:
                          main: 70
                          secondary: 30
                          video: 100
                        playback:
                          mode: loop
                          video_order: loop
                          audio_order: loop
                          default_image_duration: 10
                        transitions:
                          fade_duration: 2
                          animation_type: null
                          animation_duration: null
                        video_fit:
                          object_fit: null
                          style: null
                          background_color: null
                        schedule:
                          is_scheduled: false
                          scheduled_at: null
                          is_scheduled_end: false
                          scheduled_end_at: null
                          repeat_schedule: false
                          mode: null
                          continuous_start_type: null
                          continuous_stop_type: null
                          continuous_stop_at: null
                          stream_duration_hours: null
                          stream_duration_minutes: null
                          break_duration_hours: null
                          break_duration_minutes: null
                          preserve_state: false
                        recording: null
                        multistream_destinations: []
                        started_at: null
                        created_at: '2026-08-11T11:05:35+00:00'
                        updated_at: '2026-08-11T11:05:35+00:00'
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: a279f1eb-d873-4efd-b098-6377ef09c61c
                          description: "The stream's unique identifier (UUID)."
                        name:
                          type: string
                          example: 'Annamarie Auer'
                          description: "The stream's display name."
                        description:
                          type: string
                          example: null
                          description: "The stream's description. Nullable."
                        platform:
                          type: string
                          example: youtube
                          description: 'Destination platform. One of: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP endpoint), customsrt (custom SRT endpoint).'
                        type:
                          type: string
                          example: video
                          description: 'Content type. `static` = a single image/background, `video` = a playlist of pre-recorded videos played in sequence, `live` = live input from browser participants or RTMP ingest.'
                        url:
                          type: string
                          example: dQw4w9WgXcQ
                          description: 'Platform-specific broadcast identifier (e.g. the YouTube video ID or Twitch channel login) — not a full URL. Nullable.'
                        status:
                          type: string
                          example: active
                          description: 'Lifecycle state. One of: installing (server provisioning), booting (server starting up), active (live and broadcasting), paused (output paused), inactive (stopped cleanly), failed (fatal error), syncing (multi-stream sync in progress).'
                        thumbnail_url:
                          type: string
                          example: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                          description: "Full URL to the stream's thumbnail image. Nullable."
                        tags:
                          type: array
                          example:
                            - lofi
                            - chill
                          description: 'Tag names assigned to the stream.'
                          items:
                            type: string
                        encoding:
                          type: object
                          properties:
                            resolution:
                              type: string
                              example: 1920x1080
                              description: 'Output resolution as "{width}x{height}" (e.g. "1920x1080"). A portrait value such as "1080x1920" denotes vertical orientation.'
                            frame_rate:
                              type: string
                              example: '30'
                              description: 'Output frame rate in frames per second.'
                            bitrate:
                              type: integer
                              example: 8000
                              description: 'Target video bitrate in kbps. Nullable.'
                            audio_bitrate:
                              type: integer
                              example: 128
                              description: 'Audio bitrate in kbps. Nullable.'
                        volumes:
                          type: object
                          properties:
                            main:
                              type: integer
                              example: 70
                              description: 'Primary audio channel volume (0–100).'
                            secondary:
                              type: integer
                              example: 30
                              description: 'Secondary audio channel volume (0–100).'
                            video:
                              type: integer
                              example: 100
                              description: 'Background-video audio volume (0–100).'
                        playback:
                          type: object
                          properties:
                            mode:
                              type: string
                              example: loop
                              description: 'Whole-stream playback mode. `loop` plays the content on repeat; `single` plays it once then pauses.'
                            video_order:
                              type: string
                              example: loop
                              description: 'Background video playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                            audio_order:
                              type: string
                              example: loop
                              description: 'Audio playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                            default_image_duration:
                              type: integer
                              example: 10
                              description: 'Seconds each image is displayed when part of the video playlist.'
                        transitions:
                          type: object
                          properties:
                            fade_duration:
                              type: integer
                              example: 2
                              description: 'Audio crossfade duration in seconds (0–20) when switching tracks.'
                            animation_type:
                              type: string
                              example: null
                              description: 'Visual transition between clips. One of: fade, slide, scale, swipeAway, random — or null for no transition.'
                            animation_duration:
                              type: string
                              example: null
                              description: 'Transition animation duration in seconds (0–20). Null when no transition is set.'
                        video_fit:
                          type: object
                          properties:
                            object_fit:
                              type: string
                              example: null
                              description: 'How the video fills the frame: `cover` or `contain`. Nullable.'
                            style:
                              type: string
                              example: null
                              description: 'Fill behaviour when the video does not match the frame aspect ratio: `solid_color` or `blur`. Nullable.'
                            background_color:
                              type: string
                              example: null
                              description: 'Hex colour (#RGB, #RRGGBB or #RRGGBBAA) shown behind the video when style is `solid_color`. Nullable.'
                        schedule:
                          type: object
                          properties:
                            is_scheduled:
                              type: boolean
                              example: false
                              description: 'Whether the stream has a scheduled start time.'
                            scheduled_at:
                              type: string
                              example: null
                              description: 'ISO 8601 scheduled start time. Nullable.'
                            is_scheduled_end:
                              type: boolean
                              example: false
                              description: 'Whether the stream has a scheduled end time.'
                            scheduled_end_at:
                              type: string
                              example: null
                              description: 'ISO 8601 scheduled end time. Nullable.'
                            repeat_schedule:
                              type: boolean
                              example: false
                              description: 'Whether the schedule recurs.'
                            mode:
                              type: string
                              example: null
                              description: 'Scheduling mode. `continuous` for back-to-back cycles separated by breaks; null for a one-off or recurring schedule.'
                            continuous_start_type:
                              type: string
                              example: null
                              description: 'For continuous mode, how each cycle starts: `now` or `scheduled`. Nullable.'
                            continuous_stop_type:
                              type: string
                              example: null
                              description: 'For continuous mode, how the run stops: `never` or `scheduled`. Nullable.'
                            continuous_stop_at:
                              type: string
                              example: null
                              description: 'ISO 8601 time the continuous run stops. Nullable.'
                            stream_duration_hours:
                              type: string
                              example: null
                              description: 'Active streaming hours per continuous cycle. Nullable.'
                            stream_duration_minutes:
                              type: string
                              example: null
                              description: 'Active streaming minutes per continuous cycle. Nullable.'
                            break_duration_hours:
                              type: string
                              example: null
                              description: 'Break hours between continuous cycles. Nullable.'
                            break_duration_minutes:
                              type: string
                              example: null
                              description: 'Break minutes between continuous cycles. Nullable.'
                            preserve_state:
                              type: boolean
                              example: false
                              description: 'Whether playback position resumes after a continuous cycle restart.'
                        recording:
                          type: string
                          example: null
                          description: 'Recording settings. Present only when the recording feature is enabled for the stream; otherwise null.'
                        multistream_destinations:
                          type: array
                          example: []
                          description: 'Additional broadcast destinations. Stream keys are never exposed.'
                        started_at:
                          type: string
                          example: null
                          description: 'ISO 8601 time the stream was last started. Nullable.'
                        created_at:
                          type: string
                          example: '2026-08-11T11:05:35+00:00'
                          description: 'ISO 8601 creation time.'
                        updated_at:
                          type: string
                          example: '2026-08-11T11:05:35+00:00'
                          description: 'ISO 8601 last update time.'
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                        example: '/?page=1'
                      last:
                        type: string
                        example: '/?page=1'
                      prev:
                        type: string
                        example: null
                        nullable: true
                      next:
                        type: string
                        example: null
                        nullable: true
                    description: 'Pagination URLs: `first`, `last`, `prev`, `next`.'
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                        example: 1
                      from:
                        type: integer
                        example: 1
                      last_page:
                        type: integer
                        example: 1
                      path:
                        type: string
                        example: /
                      per_page:
                        type: integer
                        example: 15
                      to:
                        type: integer
                        example: 2
                      total:
                        type: integer
                        example: 2
                    description: 'Pagination counters: `current_page`, `last_page`, `per_page`, `total`, `from`, `to`.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
      tags:
        - Streams
    post:
      summary: 'Create a stream'
      operationId: createAStream
      description: "Creates a stream owned by the authenticated account. The `key` (stream key) is\nrequired for every platform — for `custom` it must start with rtmp:// or rtmps://\nand for `customsrt` with srt://. Settings groups (volumes, playback, transitions,\nvideo_fit, schedule, recording) are optional and default sensibly when omitted.\n`status` is managed by the start/stop endpoints and cannot be set here. Returns `201 Created`."
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1ed-e191-462e-b4d7-68c3cf7a989e
                    name: 'Jaylan Lakin'
                    description: null
                    platform: youtube
                    type: video
                    url: dQw4w9WgXcQ
                    status: installing
                    thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                    tags:
                      - lofi
                      - chill
                    encoding:
                      resolution: 1920x1080
                      frame_rate: '30'
                      bitrate: 8000
                      audio_bitrate: 128
                    volumes:
                      main: 70
                      secondary: 30
                      video: 100
                    playback:
                      mode: loop
                      video_order: loop
                      audio_order: loop
                      default_image_duration: 10
                    transitions:
                      fade_duration: 2
                      animation_type: null
                      animation_duration: null
                    video_fit:
                      object_fit: null
                      style: null
                      background_color: null
                    schedule:
                      is_scheduled: false
                      scheduled_at: null
                      is_scheduled_end: false
                      scheduled_end_at: null
                      repeat_schedule: false
                      mode: null
                      continuous_start_type: null
                      continuous_stop_type: null
                      continuous_stop_at: null
                      stream_duration_hours: null
                      stream_duration_minutes: null
                      break_duration_hours: null
                      break_duration_minutes: null
                      preserve_state: false
                    recording: null
                    multistream_destinations: []
                    started_at: null
                    created_at: '2026-08-11T11:05:36+00:00'
                    updated_at: '2026-08-11T11:05:36+00:00'
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1ed-e191-462e-b4d7-68c3cf7a989e
                        description: "The stream's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Jaylan Lakin'
                        description: "The stream's display name."
                      description:
                        type: string
                        example: null
                        description: "The stream's description. Nullable."
                      platform:
                        type: string
                        example: youtube
                        description: 'Destination platform. One of: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP endpoint), customsrt (custom SRT endpoint).'
                      type:
                        type: string
                        example: video
                        description: 'Content type. `static` = a single image/background, `video` = a playlist of pre-recorded videos played in sequence, `live` = live input from browser participants or RTMP ingest.'
                      url:
                        type: string
                        example: dQw4w9WgXcQ
                        description: 'Platform-specific broadcast identifier (e.g. the YouTube video ID or Twitch channel login) — not a full URL. Nullable.'
                      status:
                        type: string
                        example: installing
                        description: 'Lifecycle state. One of: installing (server provisioning), booting (server starting up), active (live and broadcasting), paused (output paused), inactive (stopped cleanly), failed (fatal error), syncing (multi-stream sync in progress).'
                      thumbnail_url:
                        type: string
                        example: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                        description: "Full URL to the stream's thumbnail image. Nullable."
                      tags:
                        type: array
                        example:
                          - lofi
                          - chill
                        description: 'Tag names assigned to the stream.'
                        items:
                          type: string
                      encoding:
                        type: object
                        properties:
                          resolution:
                            type: string
                            example: 1920x1080
                            description: 'Output resolution as "{width}x{height}" (e.g. "1920x1080"). A portrait value such as "1080x1920" denotes vertical orientation.'
                          frame_rate:
                            type: string
                            example: '30'
                            description: 'Output frame rate in frames per second.'
                          bitrate:
                            type: integer
                            example: 8000
                            description: 'Target video bitrate in kbps. Nullable.'
                          audio_bitrate:
                            type: integer
                            example: 128
                            description: 'Audio bitrate in kbps. Nullable.'
                      volumes:
                        type: object
                        properties:
                          main:
                            type: integer
                            example: 70
                            description: 'Primary audio channel volume (0–100).'
                          secondary:
                            type: integer
                            example: 30
                            description: 'Secondary audio channel volume (0–100).'
                          video:
                            type: integer
                            example: 100
                            description: 'Background-video audio volume (0–100).'
                      playback:
                        type: object
                        properties:
                          mode:
                            type: string
                            example: loop
                            description: 'Whole-stream playback mode. `loop` plays the content on repeat; `single` plays it once then pauses.'
                          video_order:
                            type: string
                            example: loop
                            description: 'Background video playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          audio_order:
                            type: string
                            example: loop
                            description: 'Audio playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          default_image_duration:
                            type: integer
                            example: 10
                            description: 'Seconds each image is displayed when part of the video playlist.'
                      transitions:
                        type: object
                        properties:
                          fade_duration:
                            type: integer
                            example: 2
                            description: 'Audio crossfade duration in seconds (0–20) when switching tracks.'
                          animation_type:
                            type: string
                            example: null
                            description: 'Visual transition between clips. One of: fade, slide, scale, swipeAway, random — or null for no transition.'
                          animation_duration:
                            type: string
                            example: null
                            description: 'Transition animation duration in seconds (0–20). Null when no transition is set.'
                      video_fit:
                        type: object
                        properties:
                          object_fit:
                            type: string
                            example: null
                            description: 'How the video fills the frame: `cover` or `contain`. Nullable.'
                          style:
                            type: string
                            example: null
                            description: 'Fill behaviour when the video does not match the frame aspect ratio: `solid_color` or `blur`. Nullable.'
                          background_color:
                            type: string
                            example: null
                            description: 'Hex colour (#RGB, #RRGGBB or #RRGGBBAA) shown behind the video when style is `solid_color`. Nullable.'
                      schedule:
                        type: object
                        properties:
                          is_scheduled:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled start time.'
                          scheduled_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled start time. Nullable.'
                          is_scheduled_end:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled end time.'
                          scheduled_end_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled end time. Nullable.'
                          repeat_schedule:
                            type: boolean
                            example: false
                            description: 'Whether the schedule recurs.'
                          mode:
                            type: string
                            example: null
                            description: 'Scheduling mode. `continuous` for back-to-back cycles separated by breaks; null for a one-off or recurring schedule.'
                          continuous_start_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how each cycle starts: `now` or `scheduled`. Nullable.'
                          continuous_stop_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how the run stops: `never` or `scheduled`. Nullable.'
                          continuous_stop_at:
                            type: string
                            example: null
                            description: 'ISO 8601 time the continuous run stops. Nullable.'
                          stream_duration_hours:
                            type: string
                            example: null
                            description: 'Active streaming hours per continuous cycle. Nullable.'
                          stream_duration_minutes:
                            type: string
                            example: null
                            description: 'Active streaming minutes per continuous cycle. Nullable.'
                          break_duration_hours:
                            type: string
                            example: null
                            description: 'Break hours between continuous cycles. Nullable.'
                          break_duration_minutes:
                            type: string
                            example: null
                            description: 'Break minutes between continuous cycles. Nullable.'
                          preserve_state:
                            type: boolean
                            example: false
                            description: 'Whether playback position resumes after a continuous cycle restart.'
                      recording:
                        type: string
                        example: null
                        description: 'Recording settings. Present only when the recording feature is enabled for the stream; otherwise null.'
                      multistream_destinations:
                        type: array
                        example: []
                        description: 'Additional broadcast destinations. Stream keys are never exposed.'
                      started_at:
                        type: string
                        example: null
                        description: 'ISO 8601 time the stream was last started. Nullable.'
                      created_at:
                        type: string
                        example: '2026-08-11T11:05:36+00:00'
                        description: 'ISO 8601 creation time.'
                      updated_at:
                        type: string
                        example: '2026-08-11T11:05:36+00:00'
                        description: 'ISO 8601 last update time.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: 'Stream limit reached'
                    type: object
                    example:
                      message: 'Stream limit reached (3). Upgrade your plan to add more streams.'
                    properties:
                      message:
                        type: string
                        example: 'Stream limit reached (3). Upgrade your plan to add more streams.'
                  -
                    description: 'Streaming access exhausted'
                    type: object
                    example:
                      message: "You've used up your streaming time. Upgrade your plan to keep streaming."
                    properties:
                      message:
                        type: string
                        example: "You've used up your streaming time. Upgrade your plan to keep streaming."
                  -
                    description: 'Acting as another account'
                    type: object
                    example:
                      message: 'Acting as another account is not supported on the API.'
                    properties:
                      message:
                        type: string
                        example: 'Acting as another account is not supported on the API.'
        422:
          description: 'Validation failed'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The key field is required.'
                  errors:
                    key:
                      - 'The key field is required.'
                properties:
                  message:
                    type: string
                    example: 'The key field is required.'
                  errors:
                    type: object
                    properties:
                      key:
                        type: array
                        example:
                          - 'The key field is required.'
                        items:
                          type: string
      tags:
        - Streams
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'Display name for the stream. Must not be greater than 100 characters.'
                  example: 'My 24/7 Lofi Stream'
                description:
                  type: string
                  description: 'Optional description. Must not be greater than 5000 characters.'
                  example: 'Relaxing beats, all day.'
                  nullable: true
                platform:
                  type: string
                  description: 'Destination platform: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP), customsrt (custom SRT).'
                  example: youtube
                  enum:
                    - youtube
                    - twitch
                    - facebook
                    - instagram
                    - mixcloud
                    - rumble
                    - kick
                    - custom
                    - customsrt
                type:
                  type: string
                  description: 'Content type: static (single image/background), video (playlist of pre-recorded videos), live (browser/RTMP input).'
                  example: video
                  enum:
                    - video
                    - static
                    - live
                url:
                  type: string
                  description: 'Optional platform broadcast identifier (e.g. YouTube video ID / Twitch channel login). Must not be greater than 500 characters.'
                  example: null
                  nullable: true
                key:
                  type: string
                  description: 'The stream key. Required when creating a stream; on update it is optional — omit it to keep the existing key. For platform=custom it must start with rtmp:// or rtmps://; for customsrt with srt://. Write-only — never returned.'
                  example: live2/abcd-efgh-ijkl
                encoding:
                  type: object
                  description: ''
                  example: null
                  properties:
                    resolution:
                      type: string
                      description: 'Output resolution "{width}x{height}". Portrait values (e.g. 1080x1920) stream vertically. 4K/2K values require an eligible plan. Defaults to 1920x1080.'
                      example: 1920x1080
                      enum:
                        - 1920x1080
                        - 1080x1920
                        - 1280x720
                        - 720x1280
                    frame_rate:
                      type: integer
                      description: 'Frames per second. 60 requires an eligible plan. Defaults to 30. Must be at least 1.'
                      example: 30
                    bitrate:
                      type: integer
                      description: 'Target video bitrate in kbps (500–12000; up to 30000 on 2K/4K plans). Defaults to 8000. Must be at least 500.'
                      example: 8000
                    audio_bitrate:
                      type: integer
                      description: 'Audio bitrate in kbps (128–328). Defaults to 128. Must be at least 128. Must not be greater than 328.'
                      example: 128
                volumes:
                  type: object
                  description: ''
                  example: null
                  properties:
                    main:
                      type: integer
                      description: 'Primary audio channel volume (0–100). Defaults to 70. Must be at least 0. Must not be greater than 100.'
                      example: 70
                    secondary:
                      type: integer
                      description: 'Secondary audio channel volume (0–100). Defaults to 30. Must be at least 0. Must not be greater than 100.'
                      example: 30
                    video:
                      type: integer
                      description: 'Background-video audio volume (0–100). Defaults to 100. Must be at least 0. Must not be greater than 100.'
                      example: 100
                playback:
                  type: object
                  description: ''
                  example: null
                  properties:
                    mode:
                      type: string
                      description: 'loop = play on repeat; single = play once then pause. Defaults to loop.'
                      example: loop
                      enum:
                        - loop
                        - single
                    video_order:
                      type: string
                      description: 'Background video order: loop (in order) or shuffle (random). Defaults to loop.'
                      example: loop
                      enum:
                        - loop
                        - shuffle
                    audio_order:
                      type: string
                      description: 'Audio order: loop (in order) or shuffle (random). Defaults to loop.'
                      example: loop
                      enum:
                        - loop
                        - shuffle
                    default_image_duration:
                      type: integer
                      description: 'Seconds each image shows when part of the video playlist. Defaults to 10. Must be at least 1. Must not be greater than 3600.'
                      example: 10
                transitions:
                  type: object
                  description: ''
                  example: null
                  properties:
                    fade_duration:
                      type: integer
                      description: 'Audio crossfade duration in seconds (0–20). Defaults to 2. Must be at least 0. Must not be greater than 20.'
                      example: 2
                    animation_type:
                      type: string
                      description: 'Visual transition between clips: fade, slide, scale, swipeAway, random — or null for none. Defaults to null.'
                      example: fade
                      enum:
                        - random
                        - fade
                        - slide
                        - scale
                        - swipeAway
                      nullable: true
                    animation_duration:
                      type: integer
                      description: 'Transition duration in seconds (0–20). Required when animation_type is set. Defaults to null. Must be at least 0. Must not be greater than 20.'
                      example: 1
                      nullable: true
                video_fit:
                  type: object
                  description: ''
                  example: null
                  properties:
                    object_fit:
                      type: string
                      description: 'How video fills the frame: cover or contain. Defaults to null (engine default).'
                      example: cover
                      enum:
                        - cover
                        - contain
                      nullable: true
                    style:
                      type: string
                      description: 'Fill when aspect ratios differ: solid_color or blur. Defaults to null.'
                      example: blur
                      enum:
                        - solid_color
                        - blur
                      nullable: true
                    background_color:
                      type: string
                      description: 'Hex colour (#RGB, #RRGGBB, #RRGGBBAA) used when style=solid_color. Defaults to null. Must match the regex /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.'
                      example: '#000000'
                      nullable: true
                schedule:
                  type: object
                  description: ''
                  example: null
                  properties:
                    is_scheduled:
                      type: boolean
                      description: 'Whether the stream has a scheduled start. Defaults to false.'
                      example: false
                    scheduled_at:
                      type: string
                      description: 'ISO 8601 scheduled start time. Defaults to null. Must be a valid date.'
                      example: null
                      nullable: true
                    is_scheduled_end:
                      type: boolean
                      description: 'Whether the stream has a scheduled end. Defaults to false.'
                      example: false
                    scheduled_end_at:
                      type: string
                      description: 'ISO 8601 scheduled end time. Defaults to null. Must be a valid date.'
                      example: null
                      nullable: true
                    repeat_schedule:
                      type: boolean
                      description: 'Whether the schedule recurs. Defaults to false.'
                      example: false
                    mode:
                      type: string
                      description: 'continuous for back-to-back cycles with breaks; null for one-off/recurring. The continuous_* and *_duration_* fields apply only when mode=continuous. Defaults to null.'
                      example: null
                      enum:
                        - continuous
                      nullable: true
                    continuous_start_type:
                      type: string
                      description: 'continuous mode only: now or scheduled.'
                      example: null
                      enum:
                        - now
                        - scheduled
                      nullable: true
                    continuous_stop_type:
                      type: string
                      description: 'continuous mode only: never or scheduled.'
                      example: null
                      enum:
                        - never
                        - scheduled
                      nullable: true
                    continuous_stop_at:
                      type: string
                      description: 'continuous mode only: ISO 8601 stop time. Must be a valid date.'
                      example: null
                      nullable: true
                    stream_duration_hours:
                      type: integer
                      description: 'continuous mode only: active hours per cycle (0–72). Active time per cycle must total at least 5 minutes. Must be at least 0. Must not be greater than 72.'
                      example: null
                    stream_duration_minutes:
                      type: integer
                      description: 'continuous mode only: active minutes per cycle (0–59). Active time per cycle must total at least 5 minutes. Must be at least 0. Must not be greater than 59.'
                      example: null
                    break_duration_hours:
                      type: integer
                      description: 'continuous mode only: break hours between cycles (0–72). Break per cycle must total at least 5 minutes. Must be at least 0. Must not be greater than 72.'
                      example: null
                    break_duration_minutes:
                      type: integer
                      description: 'continuous mode only: break minutes between cycles (0–59). Break per cycle must total at least 5 minutes. Must be at least 0. Must not be greater than 59.'
                      example: null
                    preserve_state:
                      type: boolean
                      description: 'continuous mode only: resume playback position after a cycle restart. Defaults to false.'
                      example: false
                recording:
                  type: object
                  description: ''
                  example: null
                  properties:
                    enabled:
                      type: boolean
                      description: 'Enable or disable recording. Only honoured when the recording feature is enabled for the account. Segment/maximum durations are system-managed and read-only. Defaults to false.'
                      example: false
                tags:
                  type: array
                  description: 'Must not be greater than 50 characters.'
                  example:
                    - vmqeopfuudtdsufvyvddq
                  items:
                    type: string
              required:
                - name
                - platform
                - key
  '/api/v1/streams/{id}':
    get:
      summary: 'Get a stream'
      operationId: getAStream
      description: 'Returns a single stream owned by the authenticated account.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1ee-f0a8-4de1-8095-f05c1bcc45f6
                    name: 'Dr. Enoch Harber II'
                    description: null
                    platform: youtube
                    type: video
                    url: dQw4w9WgXcQ
                    status: active
                    thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                    tags:
                      - lofi
                      - chill
                    encoding:
                      resolution: 1920x1080
                      frame_rate: '30'
                      bitrate: 8000
                      audio_bitrate: 128
                    volumes:
                      main: 70
                      secondary: 30
                      video: 100
                    playback:
                      mode: loop
                      video_order: loop
                      audio_order: loop
                      default_image_duration: 10
                    transitions:
                      fade_duration: 2
                      animation_type: null
                      animation_duration: null
                    video_fit:
                      object_fit: null
                      style: null
                      background_color: null
                    schedule:
                      is_scheduled: false
                      scheduled_at: null
                      is_scheduled_end: false
                      scheduled_end_at: null
                      repeat_schedule: false
                      mode: null
                      continuous_start_type: null
                      continuous_stop_type: null
                      continuous_stop_at: null
                      stream_duration_hours: null
                      stream_duration_minutes: null
                      break_duration_hours: null
                      break_duration_minutes: null
                      preserve_state: false
                    recording: null
                    multistream_destinations: []
                    started_at: null
                    created_at: '2026-08-11T11:05:37+00:00'
                    updated_at: '2026-08-11T11:05:37+00:00'
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1ee-f0a8-4de1-8095-f05c1bcc45f6
                        description: "The stream's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Dr. Enoch Harber II'
                        description: "The stream's display name."
                      description:
                        type: string
                        example: null
                        description: "The stream's description. Nullable."
                      platform:
                        type: string
                        example: youtube
                        description: 'Destination platform. One of: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP endpoint), customsrt (custom SRT endpoint).'
                      type:
                        type: string
                        example: video
                        description: 'Content type. `static` = a single image/background, `video` = a playlist of pre-recorded videos played in sequence, `live` = live input from browser participants or RTMP ingest.'
                      url:
                        type: string
                        example: dQw4w9WgXcQ
                        description: 'Platform-specific broadcast identifier (e.g. the YouTube video ID or Twitch channel login) — not a full URL. Nullable.'
                      status:
                        type: string
                        example: active
                        description: 'Lifecycle state. One of: installing (server provisioning), booting (server starting up), active (live and broadcasting), paused (output paused), inactive (stopped cleanly), failed (fatal error), syncing (multi-stream sync in progress).'
                      thumbnail_url:
                        type: string
                        example: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                        description: "Full URL to the stream's thumbnail image. Nullable."
                      tags:
                        type: array
                        example:
                          - lofi
                          - chill
                        description: 'Tag names assigned to the stream.'
                        items:
                          type: string
                      encoding:
                        type: object
                        properties:
                          resolution:
                            type: string
                            example: 1920x1080
                            description: 'Output resolution as "{width}x{height}" (e.g. "1920x1080"). A portrait value such as "1080x1920" denotes vertical orientation.'
                          frame_rate:
                            type: string
                            example: '30'
                            description: 'Output frame rate in frames per second.'
                          bitrate:
                            type: integer
                            example: 8000
                            description: 'Target video bitrate in kbps. Nullable.'
                          audio_bitrate:
                            type: integer
                            example: 128
                            description: 'Audio bitrate in kbps. Nullable.'
                      volumes:
                        type: object
                        properties:
                          main:
                            type: integer
                            example: 70
                            description: 'Primary audio channel volume (0–100).'
                          secondary:
                            type: integer
                            example: 30
                            description: 'Secondary audio channel volume (0–100).'
                          video:
                            type: integer
                            example: 100
                            description: 'Background-video audio volume (0–100).'
                      playback:
                        type: object
                        properties:
                          mode:
                            type: string
                            example: loop
                            description: 'Whole-stream playback mode. `loop` plays the content on repeat; `single` plays it once then pauses.'
                          video_order:
                            type: string
                            example: loop
                            description: 'Background video playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          audio_order:
                            type: string
                            example: loop
                            description: 'Audio playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          default_image_duration:
                            type: integer
                            example: 10
                            description: 'Seconds each image is displayed when part of the video playlist.'
                      transitions:
                        type: object
                        properties:
                          fade_duration:
                            type: integer
                            example: 2
                            description: 'Audio crossfade duration in seconds (0–20) when switching tracks.'
                          animation_type:
                            type: string
                            example: null
                            description: 'Visual transition between clips. One of: fade, slide, scale, swipeAway, random — or null for no transition.'
                          animation_duration:
                            type: string
                            example: null
                            description: 'Transition animation duration in seconds (0–20). Null when no transition is set.'
                      video_fit:
                        type: object
                        properties:
                          object_fit:
                            type: string
                            example: null
                            description: 'How the video fills the frame: `cover` or `contain`. Nullable.'
                          style:
                            type: string
                            example: null
                            description: 'Fill behaviour when the video does not match the frame aspect ratio: `solid_color` or `blur`. Nullable.'
                          background_color:
                            type: string
                            example: null
                            description: 'Hex colour (#RGB, #RRGGBB or #RRGGBBAA) shown behind the video when style is `solid_color`. Nullable.'
                      schedule:
                        type: object
                        properties:
                          is_scheduled:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled start time.'
                          scheduled_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled start time. Nullable.'
                          is_scheduled_end:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled end time.'
                          scheduled_end_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled end time. Nullable.'
                          repeat_schedule:
                            type: boolean
                            example: false
                            description: 'Whether the schedule recurs.'
                          mode:
                            type: string
                            example: null
                            description: 'Scheduling mode. `continuous` for back-to-back cycles separated by breaks; null for a one-off or recurring schedule.'
                          continuous_start_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how each cycle starts: `now` or `scheduled`. Nullable.'
                          continuous_stop_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how the run stops: `never` or `scheduled`. Nullable.'
                          continuous_stop_at:
                            type: string
                            example: null
                            description: 'ISO 8601 time the continuous run stops. Nullable.'
                          stream_duration_hours:
                            type: string
                            example: null
                            description: 'Active streaming hours per continuous cycle. Nullable.'
                          stream_duration_minutes:
                            type: string
                            example: null
                            description: 'Active streaming minutes per continuous cycle. Nullable.'
                          break_duration_hours:
                            type: string
                            example: null
                            description: 'Break hours between continuous cycles. Nullable.'
                          break_duration_minutes:
                            type: string
                            example: null
                            description: 'Break minutes between continuous cycles. Nullable.'
                          preserve_state:
                            type: boolean
                            example: false
                            description: 'Whether playback position resumes after a continuous cycle restart.'
                      recording:
                        type: string
                        example: null
                        description: 'Recording settings. Present only when the recording feature is enabled for the stream; otherwise null.'
                      multistream_destinations:
                        type: array
                        example: []
                        description: 'Additional broadcast destinations. Stream keys are never exposed.'
                      started_at:
                        type: string
                        example: null
                        description: 'ISO 8601 time the stream was last started. Nullable.'
                      created_at:
                        type: string
                        example: '2026-08-11T11:05:37+00:00'
                        description: 'ISO 8601 creation time.'
                      updated_at:
                        type: string
                        example: '2026-08-11T11:05:37+00:00'
                        description: 'ISO 8601 last update time.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Streams
    patch:
      summary: 'Update a stream'
      operationId: updateAStream
      description: "Partially updates a stream owned by the authenticated account — send only the\nfields you want to change (nested settings objects are merged, not replaced).\n`status` is managed by the start/stop endpoints and cannot be changed here, and\nmultistream destinations are managed via the Multistreaming endpoints."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1f0-075d-4b9a-85b7-281ba1e8b977
                    name: 'Jaylan Lakin'
                    description: null
                    platform: youtube
                    type: video
                    url: dQw4w9WgXcQ
                    status: active
                    thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                    tags:
                      - lofi
                      - chill
                    encoding:
                      resolution: 1920x1080
                      frame_rate: '30'
                      bitrate: 8000
                      audio_bitrate: 128
                    volumes:
                      main: 70
                      secondary: 30
                      video: 100
                    playback:
                      mode: loop
                      video_order: loop
                      audio_order: loop
                      default_image_duration: 10
                    transitions:
                      fade_duration: 2
                      animation_type: null
                      animation_duration: null
                    video_fit:
                      object_fit: null
                      style: null
                      background_color: null
                    schedule:
                      is_scheduled: false
                      scheduled_at: null
                      is_scheduled_end: false
                      scheduled_end_at: null
                      repeat_schedule: false
                      mode: null
                      continuous_start_type: null
                      continuous_stop_type: null
                      continuous_stop_at: null
                      stream_duration_hours: null
                      stream_duration_minutes: null
                      break_duration_hours: null
                      break_duration_minutes: null
                      preserve_state: false
                    recording: null
                    multistream_destinations: []
                    started_at: null
                    created_at: '2026-08-11T11:05:37+00:00'
                    updated_at: '2026-08-11T11:05:37+00:00'
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1f0-075d-4b9a-85b7-281ba1e8b977
                        description: "The stream's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Jaylan Lakin'
                        description: "The stream's display name."
                      description:
                        type: string
                        example: null
                        description: "The stream's description. Nullable."
                      platform:
                        type: string
                        example: youtube
                        description: 'Destination platform. One of: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP endpoint), customsrt (custom SRT endpoint).'
                      type:
                        type: string
                        example: video
                        description: 'Content type. `static` = a single image/background, `video` = a playlist of pre-recorded videos played in sequence, `live` = live input from browser participants or RTMP ingest.'
                      url:
                        type: string
                        example: dQw4w9WgXcQ
                        description: 'Platform-specific broadcast identifier (e.g. the YouTube video ID or Twitch channel login) — not a full URL. Nullable.'
                      status:
                        type: string
                        example: active
                        description: 'Lifecycle state. One of: installing (server provisioning), booting (server starting up), active (live and broadcasting), paused (output paused), inactive (stopped cleanly), failed (fatal error), syncing (multi-stream sync in progress).'
                      thumbnail_url:
                        type: string
                        example: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                        description: "Full URL to the stream's thumbnail image. Nullable."
                      tags:
                        type: array
                        example:
                          - lofi
                          - chill
                        description: 'Tag names assigned to the stream.'
                        items:
                          type: string
                      encoding:
                        type: object
                        properties:
                          resolution:
                            type: string
                            example: 1920x1080
                            description: 'Output resolution as "{width}x{height}" (e.g. "1920x1080"). A portrait value such as "1080x1920" denotes vertical orientation.'
                          frame_rate:
                            type: string
                            example: '30'
                            description: 'Output frame rate in frames per second.'
                          bitrate:
                            type: integer
                            example: 8000
                            description: 'Target video bitrate in kbps. Nullable.'
                          audio_bitrate:
                            type: integer
                            example: 128
                            description: 'Audio bitrate in kbps. Nullable.'
                      volumes:
                        type: object
                        properties:
                          main:
                            type: integer
                            example: 70
                            description: 'Primary audio channel volume (0–100).'
                          secondary:
                            type: integer
                            example: 30
                            description: 'Secondary audio channel volume (0–100).'
                          video:
                            type: integer
                            example: 100
                            description: 'Background-video audio volume (0–100).'
                      playback:
                        type: object
                        properties:
                          mode:
                            type: string
                            example: loop
                            description: 'Whole-stream playback mode. `loop` plays the content on repeat; `single` plays it once then pauses.'
                          video_order:
                            type: string
                            example: loop
                            description: 'Background video playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          audio_order:
                            type: string
                            example: loop
                            description: 'Audio playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          default_image_duration:
                            type: integer
                            example: 10
                            description: 'Seconds each image is displayed when part of the video playlist.'
                      transitions:
                        type: object
                        properties:
                          fade_duration:
                            type: integer
                            example: 2
                            description: 'Audio crossfade duration in seconds (0–20) when switching tracks.'
                          animation_type:
                            type: string
                            example: null
                            description: 'Visual transition between clips. One of: fade, slide, scale, swipeAway, random — or null for no transition.'
                          animation_duration:
                            type: string
                            example: null
                            description: 'Transition animation duration in seconds (0–20). Null when no transition is set.'
                      video_fit:
                        type: object
                        properties:
                          object_fit:
                            type: string
                            example: null
                            description: 'How the video fills the frame: `cover` or `contain`. Nullable.'
                          style:
                            type: string
                            example: null
                            description: 'Fill behaviour when the video does not match the frame aspect ratio: `solid_color` or `blur`. Nullable.'
                          background_color:
                            type: string
                            example: null
                            description: 'Hex colour (#RGB, #RRGGBB or #RRGGBBAA) shown behind the video when style is `solid_color`. Nullable.'
                      schedule:
                        type: object
                        properties:
                          is_scheduled:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled start time.'
                          scheduled_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled start time. Nullable.'
                          is_scheduled_end:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled end time.'
                          scheduled_end_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled end time. Nullable.'
                          repeat_schedule:
                            type: boolean
                            example: false
                            description: 'Whether the schedule recurs.'
                          mode:
                            type: string
                            example: null
                            description: 'Scheduling mode. `continuous` for back-to-back cycles separated by breaks; null for a one-off or recurring schedule.'
                          continuous_start_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how each cycle starts: `now` or `scheduled`. Nullable.'
                          continuous_stop_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how the run stops: `never` or `scheduled`. Nullable.'
                          continuous_stop_at:
                            type: string
                            example: null
                            description: 'ISO 8601 time the continuous run stops. Nullable.'
                          stream_duration_hours:
                            type: string
                            example: null
                            description: 'Active streaming hours per continuous cycle. Nullable.'
                          stream_duration_minutes:
                            type: string
                            example: null
                            description: 'Active streaming minutes per continuous cycle. Nullable.'
                          break_duration_hours:
                            type: string
                            example: null
                            description: 'Break hours between continuous cycles. Nullable.'
                          break_duration_minutes:
                            type: string
                            example: null
                            description: 'Break minutes between continuous cycles. Nullable.'
                          preserve_state:
                            type: boolean
                            example: false
                            description: 'Whether playback position resumes after a continuous cycle restart.'
                      recording:
                        type: string
                        example: null
                        description: 'Recording settings. Present only when the recording feature is enabled for the stream; otherwise null.'
                      multistream_destinations:
                        type: array
                        example: []
                        description: 'Additional broadcast destinations. Stream keys are never exposed.'
                      started_at:
                        type: string
                        example: null
                        description: 'ISO 8601 time the stream was last started. Nullable.'
                      created_at:
                        type: string
                        example: '2026-08-11T11:05:37+00:00'
                        description: 'ISO 8601 creation time.'
                      updated_at:
                        type: string
                        example: '2026-08-11T11:05:37+00:00'
                        description: 'ISO 8601 last update time.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        422:
          description: 'Validation failed'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The selected encoding.resolution is invalid.'
                  errors:
                    encoding.resolution:
                      - 'The selected encoding.resolution is invalid.'
                properties:
                  message:
                    type: string
                    example: 'The selected encoding.resolution is invalid.'
                  errors:
                    type: object
                    properties:
                      encoding.resolution:
                        type: array
                        example:
                          - 'The selected encoding.resolution is invalid.'
                        items:
                          type: string
      tags:
        - Streams
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'Display name for the stream. Must not be greater than 100 characters.'
                  example: 'My 24/7 Lofi Stream'
                description:
                  type: string
                  description: 'Optional description. Must not be greater than 5000 characters.'
                  example: 'Relaxing beats, all day.'
                  nullable: true
                platform:
                  type: string
                  description: 'Destination platform: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP), customsrt (custom SRT).'
                  example: youtube
                  enum:
                    - youtube
                    - twitch
                    - facebook
                    - instagram
                    - mixcloud
                    - rumble
                    - kick
                    - custom
                    - customsrt
                url:
                  type: string
                  description: 'Optional platform broadcast identifier (e.g. YouTube video ID / Twitch channel login). Must not be greater than 500 characters.'
                  example: null
                  nullable: true
                key:
                  type: string
                  description: 'The stream key. Required when creating a stream; on update it is optional — omit it to keep the existing key. For platform=custom it must start with rtmp:// or rtmps://; for customsrt with srt://. Write-only — never returned.'
                  example: live2/abcd-efgh-ijkl
                  nullable: true
                encoding:
                  type: object
                  description: ''
                  example: null
                  properties:
                    resolution:
                      type: string
                      description: 'Output resolution "{width}x{height}". Portrait values (e.g. 1080x1920) stream vertically. 4K/2K values require an eligible plan. Defaults to 1920x1080.'
                      example: 1920x1080
                      enum:
                        - 1920x1080
                        - 1080x1920
                        - 1280x720
                        - 720x1280
                    frame_rate:
                      type: integer
                      description: 'Frames per second. 60 requires an eligible plan. Defaults to 30. Must be at least 1.'
                      example: 30
                    bitrate:
                      type: integer
                      description: 'Target video bitrate in kbps (500–12000; up to 30000 on 2K/4K plans). Defaults to 8000. Must be at least 500.'
                      example: 8000
                    audio_bitrate:
                      type: integer
                      description: 'Audio bitrate in kbps (128–328). Defaults to 128. Must be at least 128. Must not be greater than 328.'
                      example: 128
                volumes:
                  type: object
                  description: ''
                  example: null
                  properties:
                    main:
                      type: integer
                      description: 'Primary audio channel volume (0–100). Defaults to 70. Must be at least 0. Must not be greater than 100.'
                      example: 70
                    secondary:
                      type: integer
                      description: 'Secondary audio channel volume (0–100). Defaults to 30. Must be at least 0. Must not be greater than 100.'
                      example: 30
                    video:
                      type: integer
                      description: 'Background-video audio volume (0–100). Defaults to 100. Must be at least 0. Must not be greater than 100.'
                      example: 100
                playback:
                  type: object
                  description: ''
                  example: null
                  properties:
                    mode:
                      type: string
                      description: 'loop = play on repeat; single = play once then pause. Defaults to loop.'
                      example: loop
                      enum:
                        - loop
                        - single
                    video_order:
                      type: string
                      description: 'Background video order: loop (in order) or shuffle (random). Defaults to loop.'
                      example: loop
                      enum:
                        - loop
                        - shuffle
                    audio_order:
                      type: string
                      description: 'Audio order: loop (in order) or shuffle (random). Defaults to loop.'
                      example: loop
                      enum:
                        - loop
                        - shuffle
                    default_image_duration:
                      type: integer
                      description: 'Seconds each image shows when part of the video playlist. Defaults to 10. Must be at least 1. Must not be greater than 3600.'
                      example: 10
                transitions:
                  type: object
                  description: ''
                  example: null
                  properties:
                    fade_duration:
                      type: integer
                      description: 'Audio crossfade duration in seconds (0–20). Defaults to 2. Must be at least 0. Must not be greater than 20.'
                      example: 2
                    animation_type:
                      type: string
                      description: 'Visual transition between clips: fade, slide, scale, swipeAway, random — or null for none. Defaults to null.'
                      example: fade
                      enum:
                        - random
                        - fade
                        - slide
                        - scale
                        - swipeAway
                      nullable: true
                    animation_duration:
                      type: integer
                      description: 'Transition duration in seconds (0–20). Required when animation_type is set. Defaults to null. Must be at least 0. Must not be greater than 20.'
                      example: 1
                      nullable: true
                video_fit:
                  type: object
                  description: ''
                  example: null
                  properties:
                    object_fit:
                      type: string
                      description: 'How video fills the frame: cover or contain. Defaults to null (engine default).'
                      example: cover
                      enum:
                        - cover
                        - contain
                      nullable: true
                    style:
                      type: string
                      description: 'Fill when aspect ratios differ: solid_color or blur. Defaults to null.'
                      example: blur
                      enum:
                        - solid_color
                        - blur
                      nullable: true
                    background_color:
                      type: string
                      description: 'Hex colour (#RGB, #RRGGBB, #RRGGBBAA) used when style=solid_color. Defaults to null. Must match the regex /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.'
                      example: '#000000'
                      nullable: true
                schedule:
                  type: object
                  description: ''
                  example: null
                  properties:
                    is_scheduled:
                      type: boolean
                      description: 'Whether the stream has a scheduled start. Defaults to false.'
                      example: false
                    scheduled_at:
                      type: string
                      description: 'ISO 8601 scheduled start time. Defaults to null. Must be a valid date.'
                      example: null
                      nullable: true
                    is_scheduled_end:
                      type: boolean
                      description: 'Whether the stream has a scheduled end. Defaults to false.'
                      example: false
                    scheduled_end_at:
                      type: string
                      description: 'ISO 8601 scheduled end time. Defaults to null. Must be a valid date.'
                      example: null
                      nullable: true
                    repeat_schedule:
                      type: boolean
                      description: 'Whether the schedule recurs. Defaults to false.'
                      example: false
                    mode:
                      type: string
                      description: 'continuous for back-to-back cycles with breaks; null for one-off/recurring. The continuous_* and *_duration_* fields apply only when mode=continuous. Defaults to null.'
                      example: null
                      enum:
                        - continuous
                      nullable: true
                    continuous_start_type:
                      type: string
                      description: 'continuous mode only: now or scheduled.'
                      example: null
                      enum:
                        - now
                        - scheduled
                      nullable: true
                    continuous_stop_type:
                      type: string
                      description: 'continuous mode only: never or scheduled.'
                      example: null
                      enum:
                        - never
                        - scheduled
                      nullable: true
                    continuous_stop_at:
                      type: string
                      description: 'continuous mode only: ISO 8601 stop time. Must be a valid date.'
                      example: null
                      nullable: true
                    stream_duration_hours:
                      type: integer
                      description: 'continuous mode only: active hours per cycle (0–72). Active time per cycle must total at least 5 minutes. Must be at least 0. Must not be greater than 72.'
                      example: null
                    stream_duration_minutes:
                      type: integer
                      description: 'continuous mode only: active minutes per cycle (0–59). Active time per cycle must total at least 5 minutes. Must be at least 0. Must not be greater than 59.'
                      example: null
                    break_duration_hours:
                      type: integer
                      description: 'continuous mode only: break hours between cycles (0–72). Break per cycle must total at least 5 minutes. Must be at least 0. Must not be greater than 72.'
                      example: null
                    break_duration_minutes:
                      type: integer
                      description: 'continuous mode only: break minutes between cycles (0–59). Break per cycle must total at least 5 minutes. Must be at least 0. Must not be greater than 59.'
                      example: null
                    preserve_state:
                      type: boolean
                      description: 'continuous mode only: resume playback position after a cycle restart. Defaults to false.'
                      example: false
                recording:
                  type: object
                  description: ''
                  example: null
                  properties:
                    enabled:
                      type: boolean
                      description: 'Enable or disable recording. Only honoured when the recording feature is enabled for the account. Segment/maximum durations are system-managed and read-only. Defaults to false.'
                      example: false
                tags:
                  type: array
                  description: 'Must not be greater than 50 characters.'
                  example:
                    - vmqeopfuudtdsufvyvddq
                  items:
                    type: string
    delete:
      summary: 'Delete a stream'
      operationId: deleteAStream
      description: "Permanently deletes a stream owned by the authenticated account (stops any live\nbroadcast and tears down associated resources). Returns an empty 204 response."
      parameters: []
      responses:
        204:
          description: Deleted
          content:
            text/plain:
              schema:
                type: string
                example: ''
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Streams
    parameters:
      -
        in: path
        name: id
        description: "The stream's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
  '/api/v1/streams/{stream_id}/start':
    post:
      summary: 'Start a stream'
      operationId: startAStream
      description: "Starts a stream owned by the authenticated account — moves it into the `booting`\nstate, after which the platform brings it live (status becomes `active` on its own).\nIdempotent: starting a stream that is already booting or active returns 200 with the\ncurrent stream and makes no change."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1f1-1b12-430a-9cd2-919bba59a2f5
                    name: 'Dr. Enoch Harber II'
                    description: null
                    platform: youtube
                    type: video
                    url: dQw4w9WgXcQ
                    status: booting
                    thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                    tags:
                      - lofi
                      - chill
                    encoding:
                      resolution: 1920x1080
                      frame_rate: '30'
                      bitrate: 8000
                      audio_bitrate: 128
                    volumes:
                      main: 70
                      secondary: 30
                      video: 100
                    playback:
                      mode: loop
                      video_order: loop
                      audio_order: loop
                      default_image_duration: 10
                    transitions:
                      fade_duration: 2
                      animation_type: null
                      animation_duration: null
                    video_fit:
                      object_fit: null
                      style: null
                      background_color: null
                    schedule:
                      is_scheduled: false
                      scheduled_at: null
                      is_scheduled_end: false
                      scheduled_end_at: null
                      repeat_schedule: false
                      mode: null
                      continuous_start_type: null
                      continuous_stop_type: null
                      continuous_stop_at: null
                      stream_duration_hours: null
                      stream_duration_minutes: null
                      break_duration_hours: null
                      break_duration_minutes: null
                      preserve_state: false
                    recording: null
                    multistream_destinations: []
                    started_at: null
                    created_at: '2026-08-11T11:05:38+00:00'
                    updated_at: '2026-08-11T11:05:38+00:00'
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1f1-1b12-430a-9cd2-919bba59a2f5
                        description: "The stream's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Dr. Enoch Harber II'
                        description: "The stream's display name."
                      description:
                        type: string
                        example: null
                        description: "The stream's description. Nullable."
                      platform:
                        type: string
                        example: youtube
                        description: 'Destination platform. One of: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP endpoint), customsrt (custom SRT endpoint).'
                      type:
                        type: string
                        example: video
                        description: 'Content type. `static` = a single image/background, `video` = a playlist of pre-recorded videos played in sequence, `live` = live input from browser participants or RTMP ingest.'
                      url:
                        type: string
                        example: dQw4w9WgXcQ
                        description: 'Platform-specific broadcast identifier (e.g. the YouTube video ID or Twitch channel login) — not a full URL. Nullable.'
                      status:
                        type: string
                        example: booting
                        description: 'Lifecycle state. One of: installing (server provisioning), booting (server starting up), active (live and broadcasting), paused (output paused), inactive (stopped cleanly), failed (fatal error), syncing (multi-stream sync in progress).'
                      thumbnail_url:
                        type: string
                        example: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                        description: "Full URL to the stream's thumbnail image. Nullable."
                      tags:
                        type: array
                        example:
                          - lofi
                          - chill
                        description: 'Tag names assigned to the stream.'
                        items:
                          type: string
                      encoding:
                        type: object
                        properties:
                          resolution:
                            type: string
                            example: 1920x1080
                            description: 'Output resolution as "{width}x{height}" (e.g. "1920x1080"). A portrait value such as "1080x1920" denotes vertical orientation.'
                          frame_rate:
                            type: string
                            example: '30'
                            description: 'Output frame rate in frames per second.'
                          bitrate:
                            type: integer
                            example: 8000
                            description: 'Target video bitrate in kbps. Nullable.'
                          audio_bitrate:
                            type: integer
                            example: 128
                            description: 'Audio bitrate in kbps. Nullable.'
                      volumes:
                        type: object
                        properties:
                          main:
                            type: integer
                            example: 70
                            description: 'Primary audio channel volume (0–100).'
                          secondary:
                            type: integer
                            example: 30
                            description: 'Secondary audio channel volume (0–100).'
                          video:
                            type: integer
                            example: 100
                            description: 'Background-video audio volume (0–100).'
                      playback:
                        type: object
                        properties:
                          mode:
                            type: string
                            example: loop
                            description: 'Whole-stream playback mode. `loop` plays the content on repeat; `single` plays it once then pauses.'
                          video_order:
                            type: string
                            example: loop
                            description: 'Background video playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          audio_order:
                            type: string
                            example: loop
                            description: 'Audio playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          default_image_duration:
                            type: integer
                            example: 10
                            description: 'Seconds each image is displayed when part of the video playlist.'
                      transitions:
                        type: object
                        properties:
                          fade_duration:
                            type: integer
                            example: 2
                            description: 'Audio crossfade duration in seconds (0–20) when switching tracks.'
                          animation_type:
                            type: string
                            example: null
                            description: 'Visual transition between clips. One of: fade, slide, scale, swipeAway, random — or null for no transition.'
                          animation_duration:
                            type: string
                            example: null
                            description: 'Transition animation duration in seconds (0–20). Null when no transition is set.'
                      video_fit:
                        type: object
                        properties:
                          object_fit:
                            type: string
                            example: null
                            description: 'How the video fills the frame: `cover` or `contain`. Nullable.'
                          style:
                            type: string
                            example: null
                            description: 'Fill behaviour when the video does not match the frame aspect ratio: `solid_color` or `blur`. Nullable.'
                          background_color:
                            type: string
                            example: null
                            description: 'Hex colour (#RGB, #RRGGBB or #RRGGBBAA) shown behind the video when style is `solid_color`. Nullable.'
                      schedule:
                        type: object
                        properties:
                          is_scheduled:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled start time.'
                          scheduled_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled start time. Nullable.'
                          is_scheduled_end:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled end time.'
                          scheduled_end_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled end time. Nullable.'
                          repeat_schedule:
                            type: boolean
                            example: false
                            description: 'Whether the schedule recurs.'
                          mode:
                            type: string
                            example: null
                            description: 'Scheduling mode. `continuous` for back-to-back cycles separated by breaks; null for a one-off or recurring schedule.'
                          continuous_start_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how each cycle starts: `now` or `scheduled`. Nullable.'
                          continuous_stop_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how the run stops: `never` or `scheduled`. Nullable.'
                          continuous_stop_at:
                            type: string
                            example: null
                            description: 'ISO 8601 time the continuous run stops. Nullable.'
                          stream_duration_hours:
                            type: string
                            example: null
                            description: 'Active streaming hours per continuous cycle. Nullable.'
                          stream_duration_minutes:
                            type: string
                            example: null
                            description: 'Active streaming minutes per continuous cycle. Nullable.'
                          break_duration_hours:
                            type: string
                            example: null
                            description: 'Break hours between continuous cycles. Nullable.'
                          break_duration_minutes:
                            type: string
                            example: null
                            description: 'Break minutes between continuous cycles. Nullable.'
                          preserve_state:
                            type: boolean
                            example: false
                            description: 'Whether playback position resumes after a continuous cycle restart.'
                      recording:
                        type: string
                        example: null
                        description: 'Recording settings. Present only when the recording feature is enabled for the stream; otherwise null.'
                      multistream_destinations:
                        type: array
                        example: []
                        description: 'Additional broadcast destinations. Stream keys are never exposed.'
                      started_at:
                        type: string
                        example: null
                        description: 'ISO 8601 time the stream was last started. Nullable.'
                      created_at:
                        type: string
                        example: '2026-08-11T11:05:38+00:00'
                        description: 'ISO 8601 creation time.'
                      updated_at:
                        type: string
                        example: '2026-08-11T11:05:38+00:00'
                        description: 'ISO 8601 last update time.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: 'Stream owned by another account'
                    type: object
                    example:
                      message: 'This action is unauthorized.'
                    properties:
                      message:
                        type: string
                        example: 'This action is unauthorized.'
                  -
                    description: 'Plan has no streaming access'
                    type: object
                    example:
                      message: "You've used up your streaming time. Upgrade your plan to keep streaming."
                    properties:
                      message:
                        type: string
                        example: "You've used up your streaming time. Upgrade your plan to keep streaming."
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        409:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: 'Not startable from current state'
                    type: object
                    example:
                      message: 'Stream cannot be started from its current state (installing).'
                    properties:
                      message:
                        type: string
                        example: 'Stream cannot be started from its current state (installing).'
                  -
                    description: 'Restart cooldown'
                    type: object
                    example:
                      message: 'Stream was just stopped; wait a few seconds before starting it again.'
                    properties:
                      message:
                        type: string
                        example: 'Stream was just stopped; wait a few seconds before starting it again.'
      tags:
        - Streams
    parameters:
      -
        in: path
        name: stream_id
        description: "The stream's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
  '/api/v1/streams/{stream_id}/stop':
    post:
      summary: 'Stop a stream'
      operationId: stopAStream
      description: "Stops a stream owned by the authenticated account — moves it back into the `paused`\nstate. Idempotent: stopping a stream that is already paused returns 200 with the\ncurrent stream and makes no change."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1f2-1509-4b49-a206-1e9566aab141
                    name: 'Dr. Enoch Harber II'
                    description: null
                    platform: youtube
                    type: video
                    url: dQw4w9WgXcQ
                    status: paused
                    thumbnail_url: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                    tags:
                      - lofi
                      - chill
                    encoding:
                      resolution: 1920x1080
                      frame_rate: '30'
                      bitrate: 8000
                      audio_bitrate: 128
                    volumes:
                      main: 70
                      secondary: 30
                      video: 100
                    playback:
                      mode: loop
                      video_order: loop
                      audio_order: loop
                      default_image_duration: 10
                    transitions:
                      fade_duration: 2
                      animation_type: null
                      animation_duration: null
                    video_fit:
                      object_fit: null
                      style: null
                      background_color: null
                    schedule:
                      is_scheduled: false
                      scheduled_at: null
                      is_scheduled_end: false
                      scheduled_end_at: null
                      repeat_schedule: false
                      mode: null
                      continuous_start_type: null
                      continuous_stop_type: null
                      continuous_stop_at: null
                      stream_duration_hours: null
                      stream_duration_minutes: null
                      break_duration_hours: null
                      break_duration_minutes: null
                      preserve_state: false
                    recording: null
                    multistream_destinations: []
                    started_at: null
                    created_at: '2026-08-11T11:05:39+00:00'
                    updated_at: '2026-08-11T11:05:39+00:00'
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1f2-1509-4b49-a206-1e9566aab141
                        description: "The stream's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Dr. Enoch Harber II'
                        description: "The stream's display name."
                      description:
                        type: string
                        example: null
                        description: "The stream's description. Nullable."
                      platform:
                        type: string
                        example: youtube
                        description: 'Destination platform. One of: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP endpoint), customsrt (custom SRT endpoint).'
                      type:
                        type: string
                        example: video
                        description: 'Content type. `static` = a single image/background, `video` = a playlist of pre-recorded videos played in sequence, `live` = live input from browser participants or RTMP ingest.'
                      url:
                        type: string
                        example: dQw4w9WgXcQ
                        description: 'Platform-specific broadcast identifier (e.g. the YouTube video ID or Twitch channel login) — not a full URL. Nullable.'
                      status:
                        type: string
                        example: paused
                        description: 'Lifecycle state. One of: installing (server provisioning), booting (server starting up), active (live and broadcasting), paused (output paused), inactive (stopped cleanly), failed (fatal error), syncing (multi-stream sync in progress).'
                      thumbnail_url:
                        type: string
                        example: 'https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault_live.jpg'
                        description: "Full URL to the stream's thumbnail image. Nullable."
                      tags:
                        type: array
                        example:
                          - lofi
                          - chill
                        description: 'Tag names assigned to the stream.'
                        items:
                          type: string
                      encoding:
                        type: object
                        properties:
                          resolution:
                            type: string
                            example: 1920x1080
                            description: 'Output resolution as "{width}x{height}" (e.g. "1920x1080"). A portrait value such as "1080x1920" denotes vertical orientation.'
                          frame_rate:
                            type: string
                            example: '30'
                            description: 'Output frame rate in frames per second.'
                          bitrate:
                            type: integer
                            example: 8000
                            description: 'Target video bitrate in kbps. Nullable.'
                          audio_bitrate:
                            type: integer
                            example: 128
                            description: 'Audio bitrate in kbps. Nullable.'
                      volumes:
                        type: object
                        properties:
                          main:
                            type: integer
                            example: 70
                            description: 'Primary audio channel volume (0–100).'
                          secondary:
                            type: integer
                            example: 30
                            description: 'Secondary audio channel volume (0–100).'
                          video:
                            type: integer
                            example: 100
                            description: 'Background-video audio volume (0–100).'
                      playback:
                        type: object
                        properties:
                          mode:
                            type: string
                            example: loop
                            description: 'Whole-stream playback mode. `loop` plays the content on repeat; `single` plays it once then pauses.'
                          video_order:
                            type: string
                            example: loop
                            description: 'Background video playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          audio_order:
                            type: string
                            example: loop
                            description: 'Audio playlist order. `loop` plays the items in order on repeat; `shuffle` plays them in random order.'
                          default_image_duration:
                            type: integer
                            example: 10
                            description: 'Seconds each image is displayed when part of the video playlist.'
                      transitions:
                        type: object
                        properties:
                          fade_duration:
                            type: integer
                            example: 2
                            description: 'Audio crossfade duration in seconds (0–20) when switching tracks.'
                          animation_type:
                            type: string
                            example: null
                            description: 'Visual transition between clips. One of: fade, slide, scale, swipeAway, random — or null for no transition.'
                          animation_duration:
                            type: string
                            example: null
                            description: 'Transition animation duration in seconds (0–20). Null when no transition is set.'
                      video_fit:
                        type: object
                        properties:
                          object_fit:
                            type: string
                            example: null
                            description: 'How the video fills the frame: `cover` or `contain`. Nullable.'
                          style:
                            type: string
                            example: null
                            description: 'Fill behaviour when the video does not match the frame aspect ratio: `solid_color` or `blur`. Nullable.'
                          background_color:
                            type: string
                            example: null
                            description: 'Hex colour (#RGB, #RRGGBB or #RRGGBBAA) shown behind the video when style is `solid_color`. Nullable.'
                      schedule:
                        type: object
                        properties:
                          is_scheduled:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled start time.'
                          scheduled_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled start time. Nullable.'
                          is_scheduled_end:
                            type: boolean
                            example: false
                            description: 'Whether the stream has a scheduled end time.'
                          scheduled_end_at:
                            type: string
                            example: null
                            description: 'ISO 8601 scheduled end time. Nullable.'
                          repeat_schedule:
                            type: boolean
                            example: false
                            description: 'Whether the schedule recurs.'
                          mode:
                            type: string
                            example: null
                            description: 'Scheduling mode. `continuous` for back-to-back cycles separated by breaks; null for a one-off or recurring schedule.'
                          continuous_start_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how each cycle starts: `now` or `scheduled`. Nullable.'
                          continuous_stop_type:
                            type: string
                            example: null
                            description: 'For continuous mode, how the run stops: `never` or `scheduled`. Nullable.'
                          continuous_stop_at:
                            type: string
                            example: null
                            description: 'ISO 8601 time the continuous run stops. Nullable.'
                          stream_duration_hours:
                            type: string
                            example: null
                            description: 'Active streaming hours per continuous cycle. Nullable.'
                          stream_duration_minutes:
                            type: string
                            example: null
                            description: 'Active streaming minutes per continuous cycle. Nullable.'
                          break_duration_hours:
                            type: string
                            example: null
                            description: 'Break hours between continuous cycles. Nullable.'
                          break_duration_minutes:
                            type: string
                            example: null
                            description: 'Break minutes between continuous cycles. Nullable.'
                          preserve_state:
                            type: boolean
                            example: false
                            description: 'Whether playback position resumes after a continuous cycle restart.'
                      recording:
                        type: string
                        example: null
                        description: 'Recording settings. Present only when the recording feature is enabled for the stream; otherwise null.'
                      multistream_destinations:
                        type: array
                        example: []
                        description: 'Additional broadcast destinations. Stream keys are never exposed.'
                      started_at:
                        type: string
                        example: null
                        description: 'ISO 8601 time the stream was last started. Nullable.'
                      created_at:
                        type: string
                        example: '2026-08-11T11:05:39+00:00'
                        description: 'ISO 8601 creation time.'
                      updated_at:
                        type: string
                        example: '2026-08-11T11:05:39+00:00'
                        description: 'ISO 8601 last update time.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        409:
          description: 'Not stoppable from current state'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Stream cannot be stopped from its current state (installing).'
                properties:
                  message:
                    type: string
                    example: 'Stream cannot be stopped from its current state (installing).'
      tags:
        - Streams
    parameters:
      -
        in: path
        name: stream_id
        description: "The stream's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
  '/api/v1/streams/{stream_id}/queues/{type}':
    get:
      summary: "List a stream's media queue"
      operationId: listAStreamsMediaQueue
      description: "Returns one of a stream's playback queues, paginated and in playback order. The\n`type` segment selects the queue:\n\n- `video` — the video/image queue (`selected_videos`)\n- `audio` — the primary audio queue (`selected_audios`)\n- `audio-secondary` — the secondary audio queue (`selected_audios_secondary`)\n- `external-videos` — externally-hosted videos (`selected_external_videos`)\n\nThe first three return Storage-backed media items (identity + metadata; media file\nURLs are intentionally omitted). `external-videos` returns the inline external items,\nincluding the source `url`. An unknown `type` returns 404.\n\nWithin a Storage-backed queue, any entry that no longer resolves — deleted media,\nmedia still processing, or a file-type mismatch — is omitted, so the list reflects\nexactly what would play."
      parameters:
        -
          in: query
          name: page
          description: 'The page number to return. Defaults to 1.'
          example: 1
          required: false
          schema:
            type: integer
            description: 'The page number to return. Defaults to 1.'
            example: 1
        -
          in: query
          name: per_page
          description: 'Number of items per page (1–100). Defaults to 15.'
          example: 15
          required: false
          schema:
            type: integer
            description: 'Number of items per page (1–100). Defaults to 15.'
            example: 15
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: 'Video queue'
                    type: object
                    example:
                      data:
                        -
                          id: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                          name: intro.mp4
                          file_type: video
                          extension: mp4
                          duration: 42.5
                          size: 10485760
                          title: null
                          artist: null
                          album: null
                          year: null
                          genre: null
                      links:
                        first: ...
                        last: ...
                        prev: null
                        next: null
                      meta:
                        current_page: 1
                        last_page: 1
                        per_page: 15
                        total: 1
                        from: 1
                        to: 1
                    properties:
                      data:
                        type: array
                        example:
                          -
                            id: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                            name: intro.mp4
                            file_type: video
                            extension: mp4
                            duration: 42.5
                            size: 10485760
                            title: null
                            artist: null
                            album: null
                            year: null
                            genre: null
                        description: 'The queue items in playback order. Storage-backed queues (`video`, `audio`, `audio-secondary`) return media objects (`id`, `name`, `file_type`, `extension`, `duration`, `size`, `title`, `artist`, `album`, `year`, `genre`); the `external-videos` queue returns external items (`id`, `name`, `url`, `file_type`, `thumbnail`). See the two example responses.'
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                              example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                            name:
                              type: string
                              example: intro.mp4
                            file_type:
                              type: string
                              example: video
                            extension:
                              type: string
                              example: mp4
                            duration:
                              type: number
                              example: 42.5
                            size:
                              type: integer
                              example: 10485760
                            title:
                              type: string
                              example: null
                              nullable: true
                            artist:
                              type: string
                              example: null
                              nullable: true
                            album:
                              type: string
                              example: null
                              nullable: true
                            year:
                              type: string
                              example: null
                              nullable: true
                            genre:
                              type: string
                              example: null
                              nullable: true
                      links:
                        type: object
                        properties:
                          first:
                            type: string
                            example: ...
                          last:
                            type: string
                            example: ...
                          prev:
                            type: string
                            example: null
                            nullable: true
                          next:
                            type: string
                            example: null
                            nullable: true
                        description: 'Pagination URLs: `first`, `last`, `prev`, `next`.'
                      meta:
                        type: object
                        properties:
                          current_page:
                            type: integer
                            example: 1
                          last_page:
                            type: integer
                            example: 1
                          per_page:
                            type: integer
                            example: 15
                          total:
                            type: integer
                            example: 1
                          from:
                            type: integer
                            example: 1
                          to:
                            type: integer
                            example: 1
                        description: 'Pagination counters: `current_page`, `last_page`, `per_page`, `total`, `from`, `to`.'
                  -
                    description: 'External video queue'
                    type: object
                    example:
                      data:
                        -
                          id: 65a1f3c0d4e2b
                          name: Promo
                          url: 'https://example.com/promo.mp4'
                          file_type: video
                          thumbnail: null
                      links:
                        first: ...
                        last: ...
                        prev: null
                        next: null
                      meta:
                        current_page: 1
                        last_page: 1
                        per_page: 15
                        total: 1
                        from: 1
                        to: 1
                    properties:
                      data:
                        type: array
                        example:
                          -
                            id: 65a1f3c0d4e2b
                            name: Promo
                            url: 'https://example.com/promo.mp4'
                            file_type: video
                            thumbnail: null
                        description: 'The queue items in playback order. Storage-backed queues (`video`, `audio`, `audio-secondary`) return media objects (`id`, `name`, `file_type`, `extension`, `duration`, `size`, `title`, `artist`, `album`, `year`, `genre`); the `external-videos` queue returns external items (`id`, `name`, `url`, `file_type`, `thumbnail`). See the two example responses.'
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                              example: 65a1f3c0d4e2b
                            name:
                              type: string
                              example: Promo
                            url:
                              type: string
                              example: 'https://example.com/promo.mp4'
                            file_type:
                              type: string
                              example: video
                            thumbnail:
                              type: string
                              example: null
                              nullable: true
                      links:
                        type: object
                        properties:
                          first:
                            type: string
                            example: ...
                          last:
                            type: string
                            example: ...
                          prev:
                            type: string
                            example: null
                            nullable: true
                          next:
                            type: string
                            example: null
                            nullable: true
                        description: 'Pagination URLs: `first`, `last`, `prev`, `next`.'
                      meta:
                        type: object
                        properties:
                          current_page:
                            type: integer
                            example: 1
                          last_page:
                            type: integer
                            example: 1
                          per_page:
                            type: integer
                            example: 15
                          total:
                            type: integer
                            example: 1
                          from:
                            type: integer
                            example: 1
                          to:
                            type: integer
                            example: 1
                        description: 'Pagination counters: `current_page`, `last_page`, `per_page`, `total`, `from`, `to`.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream or queue type not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Streams
    post:
      summary: 'Add items to a media queue'
      operationId: addItemsToAMediaQueue
      description: "Appends items to a queue, in order, at the end. For the Storage-backed queues\n(`video`, `audio`, `audio-secondary`) `items` is a list of your own media UUIDs of the\nqueue's type — still-processing media is accepted (it shows once ready) but failed media\nis rejected; if any id is unavailable the whole request is rejected (422). For\n`external-videos`, `items` is a list of `{url, name}` objects (`.mp4` URLs). An id/URL\nalready in the queue is skipped — a queue holds each item at most once. Returns the\nupdated queue."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: 'Updated Storage-backed queue'
                    type: object
                    example:
                      data:
                        -
                          id: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                          name: intro.mp4
                          file_type: video
                          extension: mp4
                          duration: 42.5
                          size: 10485760
                          title: null
                          artist: null
                          album: null
                          year: null
                          genre: null
                    properties:
                      data:
                        type: array
                        example:
                          -
                            id: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                            name: intro.mp4
                            file_type: video
                            extension: mp4
                            duration: 42.5
                            size: 10485760
                            title: null
                            artist: null
                            album: null
                            year: null
                            genre: null
                        description: 'The updated queue in playback order — same item fields as "List a stream''s media queue" (Storage-backed media objects, or external-video objects for the `external-videos` queue).'
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                              example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                            name:
                              type: string
                              example: intro.mp4
                            file_type:
                              type: string
                              example: video
                            extension:
                              type: string
                              example: mp4
                            duration:
                              type: number
                              example: 42.5
                            size:
                              type: integer
                              example: 10485760
                            title:
                              type: string
                              example: null
                              nullable: true
                            artist:
                              type: string
                              example: null
                              nullable: true
                            album:
                              type: string
                              example: null
                              nullable: true
                            year:
                              type: string
                              example: null
                              nullable: true
                            genre:
                              type: string
                              example: null
                              nullable: true
                  -
                    description: 'Updated external-videos queue'
                    type: object
                    example:
                      data:
                        -
                          id: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                          name: Promo
                          url: 'https://example.com/promo.mp4'
                          file_type: video
                          thumbnail: null
                    properties:
                      data:
                        type: array
                        example:
                          -
                            id: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                            name: Promo
                            url: 'https://example.com/promo.mp4'
                            file_type: video
                            thumbnail: null
                        description: 'The updated queue in playback order — same item fields as "List a stream''s media queue" (Storage-backed media objects, or external-video objects for the `external-videos` queue).'
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                              example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                            name:
                              type: string
                              example: Promo
                            url:
                              type: string
                              example: 'https://example.com/promo.mp4'
                            file_type:
                              type: string
                              example: video
                            thumbnail:
                              type: string
                              example: null
                              nullable: true
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        422:
          description: 'An id is unavailable'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This media is not available for this queue.'
                  errors:
                    items.0:
                      - 'This media is not available for this queue.'
                properties:
                  message:
                    type: string
                    example: 'This media is not available for this queue.'
                  errors:
                    type: object
                    properties:
                      items.0:
                        type: array
                        example:
                          - 'This media is not available for this queue.'
                        items:
                          type: string
      tags:
        - Streams
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  description: 'Must be a valid UUID.'
                  example:
                    - 66529e01-d113-3473-8d6f-9e11e09332ea
                  items:
                    type: string
              required:
                - items
    parameters:
      -
        in: path
        name: stream_id
        description: "The stream's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
      -
        in: path
        name: type
        description: 'The queue to read: video, audio, audio-secondary, or external-videos.'
        example: video
        required: true
        schema:
          type: string
  '/api/v1/streams/{stream_id}/queues/{type}/{mediaId}':
    delete:
      summary: 'Remove an item from a media queue'
      operationId: removeAnItemFromAMediaQueue
      description: "Removes an item from a queue by its id — a media UUID for the Storage-backed queues, or\nthe inline item id for external-videos. Returns the updated queue, or 404 if that id\nisn't currently in the queue."
      parameters: []
      responses:
        200:
          description: 'Updated queue'
          content:
            application/json:
              schema:
                type: object
                example:
                  data: []
                properties:
                  data:
                    type: array
                    example: []
                    description: 'The updated queue in playback order — same item fields as "List a stream''s media queue" (Storage-backed media objects, or external-video objects for the `external-videos` queue).'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found or item not in queue'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Streams
    parameters:
      -
        in: path
        name: stream_id
        description: "The stream's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
      -
        in: path
        name: type
        description: 'The queue: video, audio, audio-secondary, or external-videos.'
        example: video
        required: true
        schema:
          type: string
      -
        in: path
        name: mediaId
        description: 'The id of the item to remove — a media UUID for the Storage-backed queues, or the external-video item id for external-videos.'
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
  '/api/v1/streams/{stream_id}/queues/{type}/reorder':
    patch:
      summary: 'Reorder a media queue'
      operationId: reorderAMediaQueue
      description: "Sets the playback order of a queue (Storage-backed or external-videos). `order` must\ncontain exactly the ids currently visible in the queue — reorder only reorders; use the\nadd/remove endpoints to change membership. Returns the reordered queue."
      parameters: []
      responses:
        200:
          description: 'Reordered queue'
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                      name: intro.mp4
                      file_type: video
                      extension: mp4
                      duration: 42.5
                      size: 10485760
                      title: null
                      artist: null
                      album: null
                      year: null
                      genre: null
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                        name: intro.mp4
                        file_type: video
                        extension: mp4
                        duration: 42.5
                        size: 10485760
                        title: null
                        artist: null
                        album: null
                        year: null
                        genre: null
                    description: 'The reordered queue in playback order — same item fields as "List a stream''s media queue" (Storage-backed media objects, or external-video objects for the `external-videos` queue).'
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                        name:
                          type: string
                          example: intro.mp4
                        file_type:
                          type: string
                          example: video
                        extension:
                          type: string
                          example: mp4
                        duration:
                          type: number
                          example: 42.5
                        size:
                          type: integer
                          example: 10485760
                        title:
                          type: string
                          example: null
                          nullable: true
                        artist:
                          type: string
                          example: null
                          nullable: true
                        album:
                          type: string
                          example: null
                          nullable: true
                        year:
                          type: string
                          example: null
                          nullable: true
                        genre:
                          type: string
                          example: null
                          nullable: true
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        422:
          description: "Order isn't the current set"
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The order must contain exactly the items currently in the queue.'
                  errors:
                    order:
                      - 'The order must contain exactly the items currently in the queue.'
                properties:
                  message:
                    type: string
                    example: 'The order must contain exactly the items currently in the queue.'
                  errors:
                    type: object
                    properties:
                      order:
                        type: array
                        example:
                          - 'The order must contain exactly the items currently in the queue.'
                        items:
                          type: string
      tags:
        - Streams
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                order:
                  type: array
                  description: "The current queue's ids in the desired order."
                  example:
                    - 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
                  items:
                    type: string
              required:
                - order
    parameters:
      -
        in: path
        name: stream_id
        description: "The stream's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
      -
        in: path
        name: type
        description: 'The queue: video, audio, audio-secondary, or external-videos.'
        example: video
        required: true
        schema:
          type: string
  '/api/v1/streams/{stream_id}/destinations':
    get:
      summary: 'List destinations'
      operationId: listDestinations
      description: "Returns the multistream destinations for a stream. Destination stream keys are\nnever exposed."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: a279f1f3-a1ec-4491-8649-064823018919
                      name: 'dolores molestias'
                      platform: youtube
                      url: null
                      status: active
                      include_in_schedule: true
                    -
                      id: a279f1f4-554d-4230-8dd9-7489e27f624e
                      name: 'cum molestiae'
                      platform: youtube
                      url: null
                      status: active
                      include_in_schedule: true
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: a279f1f3-a1ec-4491-8649-064823018919
                        name: 'dolores molestias'
                        platform: youtube
                        url: null
                        status: active
                        include_in_schedule: true
                      -
                        id: a279f1f4-554d-4230-8dd9-7489e27f624e
                        name: 'cum molestiae'
                        platform: youtube
                        url: null
                        status: active
                        include_in_schedule: true
                    description: "An array of the stream's multistream destinations. This list is not paginated. Destination stream keys are never exposed."
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: a279f1f3-a1ec-4491-8649-064823018919
                          description: "The destination's unique identifier (UUID). Use it to update or delete the destination."
                        name:
                          type: string
                          example: 'dolores molestias'
                          description: 'Destination display name.'
                        platform:
                          type: string
                          example: youtube
                          description: "Destination platform (same value set as the stream's `platform`)."
                        url:
                          type: string
                          example: null
                          description: 'Destination URL. Nullable.'
                        status:
                          type: string
                          example: active
                          description: 'Whether the destination is broadcast to: active or paused.'
                        include_in_schedule:
                          type: boolean
                          example: true
                          description: 'Whether this destination is used when the stream is scheduled.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Multistreaming
    post:
      summary: 'Add a destination'
      operationId: addADestination
      description: 'Adds a multistream destination to a stream (max 10 per stream). Returns `201 Created`.'
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1f5-1288-4a03-9d2b-36cc08e66fce
                    name: 'consequatur dolores'
                    platform: youtube
                    url: null
                    status: active
                    include_in_schedule: true
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1f5-1288-4a03-9d2b-36cc08e66fce
                        description: "The destination's unique identifier (UUID). Use it to update or delete the destination."
                      name:
                        type: string
                        example: 'consequatur dolores'
                        description: 'Destination display name.'
                      platform:
                        type: string
                        example: youtube
                        description: "Destination platform (same value set as the stream's `platform`)."
                      url:
                        type: string
                        example: null
                        description: 'Destination URL. Nullable.'
                      status:
                        type: string
                        example: active
                        description: 'Whether the destination is broadcast to: active or paused.'
                      include_in_schedule:
                        type: boolean
                        example: true
                        description: 'Whether this destination is used when the stream is scheduled.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Stream not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        422:
          description: 'Limit reached'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This stream already has the maximum of 10 destinations.'
                properties:
                  message:
                    type: string
                    example: 'This stream already has the maximum of 10 destinations.'
      tags:
        - Multistreaming
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'Display name for the destination. Must not be greater than 100 characters.'
                  example: 'Backup YouTube'
                platform:
                  type: string
                  description: 'Destination platform: youtube, twitch, facebook, instagram, mixcloud, rumble, kick, custom (custom RTMP), customsrt (custom SRT).'
                  example: youtube
                  enum:
                    - youtube
                    - twitch
                    - facebook
                    - instagram
                    - mixcloud
                    - rumble
                    - kick
                    - custom
                    - customsrt
                url:
                  type: string
                  description: 'Optional destination URL. Must not be greater than 500 characters.'
                  example: 'rtmp://a.rtmp.youtube.com/live2'
                  nullable: true
                key:
                  type: string
                  description: 'Stream key for the destination. For platform=custom it must start with rtmp:// or rtmps://; for customsrt with srt://. Write-only — never returned.'
                  example: live2/abcd-efgh
                include_in_schedule:
                  type: boolean
                  description: 'Whether this destination is used when the stream is scheduled.'
                  example: true
                status:
                  type: string
                  description: 'Destination status (active or paused). Defaults to active.'
                  example: active
                  enum:
                    - active
                    - paused
              required:
                - name
                - platform
                - key
    parameters:
      -
        in: path
        name: stream_id
        description: "The stream's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
  '/api/v1/streams/{stream_id}/destinations/{id}':
    patch:
      summary: 'Update a destination'
      operationId: updateADestination
      description: 'Updates a multistream destination. Send only the fields you want to change.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1f5-df5a-409f-8946-97c3d38d0f20
                    name: 'consequatur dolores'
                    platform: youtube
                    url: null
                    status: active
                    include_in_schedule: true
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1f5-df5a-409f-8946-97c3d38d0f20
                        description: "The destination's unique identifier (UUID). Use it to update or delete the destination."
                      name:
                        type: string
                        example: 'consequatur dolores'
                        description: 'Destination display name.'
                      platform:
                        type: string
                        example: youtube
                        description: "Destination platform (same value set as the stream's `platform`)."
                      url:
                        type: string
                        example: null
                        description: 'Destination URL. Nullable.'
                      status:
                        type: string
                        example: active
                        description: 'Whether the destination is broadcast to: active or paused.'
                      include_in_schedule:
                        type: boolean
                        example: true
                        description: 'Whether this destination is used when the stream is scheduled.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Destination not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Multistreaming
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'Display name for the destination. Must not be greater than 100 characters.'
                  example: 'Backup YouTube'
                platform:
                  type: string
                  description: 'Destination platform.'
                  example: youtube
                  enum:
                    - youtube
                    - twitch
                    - facebook
                    - instagram
                    - mixcloud
                    - rumble
                    - kick
                    - custom
                    - customsrt
                url:
                  type: string
                  description: 'Optional destination URL. Must not be greater than 500 characters.'
                  example: 'rtmp://a.rtmp.youtube.com/live2'
                  nullable: true
                key:
                  type: string
                  description: 'Stream key. For platform=custom it must start with rtmp:// or rtmps://; for customsrt with srt://. Write-only.'
                  example: live2/abcd-efgh
                include_in_schedule:
                  type: boolean
                  description: 'Whether this destination is used when the stream is scheduled.'
                  example: true
                status:
                  type: string
                  description: 'Destination status (active or paused).'
                  example: active
                  enum:
                    - active
                    - paused
    delete:
      summary: 'Remove a destination'
      operationId: removeADestination
      description: 'Deletes a multistream destination. Returns an empty 204 response.'
      parameters: []
      responses:
        204:
          description: Deleted
          content:
            text/plain:
              schema:
                type: string
                example: ''
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Stream owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Destination not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Multistreaming
    parameters:
      -
        in: path
        name: stream_id
        description: "The stream's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
      -
        in: path
        name: id
        description: "The destination's UUID."
        example: 7c1a9b2e-4ada-bec1-74fd-fdc171b3a21b
        required: true
        schema:
          type: string
  /api/v1/media/uploads:
    post:
      summary: 'Start a media upload'
      operationId: startAMediaUpload
      description: "Returns an upload ticket — a TUS endpoint plus a short-lived bearer token — for\nuploading a media file to your library with a resumable (TUS 1.0.0) client.\n\n**Complete, runnable examples** — Node.js, Python, Go and cURL, each doing the full\nmint → upload → poll flow against a ready-to-upload sample clip — are on GitHub:\n<https://github.com/upstream-so/upstream-upload-examples>\n\nThe flow has three steps:\n1. Call this endpoint to get `upload_url`, `token` and `expires_at`.\n2. Upload the file to `upload_url` with any TUS 1.0.0 client, sending\n   `Authorization: Bearer {token}` and the file name in `Upload-Metadata`. To place\n   the file in a folder you own, send its UUID as a `Folder-Id` header — the server\n   validates ownership and silently ignores an unknown or foreign id (the file then\n   lands at the library root). When the upload finishes, the response carries the new\n   file's id in the `storage-id` header.\n3. Poll `GET /api/v1/media/{id}` until `is_processing` is `false`.\n\nOne token drives many uploads — sequential or concurrent — for its full 24-hour life;\nit is validated per request, not consumed. Because it is single-active per account\n(minting a new one, here or via the web app, revokes the previous), mint **once** and\nreuse it for a batch — minting per file would revoke your other in-flight uploads.\n\nExample with tus-js-client:\n\n```js\nimport * as tus from 'tus-js-client'\n\nconst { upload_url, token } = ticket.data // from POST /api/v1/media/uploads\nconst upload = new tus.Upload(file, {\n  endpoint: upload_url,\n  headers: { Authorization: `Bearer ${token}`, 'Folder-Id': folderId }, // Folder-Id optional\n  metadata: { name: file.name },\n  onAfterResponse: (req, res) => {\n    const id = res.getHeader('storage-id')\n    if (id) console.log('media id:', id) // then poll GET /api/v1/media/{id}\n  },\n  onError: console.error,\n})\nupload.start()\n```\n\n`upload_url` points at your account's default (closest) region. The token is valid on\nevery regional upload server, so you may instead upload to the nearest:\n- Europe — `https://e.upstream.so/api/upload/`\n- America — `https://a.upstream.so/api/upload/`\n- Asia — `https://i.upstream.so/api/upload/`"
      parameters: []
      responses:
        200:
          description: 'Upload ticket'
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    upload_url: 'https://e.upstream.so/api/upload/'
                    token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                    expires_at: '2026-06-27T12:00:00+00:00'
                    folder_id: null
                properties:
                  data:
                    type: object
                    properties:
                      upload_url:
                        type: string
                        example: 'https://e.upstream.so/api/upload/'
                        description: 'The TUS 1.0.0 endpoint to upload the file to. Send chunks here with `token` as the Bearer credential.'
                      token:
                        type: string
                        example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                        description: 'Short-lived (24h) bearer token authorising the upload. Single-active per account — minting a new one (here or via the web app) revokes the previous.'
                      expires_at:
                        type: string
                        example: '2026-06-27T12:00:00+00:00'
                        description: 'ISO 8601 time the token expires.'
                      folder_id:
                        type: string
                        example: null
                        description: 'Echoes the `folder_id` you submitted (validated for ownership), or null. To place the file in that folder, re-send this value as the `Folder-Id` header to the upload server; otherwise the file lands at the library root.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Account has no active subscription or trial'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        422:
          description: 'folder_id is not a folder you own'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The folder_id must be a folder you own.'
                  errors:
                    folder_id:
                      - 'The folder_id must be a folder you own.'
                properties:
                  message:
                    type: string
                    example: 'The folder_id must be a folder you own.'
                  errors:
                    type: object
                    properties:
                      folder_id:
                        type: array
                        example:
                          - 'The folder_id must be a folder you own.'
                        items:
                          type: string
      tags:
        - Media
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                folder_id:
                  type: string
                  description: 'Optional. UUID of a folder you own to place the upload in. Omit for the library root.'
                  example: null
                  nullable: true
  /api/v1/media:
    get:
      summary: 'List media files'
      operationId: listMediaFiles
      description: "Returns the media files owned by the authenticated account, newest first,\npaginated. Filter by `type`, by a `search` term matched against the file name,\nor by `folder_id` (a folder's UUID, or `root` for files not in any folder)."
      parameters:
        -
          in: query
          name: type
          description: 'Filter by file type: `video`, `audio`, or `image`.'
          example: audio
          required: false
          schema:
            type: string
            description: 'Filter by file type: `video`, `audio`, or `image`.'
            example: audio
            enum:
              - video
              - audio
              - image
            nullable: true
        -
          in: query
          name: search
          description: 'Case-insensitive match against the file name. Must not be greater than 255 characters.'
          example: intro
          required: false
          schema:
            type: string
            description: 'Case-insensitive match against the file name. Must not be greater than 255 characters.'
            example: intro
            nullable: true
        -
          in: query
          name: folder_id
          description: "A folder UUID to list that folder's files, or `root` for files not in any folder."
          example: root
          required: false
          schema:
            type: string
            description: "A folder UUID to list that folder's files, or `root` for files not in any folder."
            example: root
            nullable: true
        -
          in: query
          name: page
          description: 'The page number to return. Defaults to 1.'
          example: 1
          required: false
          schema:
            type: integer
            description: 'The page number to return. Defaults to 1.'
            example: 1
        -
          in: query
          name: per_page
          description: 'Number of files per page (1–100). Defaults to 15.'
          example: 15
          required: false
          schema:
            type: integer
            description: 'Number of files per page (1–100). Defaults to 15.'
            example: 15
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: a279f1f6-75cc-4113-a7f8-4906053bf4ed
                      name: consequatur
                      file_type: video
                      extension: skt
                      size: 612111
                      duration: null
                      resolution: null
                      title: null
                      artist: null
                      album: null
                      year: null
                      genre: null
                      folder_id: null
                      is_processing: false
                    -
                      id: a279f1f7-20cb-429b-b881-2df0f1b57aba
                      name: sed
                      file_type: audio
                      extension: m4v
                      size: 11979615
                      duration: null
                      resolution: null
                      title: null
                      artist: null
                      album: null
                      year: null
                      genre: null
                      folder_id: null
                      is_processing: false
                  links:
                    first: '/?page=1'
                    last: '/?page=1'
                    prev: null
                    next: null
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 1
                    path: /
                    per_page: 15
                    to: 2
                    total: 2
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: a279f1f6-75cc-4113-a7f8-4906053bf4ed
                        name: consequatur
                        file_type: video
                        extension: skt
                        size: 612111
                        duration: null
                        resolution: null
                        title: null
                        artist: null
                        album: null
                        year: null
                        genre: null
                        folder_id: null
                        is_processing: false
                      -
                        id: a279f1f7-20cb-429b-b881-2df0f1b57aba
                        name: sed
                        file_type: audio
                        extension: m4v
                        size: 11979615
                        duration: null
                        resolution: null
                        title: null
                        artist: null
                        album: null
                        year: null
                        genre: null
                        folder_id: null
                        is_processing: false
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: a279f1f6-75cc-4113-a7f8-4906053bf4ed
                          description: "The file's unique identifier (UUID)."
                        name:
                          type: string
                          example: consequatur
                          description: "The file's display name."
                        file_type:
                          type: string
                          example: video
                          description: 'The media type: `video`, `audio`, or `image`.'
                        extension:
                          type: string
                          example: skt
                          description: 'The file''s extension (e.g. "mp4", "mp3", "png"). Nullable.'
                        size:
                          type: integer
                          example: 612111
                          description: 'File size in bytes. Nullable.'
                        duration:
                          type: string
                          example: null
                          description: 'Duration in seconds for video/audio files. Nullable.'
                        resolution:
                          type: string
                          example: null
                          description: 'Video resolution as `WIDTHxHEIGHT` (e.g. "1920x1080"). Nullable.'
                        title:
                          type: string
                          example: null
                          description: 'Audio track title. Nullable.'
                        artist:
                          type: string
                          example: null
                          description: 'Audio artist. Nullable.'
                        album:
                          type: string
                          example: null
                          description: 'Audio album. Nullable.'
                        year:
                          type: string
                          example: null
                          description: 'Audio release year. Nullable.'
                        genre:
                          type: string
                          example: null
                          description: 'Audio genre. Nullable.'
                        folder_id:
                          type: string
                          example: null
                          description: 'UUID of the folder containing the file, or null when it sits at the root.'
                        is_processing:
                          type: boolean
                          example: false
                          description: 'Whether the file is still being processed (not yet playable).'
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                        example: '/?page=1'
                      last:
                        type: string
                        example: '/?page=1'
                      prev:
                        type: string
                        example: null
                        nullable: true
                      next:
                        type: string
                        example: null
                        nullable: true
                    description: 'Pagination URLs: `first`, `last`, `prev`, `next`.'
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                        example: 1
                      from:
                        type: integer
                        example: 1
                      last_page:
                        type: integer
                        example: 1
                      path:
                        type: string
                        example: /
                      per_page:
                        type: integer
                        example: 15
                      to:
                        type: integer
                        example: 2
                      total:
                        type: integer
                        example: 2
                    description: 'Pagination counters: `current_page`, `last_page`, `per_page`, `total`, `from`, `to`.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        422:
          description: 'Invalid filter'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The folder_id must be a valid UUID or "root".'
                  errors:
                    folder_id:
                      - 'The folder_id must be a valid UUID or "root".'
                properties:
                  message:
                    type: string
                    example: 'The folder_id must be a valid UUID or "root".'
                  errors:
                    type: object
                    properties:
                      folder_id:
                        type: array
                        example:
                          - 'The folder_id must be a valid UUID or "root".'
                        items:
                          type: string
      tags:
        - Media
  '/api/v1/media/{media_id}':
    get:
      summary: 'Get a media file'
      operationId: getAMediaFile
      description: 'Returns a single media file owned by the authenticated account.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1f7-d0a3-4135-b7bf-825e9ec2d036
                    name: dolores
                    file_type: video
                    extension: rss
                    size: 284
                    duration: null
                    resolution: null
                    title: null
                    artist: null
                    album: null
                    year: null
                    genre: null
                    folder_id: null
                    is_processing: false
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1f7-d0a3-4135-b7bf-825e9ec2d036
                        description: "The file's unique identifier (UUID)."
                      name:
                        type: string
                        example: dolores
                        description: "The file's display name."
                      file_type:
                        type: string
                        example: video
                        description: 'The media type: `video`, `audio`, or `image`.'
                      extension:
                        type: string
                        example: rss
                        description: 'The file''s extension (e.g. "mp4", "mp3", "png"). Nullable.'
                      size:
                        type: integer
                        example: 284
                        description: 'File size in bytes. Nullable.'
                      duration:
                        type: string
                        example: null
                        description: 'Duration in seconds for video/audio files. Nullable.'
                      resolution:
                        type: string
                        example: null
                        description: 'Video resolution as `WIDTHxHEIGHT` (e.g. "1920x1080"). Nullable.'
                      title:
                        type: string
                        example: null
                        description: 'Audio track title. Nullable.'
                      artist:
                        type: string
                        example: null
                        description: 'Audio artist. Nullable.'
                      album:
                        type: string
                        example: null
                        description: 'Audio album. Nullable.'
                      year:
                        type: string
                        example: null
                        description: 'Audio release year. Nullable.'
                      genre:
                        type: string
                        example: null
                        description: 'Audio genre. Nullable.'
                      folder_id:
                        type: string
                        example: null
                        description: 'UUID of the folder containing the file, or null when it sits at the root.'
                      is_processing:
                        type: boolean
                        example: false
                        description: 'Whether the file is still being processed (not yet playable).'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'File owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'File not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Media
    patch:
      summary: 'Update a media file'
      operationId: updateAMediaFile
      description: "Updates a media file owned by the authenticated account. Send only the fields you\nwant to change. `name` renames any file; the audio metadata fields (`title`,\n`artist`, `album`, `year`, `genre`) apply to audio files only and are rejected on\nother types."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1f8-7613-4914-8f91-f6bc964e8da9
                    name: consequatur
                    file_type: video
                    extension: skt
                    size: 612111
                    duration: null
                    resolution: null
                    title: null
                    artist: null
                    album: null
                    year: null
                    genre: null
                    folder_id: null
                    is_processing: false
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1f8-7613-4914-8f91-f6bc964e8da9
                        description: "The file's unique identifier (UUID)."
                      name:
                        type: string
                        example: consequatur
                        description: "The file's display name."
                      file_type:
                        type: string
                        example: video
                        description: 'The media type: `video`, `audio`, or `image`.'
                      extension:
                        type: string
                        example: skt
                        description: 'The file''s extension (e.g. "mp4", "mp3", "png"). Nullable.'
                      size:
                        type: integer
                        example: 612111
                        description: 'File size in bytes. Nullable.'
                      duration:
                        type: string
                        example: null
                        description: 'Duration in seconds for video/audio files. Nullable.'
                      resolution:
                        type: string
                        example: null
                        description: 'Video resolution as `WIDTHxHEIGHT` (e.g. "1920x1080"). Nullable.'
                      title:
                        type: string
                        example: null
                        description: 'Audio track title. Nullable.'
                      artist:
                        type: string
                        example: null
                        description: 'Audio artist. Nullable.'
                      album:
                        type: string
                        example: null
                        description: 'Audio album. Nullable.'
                      year:
                        type: string
                        example: null
                        description: 'Audio release year. Nullable.'
                      genre:
                        type: string
                        example: null
                        description: 'Audio genre. Nullable.'
                      folder_id:
                        type: string
                        example: null
                        description: 'UUID of the folder containing the file, or null when it sits at the root.'
                      is_processing:
                        type: boolean
                        example: false
                        description: 'Whether the file is still being processed (not yet playable).'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'File owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'File not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        422:
          description: 'Metadata on a non-audio file'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Metadata can only be edited for audio files.'
                  errors:
                    title:
                      - 'Metadata can only be edited for audio files.'
                properties:
                  message:
                    type: string
                    example: 'Metadata can only be edited for audio files.'
                  errors:
                    type: object
                    properties:
                      title:
                        type: array
                        example:
                          - 'Metadata can only be edited for audio files.'
                        items:
                          type: string
      tags:
        - Media
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'New display name for the file. Must not be greater than 255 characters.'
                  example: intro.mp4
                title:
                  type: string
                  description: 'Audio track title (audio files only). Must not be greater than 255 characters.'
                  example: 'My Title'
                  nullable: true
                artist:
                  type: string
                  description: 'Audio artist (audio files only). Must not be greater than 255 characters.'
                  example: 'My Artist'
                  nullable: true
                album:
                  type: string
                  description: 'Audio album (audio files only). Must not be greater than 255 characters.'
                  example: 'My Album'
                  nullable: true
                year:
                  type: string
                  description: 'Audio release year (audio files only). Must not be greater than 255 characters.'
                  example: '2026'
                  nullable: true
                genre:
                  type: string
                  description: 'Audio genre (audio files only). Must not be greater than 255 characters.'
                  example: Lofi
                  nullable: true
    delete:
      summary: 'Delete a media file'
      operationId: deleteAMediaFile
      description: "Deletes a media file owned by the authenticated account. The file is removed from\nevery stream's queues and deleted from storage. Returns an empty 204 response."
      parameters: []
      responses:
        204:
          description: Deleted
          content:
            text/plain:
              schema:
                type: string
                example: ''
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'File owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'File not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Media
    parameters:
      -
        in: path
        name: media_id
        description: "The media file's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
  /api/v1/folders:
    get:
      summary: 'List folders'
      operationId: listFolders
      description: "Returns the folders owned by the authenticated account, newest first, paginated.\nFilter by `parent_id` (a folder's UUID for its direct children, or `root` for\ntop-level folders)."
      parameters:
        -
          in: query
          name: parent_id
          description: 'A folder UUID to list its direct children, or `root` for top-level folders.'
          example: root
          required: false
          schema:
            type: string
            description: 'A folder UUID to list its direct children, or `root` for top-level folders.'
            example: root
            nullable: true
        -
          in: query
          name: page
          description: 'The page number to return. Defaults to 1.'
          example: 1
          required: false
          schema:
            type: integer
            description: 'The page number to return. Defaults to 1.'
            example: 1
        -
          in: query
          name: per_page
          description: 'Number of folders per page (1–100). Defaults to 15.'
          example: 15
          required: false
          schema:
            type: integer
            description: 'Number of folders per page (1–100). Defaults to 15.'
            example: 15
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: a279f1fb-1733-43a7-b226-b9500f64f8bf
                      name: 'Dr. Enoch Harber II'
                      parent_id: null
                    -
                      id: a279f1fb-8552-4b20-9cb5-1d7b268ba45d
                      name: 'Otho Pagac DVM'
                      parent_id: null
                  links:
                    first: '/?page=1'
                    last: '/?page=1'
                    prev: null
                    next: null
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 1
                    path: /
                    per_page: 15
                    to: 2
                    total: 2
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: a279f1fb-1733-43a7-b226-b9500f64f8bf
                        name: 'Dr. Enoch Harber II'
                        parent_id: null
                      -
                        id: a279f1fb-8552-4b20-9cb5-1d7b268ba45d
                        name: 'Otho Pagac DVM'
                        parent_id: null
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: a279f1fb-1733-43a7-b226-b9500f64f8bf
                          description: "The folder's unique identifier (UUID)."
                        name:
                          type: string
                          example: 'Dr. Enoch Harber II'
                          description: "The folder's display name."
                        parent_id:
                          type: string
                          example: null
                          description: 'UUID of the parent folder, or null when the folder sits at the root.'
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                        example: '/?page=1'
                      last:
                        type: string
                        example: '/?page=1'
                      prev:
                        type: string
                        example: null
                        nullable: true
                      next:
                        type: string
                        example: null
                        nullable: true
                    description: 'Pagination URLs: `first`, `last`, `prev`, `next`.'
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                        example: 1
                      from:
                        type: integer
                        example: 1
                      last_page:
                        type: integer
                        example: 1
                      path:
                        type: string
                        example: /
                      per_page:
                        type: integer
                        example: 15
                      to:
                        type: integer
                        example: 2
                      total:
                        type: integer
                        example: 2
                    description: 'Pagination counters: `current_page`, `last_page`, `per_page`, `total`, `from`, `to`.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        422:
          description: 'Invalid filter'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The parent_id must be a valid UUID or "root".'
                  errors:
                    parent_id:
                      - 'The parent_id must be a valid UUID or "root".'
                properties:
                  message:
                    type: string
                    example: 'The parent_id must be a valid UUID or "root".'
                  errors:
                    type: object
                    properties:
                      parent_id:
                        type: array
                        example:
                          - 'The parent_id must be a valid UUID or "root".'
                        items:
                          type: string
      tags:
        - Folders
    post:
      summary: 'Create a folder'
      operationId: createAFolder
      description: "Creates a folder owned by the authenticated account. Omit `parent_id` (or send null)\nfor a top-level folder, or pass an owned folder's UUID to nest it. Returns `201 Created`."
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1fb-fe66-414c-9519-a2fd1f1f2078
                    name: 'Miss Lorna Dibbert'
                    parent_id: null
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1fb-fe66-414c-9519-a2fd1f1f2078
                        description: "The folder's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Miss Lorna Dibbert'
                        description: "The folder's display name."
                      parent_id:
                        type: string
                        example: null
                        description: 'UUID of the parent folder, or null when the folder sits at the root.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: 'Account has no streaming plan'
                    type: object
                    example:
                      message: 'This action is unauthorized.'
                    properties:
                      message:
                        type: string
                        example: 'This action is unauthorized.'
                  -
                    description: 'Acting as another account'
                    type: object
                    example:
                      message: 'Acting as another account is not supported on the API.'
                    properties:
                      message:
                        type: string
                        example: 'Acting as another account is not supported on the API.'
        422:
          description: 'Invalid input'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The name field is required.'
                  errors:
                    name:
                      - 'The name field is required.'
                properties:
                  message:
                    type: string
                    example: 'The name field is required.'
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        example:
                          - 'The name field is required.'
                        items:
                          type: string
      tags:
        - Folders
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'Display name for the folder. Must not be greater than 255 characters.'
                  example: Clips
                parent_id:
                  type: string
                  description: 'UUID of the parent folder, or omit/null for a top-level folder. Must be a valid UUID. Must match an existing stored value.'
                  example: null
                  nullable: true
              required:
                - name
  /api/v1/folders/move-files:
    post:
      summary: 'Move files'
      operationId: moveFiles
      description: "Moves the given media files into a folder, or to the root. Pass `folder_id` (an owned\nfolder's UUID) to move them into that folder, or omit it (or send null) to move them\nto the root. Every file — and the destination folder — must be owned by the\nauthenticated account. Returns an empty 204."
      parameters: []
      responses:
        204:
          description: Moved
          content:
            text/plain:
              schema:
                type: string
                example: ''
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Acting as another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Acting as another account is not supported on the API.'
                properties:
                  message:
                    type: string
                    example: 'Acting as another account is not supported on the API.'
        422:
          description: ''
          content:
            application/json:
              schema:
                oneOf:
                  -
                    description: 'A file is not owned by the caller'
                    type: object
                    example:
                      message: 'One or more of the media files do not belong to you.'
                      errors:
                        media_ids:
                          - 'One or more of the media files do not belong to you.'
                    properties:
                      message:
                        type: string
                        example: 'One or more of the media files do not belong to you.'
                      errors:
                        type: object
                        properties:
                          media_ids:
                            type: array
                            example:
                              - 'One or more of the media files do not belong to you.'
                            items:
                              type: string
                  -
                    description: 'The destination folder is not owned by the caller'
                    type: object
                    example:
                      message: 'The selected folder is invalid.'
                      errors:
                        folder_id:
                          - 'The selected folder is invalid.'
                    properties:
                      message:
                        type: string
                        example: 'The selected folder is invalid.'
                      errors:
                        type: object
                        properties:
                          folder_id:
                            type: array
                            example:
                              - 'The selected folder is invalid.'
                            items:
                              type: string
      tags:
        - Folders
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                media_ids:
                  type: array
                  description: 'Must be a valid UUID.'
                  example:
                    - 66529e01-d113-3473-8d6f-9e11e09332ea
                  items:
                    type: string
                folder_id:
                  type: string
                  description: 'UUID of the destination folder, or omit/null to move the files to the root. Must be a valid UUID. Must match an existing stored value.'
                  example: null
                  nullable: true
  '/api/v1/folders/{id}':
    get:
      summary: 'Get a folder'
      operationId: getAFolder
      description: "Returns a single folder owned by the authenticated account. List a folder's\nchildren with `GET /folders?parent_id={id}`."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1fc-7981-48d8-8983-b1e67b29308e
                    name: 'Dr. Enoch Harber II'
                    parent_id: null
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1fc-7981-48d8-8983-b1e67b29308e
                        description: "The folder's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Dr. Enoch Harber II'
                        description: "The folder's display name."
                      parent_id:
                        type: string
                        example: null
                        description: 'UUID of the parent folder, or null when the folder sits at the root.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Folder owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Folder not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Folders
    patch:
      summary: 'Update a folder'
      operationId: updateAFolder
      description: "Updates a folder owned by the authenticated account. Send `name` to rename, and/or\n`parent_id` to move it (an owned folder's UUID to nest it, or null to move it to the\nroot). A folder can't be moved into itself or one of its descendants."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1fc-eeae-4d9c-af1a-8dc5ae46a667
                    name: 'Miss Lorna Dibbert'
                    parent_id: null
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1fc-eeae-4d9c-af1a-8dc5ae46a667
                        description: "The folder's unique identifier (UUID)."
                      name:
                        type: string
                        example: 'Miss Lorna Dibbert'
                        description: "The folder's display name."
                      parent_id:
                        type: string
                        example: null
                        description: 'UUID of the parent folder, or null when the folder sits at the root.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Folder owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Folder not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        422:
          description: 'Cyclic move'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'A folder cannot be moved into itself or its descendants.'
                  errors:
                    parent_id:
                      - 'A folder cannot be moved into itself or its descendants.'
                properties:
                  message:
                    type: string
                    example: 'A folder cannot be moved into itself or its descendants.'
                  errors:
                    type: object
                    properties:
                      parent_id:
                        type: array
                        example:
                          - 'A folder cannot be moved into itself or its descendants.'
                        items:
                          type: string
      tags:
        - Folders
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'New display name for the folder. Must not be greater than 255 characters.'
                  example: 'Renamed clips'
                parent_id:
                  type: string
                  description: 'UUID of the new parent folder, or null to move it to the root. Must be a valid UUID. Must match an existing stored value.'
                  example: null
                  nullable: true
    delete:
      summary: 'Delete a folder'
      operationId: deleteAFolder
      description: "Deletes a folder owned by the authenticated account. Its subfolders are deleted too,\nand any files inside are moved to the root (not deleted). Returns an empty 204."
      parameters: []
      responses:
        204:
          description: Deleted
          content:
            text/plain:
              schema:
                type: string
                example: ''
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Folder owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Folder not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Folders
    parameters:
      -
        in: path
        name: id
        description: "The folder's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
  /api/v1/tags:
    get:
      summary: 'List tags'
      operationId: listTags
      description: "Returns all the tags owned by the authenticated account, ordered by name (not\npaginated — the full set is small and is meant to populate a tag picker). Tag\nnames can be assigned to streams via the stream create/update endpoints."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: a279f1f9-278d-41ec-82b1-19d5d9638e44
                      name: dolores
                      color: '#8236f7'
                      icon: X
                    -
                      id: a279f1f9-98b0-48b1-95c4-1cfe0a0dc37d
                      name: dignissimos
                      color: '#038655'
                      icon: X
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: a279f1f9-278d-41ec-82b1-19d5d9638e44
                        name: dolores
                        color: '#8236f7'
                        icon: X
                      -
                        id: a279f1f9-98b0-48b1-95c4-1cfe0a0dc37d
                        name: dignissimos
                        color: '#038655'
                        icon: X
                    description: "An array of the account's tags, ordered by name. This list is not paginated."
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: a279f1f9-278d-41ec-82b1-19d5d9638e44
                          description: "The tag's unique identifier (UUID)."
                        name:
                          type: string
                          example: dolores
                          description: 'The tag name.'
                        color:
                          type: string
                          example: '#8236f7'
                          description: 'Hex colour shown for the tag (e.g. "#3366FF"). Nullable.'
                        icon:
                          type: string
                          example: X
                          description: 'Short icon identifier for the tag. Nullable.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
      tags:
        - Tags
    post:
      summary: 'Create a tag'
      operationId: createATag
      description: "Creates a tag owned by the authenticated account. Tag names are unique per account.\nReturns `201 Created`."
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1fa-0d5d-4a19-9195-0f9571858d89
                    name: consequatur
                    color: '#7f66e3'
                    icon: X
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1fa-0d5d-4a19-9195-0f9571858d89
                        description: "The tag's unique identifier (UUID)."
                      name:
                        type: string
                        example: consequatur
                        description: 'The tag name.'
                      color:
                        type: string
                        example: '#7f66e3'
                        description: 'Hex colour shown for the tag (e.g. "#3366FF"). Nullable.'
                      icon:
                        type: string
                        example: X
                        description: 'Short icon identifier for the tag. Nullable.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        422:
          description: 'Validation failed'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The name has already been taken.'
                  errors:
                    name:
                      - 'The name has already been taken.'
                properties:
                  message:
                    type: string
                    example: 'The name has already been taken.'
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        example:
                          - 'The name has already been taken.'
                        items:
                          type: string
      tags:
        - Tags
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'Tag name. Must be unique within your account. Must not be greater than 255 characters.'
                  example: lofi
                color:
                  type: string
                  description: 'Optional hex colour for the tag. Must match the regex /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.'
                  example: '#3366FF'
                  nullable: true
                icon:
                  type: string
                  description: 'Optional short icon identifier for the tag. Must not be greater than 10 characters.'
                  example: music
                  nullable: true
              required:
                - name
  '/api/v1/tags/{id}':
    patch:
      summary: 'Update a tag'
      operationId: updateATag
      description: 'Updates a tag owned by the authenticated account. Send only the fields you want to change.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    id: a279f1fa-91e7-4d68-a031-12456383f941
                    name: consequatur
                    color: '#7f66e3'
                    icon: X
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: a279f1fa-91e7-4d68-a031-12456383f941
                        description: "The tag's unique identifier (UUID)."
                      name:
                        type: string
                        example: consequatur
                        description: 'The tag name.'
                      color:
                        type: string
                        example: '#7f66e3'
                        description: 'Hex colour shown for the tag (e.g. "#3366FF"). Nullable.'
                      icon:
                        type: string
                        example: X
                        description: 'Short icon identifier for the tag. Nullable.'
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Tag owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Tag not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
        422:
          description: 'Validation failed'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The name has already been taken.'
                  errors:
                    name:
                      - 'The name has already been taken.'
                properties:
                  message:
                    type: string
                    example: 'The name has already been taken.'
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        example:
                          - 'The name has already been taken.'
                        items:
                          type: string
      tags:
        - Tags
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: 'Tag name. Must be unique within your account. Must not be greater than 255 characters.'
                  example: lofi
                color:
                  type: string
                  description: 'Optional hex colour for the tag. Must match the regex /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.'
                  example: '#3366FF'
                  nullable: true
                icon:
                  type: string
                  description: 'Optional short icon identifier for the tag. Must not be greater than 10 characters.'
                  example: music
                  nullable: true
    delete:
      summary: 'Delete a tag'
      operationId: deleteATag
      description: "Deletes a tag owned by the authenticated account and removes it from any streams.\nReturns an empty 204 response."
      parameters: []
      responses:
        204:
          description: Deleted
          content:
            text/plain:
              schema:
                type: string
                example: ''
        401:
          description: 'Missing or invalid token'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
        403:
          description: 'Tag owned by another account'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'This action is unauthorized.'
                properties:
                  message:
                    type: string
                    example: 'This action is unauthorized.'
        404:
          description: 'Tag not found'
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Resource not found.'
                properties:
                  message:
                    type: string
                    example: 'Resource not found.'
      tags:
        - Tags
    parameters:
      -
        in: path
        name: id
        description: "The tag's UUID."
        example: 9b2e7c1a-4f3d-4a8b-9c2e-1f3d4a8b9c2e
        required: true
        schema:
          type: string
