> ## Documentation Index
> Fetch the complete documentation index at: https://streamloop.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a scene

> A new scene, nothing published. Its draft starts empty — build it with `PUT /scenes/{id}/resources/frame/{frame}` — or, to import one, from `draft`: a whole scene document in the studio's format. A name is 1 to 120 characters.



## OpenAPI

````yaml /api-reference/scenes-openapi.json post /scenes
openapi: 3.1.0
info:
  title: Streamloop Scenes API
  version: 1.0.0
  description: >-
    Build and run scenes: live, designed streams. A scene (id `scn_…`) holds
    frames — full arrangements of layers (text, pictures, video, web pages,
    tables, tickers), one on air at a time — each at `frame/<id>`, plus the
    sources it reads (cameras, RTMP/SRT inputs, files, playlists, URLs, Google
    Sheets), its components and its script. You edit its draft as resources at
    paths (`frame/intro`, `frame/intro/title`, `source/data/headlines`,
    `component/LowerThird`, `script/show.ts`); every write is built and checked
    as the Streamloop studio checks it, and studios open on it see it at once.
    Nothing reaches viewers until you publish. To put a scene on a stream: `PUT
    /v1/streams/{id}/scene` (Streamloop REST API), then start the stream.


    This API follows the conventions of Streamloop's REST API: the same
    authentication (`X-API-Key`, an OAuth bearer, or the dashboard's session),
    `X-Workspace-Id`, RFC 7807 problems with a stable `code`, cursor pages,
    `Idempotency-Key` on POST and PATCH, and `RateLimit-*` headers (600 requests
    a minute).
servers:
  - url: https://api.streamloop.app/v1
security:
  - apiKey: []
  - oauth: []
tags:
  - name: scenes
    description: Create, list, read and delete scenes.
  - name: draft
    description: >-
      Read and change the scene's draft, resource by resource. Start with `GET
      /scenes/{id}/resources` (the kinds of thing it holds) and `GET
      /scenes/{id}/resources/element/*` (the building blocks and their props).
  - name: publishing
    description: Put the draft on air, see what was published, go back.
  - name: live
    description: What a stream playing the scene has on air, and the operator's actions.
  - name: inputs
    description: >-
      Live inputs: ingest keys for RTMP/RTMPS/SRT encoders, RTSP cameras, and
      secrets the scene's tables use.
paths:
  /scenes:
    post:
      tags:
        - scenes
      summary: Create a scene
      description: >-
        A new scene, nothing published. Its draft starts empty — build it with
        `PUT /scenes/{id}/resources/frame/{frame}` — or, to import one, from
        `draft`: a whole scene document in the studio's format. A name is 1 to
        120 characters.
      operationId: createScene
      parameters:
        - $ref: '#/components/parameters/workspace'
        - $ref: '#/components/parameters/idempotency'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              additionalProperties: false
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 120
                draft:
                  type: object
                  required:
                    - show
                  additionalProperties: false
                  description: >-
                    Import: the draft to start from, refused (422) unless `show`
                    is an object. A studio's saved project has this shape.
                  properties:
                    show:
                      type: object
                      description: >-
                        The scene document: `{ version: 2, name, design?:
                        {width, height}, frames: [{ id, name, root }], sources?,
                        data?, controls?, components?, tokens?, stateType?,
                        stateSchema? }` — each `frames[]` entry is what `GET
                        …/resources/frame/<id>?as=json` answers, each source,
                        table, control and component what its resource answers.
                        A document from before frames (`scenes: […]`, roots
                        `type: "Scene"`) is read as frames.
                      additionalProperties: true
                    script:
                      type: string
                      description: 'The TypeScript of `script/show.ts` (empty: none)'
      responses:
        '201':
          description: The scene
          headers:
            Location:
              schema:
                type: string
              description: /v1/scenes/{id}
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Scene'
        '400':
          $ref: '#/components/responses/BadRequest'
        4XX:
          $ref: '#/components/responses/Problem'
        5XX:
          $ref: '#/components/responses/Problem'
components:
  parameters:
    workspace:
      name: X-Workspace-Id
      in: header
      schema:
        type: string
      description: >-
        The workspace to act in. Required with an API key; otherwise the
        session's own.
    idempotency:
      name: Idempotency-Key
      in: header
      schema:
        type: string
        maxLength: 200
      description: >-
        Retry safely: the key (per caller, workspace, method and path) is taken
        before the request runs, and its first answer is replayed for 24 hours,
        with `Idempotency-Replayed: true` — a repeat sent while the first still
        runs waits for it. The same key with a different body is 422
        IDEMPOTENCY_KEY_REUSED. A 5xx is not kept: the retry runs.
  schemas:
    Scene:
      allOf:
        - $ref: '#/components/schemas/SceneSummary'
        - type: object
          properties:
            workspaceId:
              type: string
            draftRevision:
              type: string
              description: 'GET: the draft''s revision now, what publish and discard take'
            streams:
              type: array
              description: The streams that play it
              items:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
                  state:
                    type: string
    SceneSummary:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        version:
          type: integer
          description: 'The published version; 0: never published'
        publishedAt:
          type:
            - string
            - 'null'
          format: date-time
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    Problem:
      type: object
      required:
        - type
        - title
        - status
        - code
        - detail
      properties:
        type:
          type: string
          const: about:blank
        title:
          type: string
        status:
          type: integer
        code:
          type: string
          description: >-
            Stable — branch on it: BAD_REQUEST (400), WORKSPACE_REQUIRED (400),
            UNAUTHENTICATED (401), INSUFFICIENT_SCOPE (403), WORKSPACE_FORBIDDEN
            (403), NOT_FOUND (404), METHOD_NOT_ALLOWED (405), READ_ONLY (422),
            CONFLICT (409; currentRevision), EDIT_NO_MATCH (409), EDIT_AMBIGUOUS
            (409), IN_USE (409), CONFIRM_REQUIRED (409), STALE_PUBLISH (409;
            publishedVersion, basedOn, reverted, publishedVersionIsRevert),
            REVISION_REQUIRED (MCP only: a set or remove of an existing resource
            without its revision), NOT_PUBLISHED (409), SCENE_IN_USE (409),
            DRAFT_NOT_SAVED (409), SCENE_OFFLINE (409), SCENE_REFUSED (409),
            INGEST_KEY_REVOKED (409), CAMERA_PULL_GONE (409), SECRETS_FULL
            (409), PRECONDITION_FAILED (412; currentRevision), TOO_LARGE (413),
            UNSUPPORTED_MEDIA_TYPE (415), INVALID_INPUT (422),
            IDEMPOTENCY_KEY_REUSED (422), CHECK_FAILED (422), SCENE_INVALID
            (422), CAMERA_INVALID (422), CAMERA_PRIVATE_ADDRESS (422),
            SECRET_MISSING (422), RATE_LIMITED (429), CAMERA_TEST_BUSY (429),
            INTERNAL (500), NOT_SUPPORTED (501), UNAVAILABLE (502 or 503),
            INGEST_UNAVAILABLE (503), CAMERAS_UNAVAILABLE (503),
            SECRETS_UNAVAILABLE (503), SCENE_TIMEOUT (504)
        detail:
          type: string
          description: What happened and what to do
        errors:
          type: array
          description: Each problem, when there are several (a check's findings)
          items:
            type: object
            properties:
              line:
                type: integer
              path:
                type: string
              node:
                type: string
              message:
                type: string
            additionalProperties: true
        currentRevision:
          type:
            - string
            - 'null'
          description: >-
            CONFLICT / PRECONDITION_FAILED: the resource's revision now; null
            when it no longer exists
  responses:
    BadRequest:
      description: >-
        BAD_REQUEST (400): a body or query that can't be parsed (not JSON);
        INVALID_INPUT (422): one that parses but doesn't fit — an unknown or
        missing field or query parameter, a value of the wrong type or out of
        range. `detail` names the field
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    Problem:
      description: An RFC 7807 problem; branch on `code`
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        A Streamloop API key (`sl_…`). It carries no workspace: send
        `X-Workspace-Id` too (400 WORKSPACE_REQUIRED otherwise).
    oauth:
      type: http
      scheme: bearer
      description: >-
        An OAuth access token (as Streamloop's MCP server uses). Each operation
        needs the scope named in its `x-scope`: streamloop:read ⊂
        streamloop:write ⊂ streamloop:destructive (403 INSUFFICIENT_SCOPE).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.