openapi: 3.0.3
info:
  title: Nirai Flux Local API
  description: |
    Local HTTP API for Nirai Flux. Drive generation and playback from Stream Deck, OBS, chat bots, or scripts while the studio tab is open.

    **Base URL:** `http://127.0.0.1:8787` (localhost only — do not expose to the public internet)

    **Requirements**
    - Nirai Flux is running and the model is Ready
    - The studio is open in a browser tab at the base URL. If the tab is closed, commands queue and nothing plays
  version: 1.0.0
  contact:
    name: Nirai Flux
    url: https://github.com/amakann/nirai-flux

servers:
  - url: http://127.0.0.1:8787
    description: Local studio (default)

tags:
  - name: Control
    description: Generate, stream, play, and stop
  - name: Library
    description: Presets, songs, streams, and uploads

paths:
  /api/control:
    get:
      tags: [Control]
      summary: Get last control command
      description: Returns the last command sent to the studio (`seq` + `command`).
      operationId: getControl
      responses:
        "200":
          description: Last command
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ControlStatus"
    post:
      tags: [Control]
      summary: Send control command
      description: |
        Primary automation endpoint. Send JSON to generate, stream, play, or stop.

        For `play`, provide exactly one of `generation_id`, `stream_id`, or `upload_id`.
      operationId: postControl
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ControlCommand"
            examples:
              generatePreset:
                summary: Generate from preset
                value:
                  action: generate
                  preset: Chill Pad
                  play_when: now
              stream:
                summary: Continuous stream
                value:
                  action: stream
                  preset: Chill Pad
                  crossfade_seconds: 3
                  play_when: now
              playUpload:
                summary: Play uploaded intro
                value:
                  action: play
                  upload_id: PASTE_ID_HERE
                  play_when: now
              stop:
                summary: Stop playback and stream
                value:
                  action: stop
      responses:
        "200":
          description: Command accepted
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true

  /api/favorites:
    get:
      tags: [Library]
      summary: List presets
      description: Saved presets from the Presets tab. Use `name` or `id` in control commands.
      operationId: listFavorites
      responses:
        "200":
          description: Preset list
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Preset"

  /api/songs:
    get:
      tags: [Library]
      summary: List generated songs
      operationId: listSongs
      responses:
        "200":
          description: Song list
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Song"

  /api/streams:
    get:
      tags: [Library]
      summary: List stream sessions
      operationId: listStreams
      responses:
        "200":
          description: Stream session list
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/StreamSession"

  /api/uploads:
    get:
      tags: [Library]
      summary: List uploaded files
      operationId: listUploads
      responses:
        "200":
          description: Upload list
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Upload"
    post:
      tags: [Library]
      summary: Upload audio file
      operationId: uploadFile
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required: [file]
              properties:
                file:
                  type: string
                  format: binary
      responses:
        "200":
          description: Upload created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Upload"

components:
  schemas:
    ControlCommand:
      type: object
      required: [action]
      properties:
        action:
          type: string
          enum: [generate, stream, play, stop]
        prompt:
          type: string
          description: Required for generate/stream unless `preset` is set
        preset:
          type: string
          description: Preset name or id from `/api/favorites`
        duration:
          type: integer
          minimum: 60
          maximum: 380
          description: Track length in seconds (capped by active model)
        play_when:
          type: string
          enum: [now, after_current]
          default: now
          description: "`now` starts ASAP (crossfade if playing); `after_current` waits for the current track"
        crossfade_seconds:
          type: number
          minimum: 0
          maximum: 10
        crossfade_enabled:
          type: boolean
        negative_prompt:
          type: string
        output_format:
          type: string
          enum: [opus, mp3, aac, wav]
        generation_id:
          type: string
          description: Song id from `/api/songs` (play only)
        stream_id:
          type: string
          description: Stream session id from `/api/streams` (play only)
        upload_id:
          type: string
          description: Upload id from `/api/uploads` (play only)

    ControlStatus:
      type: object
      properties:
        seq:
          type: integer
        command:
          $ref: "#/components/schemas/ControlCommand"

    Preset:
      type: object
      properties:
        id:
          type: string
        name:
          type: string

    Song:
      type: object
      properties:
        id:
          type: string
        name:
          type: string

    StreamSession:
      type: object
      properties:
        stream_id:
          type: string

    Upload:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
