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

# Create stream

> Create a new video inference stream. Returns connection details for the chosen transport.

**Workflow:** Create stream → connect video source → receive results on WebSocket → send keepalives → close when done.

**Transport options:**
- **Native** (default, recommended): Omit `source`. Response includes `livekit.url` and `livekit.token` for publishing video.
- **WebRTC**: Set `source.type: 'webrtc'` with an SDP offer. Response includes `webrtc` answer and `turn_servers`.
- **LiveKit**: Set `source.type: 'livekit'` with your room URL and token.

**Processing modes:**
- **Clip mode**: Send `target_fps`, `clip_length_seconds`, `delay_seconds` for temporal analysis (motion, actions).
- **Frame mode**: Send `interval_seconds` for static analysis (OCR, object detection).

**Limits:** 5 concurrent streams per API key. Requires credits.

<Warning>
  The v0.2 API is deprecated. New integrations should use v1.
</Warning>


## OpenAPI

````yaml api-reference/v0.2/openapi.json POST /streams
openapi: 3.1.0
info:
  title: Overshoot Streaming API
  description: >-
    Real-time video and image inference API. Stream video from any source
    (camera, file, RTSP, screen share) and receive continuous AI analysis
    results over WebSocket.


    ## Quick start


    1. **Create a stream** — `POST /streams` with a prompt and model

    2. **Connect WebSocket** — `WS /ws/streams/{stream_id}` to receive results

    3. **Send keepalives** — `POST /streams/{stream_id}/keepalive` every 15s

    4. **Close when done** — `DELETE /streams/{stream_id}`


    ## List models


    `GET /models` returns available models and their current status.


    ```json

    [{"model": "Qwen/Qwen3.5-9B", "ready": true, "status": "ready"}]

    ```


    | Status | `ready` | Meaning |

    |--------|---------|----------|

    | `ready` | `true` | Healthy, performing well |

    | `degraded` | `true` | Near capacity, higher latency expected |

    | `saturated` | `false` | At capacity, will reject new streams |

    | `unavailable` | `false` | Endpoint not reachable |


    ## WebSocket — Receive results


    Connect to `WS /ws/streams/{stream_id}` to receive inference results in
    real-time.


    **Authentication:** Send your API key as the first message:

    ```json

    {"api_key": "your-api-key"}

    ```


    **Result messages:** Each message is a `StreamInferenceResult` with fields:
    `result` (model output), `ok`, `error`, `finish_reason`,
    `inference_latency_ms`, `total_latency_ms`.


    **Close codes:**

    - `1008` — Authentication failed

    - `1001` — Stream ended (reasons: `client_requested`, `lease_expired`,
    `insufficient_credits`, transport disconnected)


    ## Authentication


    All endpoints require a Bearer token: `Authorization: Bearer <api_key>`


    Get your API key at
    [platform.overshoot.ai](https://platform.overshoot.ai/api-keys).


    ## SDKs


    - **JavaScript:** `npm install overshoot`

    - **Python:** `pip install
    git+https://github.com/Overshoot-ai/overshoot-python.git`


    Full documentation at [docs.overshoot.ai](https://docs.overshoot.ai).
  version: '0.2'
servers:
  - url: /v0.2
security: []
tags:
  - name: streams
    description: Create, manage, and close video inference streams.
  - name: internal
    description: Internal/experimental endpoints. Not used by SDKs.
paths:
  /streams:
    post:
      tags:
        - streams
      summary: Create stream
      description: >-
        Create a new video inference stream. Returns connection details for the
        chosen transport.


        **Workflow:** Create stream → connect video source → receive results on
        WebSocket → send keepalives → close when done.


        **Transport options:**

        - **Native** (default, recommended): Omit `source`. Response includes
        `livekit.url` and `livekit.token` for publishing video.

        - **WebRTC**: Set `source.type: 'webrtc'` with an SDP offer. Response
        includes `webrtc` answer and `turn_servers`.

        - **LiveKit**: Set `source.type: 'livekit'` with your room URL and
        token.


        **Processing modes:**

        - **Clip mode**: Send `target_fps`, `clip_length_seconds`,
        `delay_seconds` for temporal analysis (motion, actions).

        - **Frame mode**: Send `interval_seconds` for static analysis (OCR,
        object detection).


        **Limits:** 5 concurrent streams per API key. Requires credits.
      operationId: create_stream_streams_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StreamCreateRequest'
        required: true
      responses:
        '201':
          description: Stream created. Use `stream_id` for all subsequent operations.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StreamCreateResponse'
        '400':
          description: Invalid request body (validation error)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: No credits available. Add credits at platform.overshoot.ai.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Request validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: >-
            Concurrent stream limit reached (max 5). Close an existing stream
            first.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - API Key: []
components:
  schemas:
    StreamCreateRequest:
      properties:
        source:
          anyOf:
            - oneOf:
                - $ref: '#/components/schemas/WebRTCSourceConfig'
                - $ref: '#/components/schemas/LiveKitSourceConfig'
                - $ref: '#/components/schemas/NativeSourceConfig'
            - type: 'null'
          title: Source
          description: >-
            Video source configuration. Omit for native LiveKit transport
            (recommended). Options: native, webrtc, livekit.
        webrtc:
          anyOf:
            - $ref: '#/components/schemas/WebRtcOffer'
            - type: 'null'
          description: (Legacy) WebRTC offer. Use `source` instead.
        mode:
          anyOf:
            - type: string
              enum:
                - clip
                - frame
            - type: 'null'
          title: Mode
          description: >-
            Processing mode. Auto-detected from `processing` config if omitted.
            'clip' for video clips, 'frame' for single images.
        processing:
          anyOf:
            - $ref: '#/components/schemas/ClipProcessingConfig'
            - $ref: '#/components/schemas/FrameProcessingConfig'
          title: Processing
          description: >-
            How to sample the video. Use ClipProcessingConfig for temporal
            analysis or FrameProcessingConfig for static analysis.
        inference:
          $ref: '#/components/schemas/StreamInferenceConfig'
        client:
          anyOf:
            - $ref: '#/components/schemas/StreamClientMeta'
            - type: 'null'
          description: Optional client metadata for request tracking.
      type: object
      required:
        - processing
        - inference
      title: StreamCreateRequest
      description: |-
        Create a new video inference stream.

        Minimal example (frame mode, native transport):
        ```json
        {
          "processing": { "interval_seconds": 2.0 },
          "inference": { "prompt": "Describe what you see", "model": "Qwen/Qwen3.5-9B" }
        }
        ```
    StreamCreateResponse:
      properties:
        stream_id:
          type: string
          title: Stream Id
          description: >-
            Unique stream identifier. Use this for keepalive, close, prompt
            update, and WebSocket connection.
        webrtc:
          anyOf:
            - $ref: '#/components/schemas/WebRtcAnswer'
            - type: 'null'
          description: SDP answer for WebRTC sources. Null for native/livekit sources.
        lease:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Lease
          description: >-
            Stream lease info including ttl_seconds. Send keepalives before TTL
            expires.
        turn_servers:
          anyOf:
            - items:
                additionalProperties:
                  type: string
                type: object
              type: array
            - type: 'null'
          title: Turn Servers
          description: >-
            TURN server credentials for WebRTC sources. Null for native/livekit
            sources.
        livekit:
          anyOf:
            - additionalProperties:
                type: string
              type: object
            - type: 'null'
          title: Livekit
          description: >-
            LiveKit connection details (url + token) for native sources. Connect
            to this room to publish video.
      type: object
      required:
        - stream_id
      title: StreamCreateResponse
      description: >-
        Returned after successfully creating a stream. Contains connection
        details specific to the chosen transport.
    ErrorResponse:
      properties:
        error:
          type: string
          title: Error
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Request Id
        details:
          anyOf:
            - {}
            - type: 'null'
          title: Details
      type: object
      required:
        - error
      title: ErrorResponse
      description: Error response.
    WebRTCSourceConfig:
      properties:
        type:
          type: string
          const: webrtc
          title: Type
        sdp:
          type: string
          minLength: 1
          title: Sdp
          description: SDP offer string from RTCPeerConnection.createOffer()
      additionalProperties: false
      type: object
      required:
        - type
        - sdp
      title: WebRTCSourceConfig
      description: >-
        Legacy WebRTC source. Send an SDP offer and receive an SDP answer in the
        response.
    LiveKitSourceConfig:
      properties:
        type:
          type: string
          const: livekit
          title: Type
        url:
          type: string
          minLength: 1
          title: Url
          description: LiveKit server URL (e.g. wss://myapp.livekit.cloud)
        token:
          type: string
          minLength: 1
          title: Token
          description: Participant JWT with subscribe permission
      additionalProperties: false
      type: object
      required:
        - type
        - url
        - token
      title: LiveKitSourceConfig
      description: >-
        Connect to your own LiveKit room. The gateway joins as a subscriber to
        receive video.
    NativeSourceConfig:
      properties:
        type:
          type: string
          const: native
          title: Type
      additionalProperties: false
      type: object
      required:
        - type
      title: NativeSourceConfig
      description: >-
        Default transport. The server creates a LiveKit room and returns
        connection details (url + token) in the response.
    WebRtcOffer:
      properties:
        type:
          type: string
          const: offer
          title: Type
        sdp:
          type: string
          minLength: 1
          title: Sdp
      additionalProperties: false
      type: object
      required:
        - type
        - sdp
      title: WebRtcOffer
      description: Legacy request model — kept for backwards compatibility.
    ClipProcessingConfig:
      properties:
        target_fps:
          anyOf:
            - type: integer
              maximum: 30
              exclusiveMinimum: 0
            - type: 'null'
          title: Target Fps
          description: >-
            Frames per second to sample (1-30). This is the effective FPS of the
            clips sent to the model.
        sampling_ratio:
          anyOf:
            - type: number
              maximum: 1
              minimum: 0.1
            - type: 'null'
          title: Sampling Ratio
          description: (Legacy) Fraction of source frames to keep. Use target_fps instead.
        fps:
          anyOf:
            - type: integer
              exclusiveMinimum: 0
            - type: 'null'
          title: Fps
          description: (Legacy) Source video FPS. Use target_fps instead.
        clip_length_seconds:
          type: number
          maximum: 60
          minimum: 0.1
          title: Clip Length Seconds
          description: >-
            Duration of each video clip in seconds (e.g. 0.5 for half-second
            clips)
        delay_seconds:
          type: number
          exclusiveMinimum: 0
          title: Delay Seconds
          description: >-
            Seconds between inference requests. Lower = more frequent results
            but higher cost.
      additionalProperties: false
      type: object
      required:
        - clip_length_seconds
        - delay_seconds
      title: ClipProcessingConfig
      description: >-
        Clip mode processing config. Samples frames into short video clips for
        temporal analysis (motion, actions, events).


        Provide `target_fps` directly, or the legacy `fps` + `sampling_ratio`
        pair (not both).
    FrameProcessingConfig:
      properties:
        interval_seconds:
          type: number
          maximum: 60
          exclusiveMinimum: 0
          title: Interval Seconds
          description: >-
            Seconds between frame captures (e.g. 2.0 = one frame every 2
            seconds)
      additionalProperties: false
      type: object
      required:
        - interval_seconds
      title: FrameProcessingConfig
      description: >-
        Frame mode processing config. Captures individual frames at regular
        intervals for static analysis (OCR, object detection, scene
        description).
    StreamInferenceConfig:
      properties:
        prompt:
          type: string
          minLength: 1
          title: Prompt
          description: >-
            The task for the AI model (e.g. 'Read any visible text', 'Count
            people in the scene')
        model:
          type: string
          minLength: 1
          title: Model
          description: >-
            Model identifier (e.g. 'Qwen/Qwen3.5-9B'). See GET /models for
            available models.
        backend:
          type: string
          enum:
            - gemini
            - overshoot
          title: Backend
          description: >-
            Inference backend. Defaults to 'overshoot'. Most users should omit
            this.
          default: overshoot
        output_schema_json:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Output Schema Json
          description: >-
            JSON Schema for structured output. When provided, the model returns
            valid JSON matching this schema instead of free-form text.
        max_output_tokens:
          anyOf:
            - type: integer
              exclusiveMinimum: 0
            - type: 'null'
          title: Max Output Tokens
          description: >-
            Maximum tokens per inference. Auto-calculated from your processing
            interval if omitted. Effective token rate (max_output_tokens /
            interval) must not exceed 128 tok/s.
      additionalProperties: false
      type: object
      required:
        - prompt
        - model
      title: StreamInferenceConfig
      description: What the AI model should do with the video.
    StreamClientMeta:
      properties:
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Request Id
      type: object
      title: StreamClientMeta
    WebRtcAnswer:
      properties:
        type:
          type: string
          const: answer
          title: Type
        sdp:
          type: string
          minLength: 1
          title: Sdp
      additionalProperties: false
      type: object
      required:
        - type
        - sdp
      title: WebRtcAnswer
  securitySchemes:
    API Key:
      type: http
      description: Provide your API key in the Authorization header as 'Bearer <api_key>'
      scheme: bearer

````