> ## 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.

# Keepalive

> Renew the stream lease and pay for elapsed streaming time. **Call every 10-20 seconds.** Streams expire after ~45 seconds without a keepalive.

Each call charges for time since the last keepalive. If credits are insufficient (402), the lease is NOT renewed and the stream will expire.

For native transport, the response includes a refreshed `livekit_token`.

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


## OpenAPI

````yaml api-reference/v0.2/openapi.json POST /streams/{stream_id}/keepalive
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/{stream_id}/keepalive:
    post:
      tags:
        - streams
      summary: Keepalive
      description: >-
        Renew the stream lease and pay for elapsed streaming time. **Call every
        10-20 seconds.** Streams expire after ~45 seconds without a keepalive.


        Each call charges for time since the last keepalive. If credits are
        insufficient (402), the lease is NOT renewed and the stream will expire.


        For native transport, the response includes a refreshed `livekit_token`.
      operationId: keepalive_stream_streams__stream_id__keepalive_post
      parameters:
        - name: stream_id
          in: path
          required: true
          schema:
            type: string
            title: Stream Id
      responses:
        '200':
          description: Lease renewed, credits charged
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/KeepaliveResponse'
        '400':
          description: 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: Insufficient credits — lease NOT renewed, stream will expire
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Stream not found or expired
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Request validation error
          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:
    KeepaliveResponse:
      properties:
        status:
          type: string
          const: ok
          title: Status
        stream_id:
          type: string
          title: Stream Id
          description: Stream identifier
        ttl_seconds:
          type: integer
          title: Ttl Seconds
          description: Seconds until stream expires without another keepalive
        credits_remaining_cents:
          type: integer
          title: Credits Remaining Cents
          description: Credits remaining after this charge (in cents)
        cost_cents:
          type: number
          title: Cost Cents
          description: Credits charged for this keepalive interval (in cents)
        seconds_charged:
          type: number
          title: Seconds Charged
          description: Seconds of streaming time charged
        livekit_token:
          anyOf:
            - type: string
            - type: 'null'
          title: Livekit Token
          description: >-
            Refreshed LiveKit JWT for native sources. Use this to maintain the
            connection.
        state:
          type: string
          enum:
            - pending
            - active
            - idle
          title: State
          description: >-
            Current stream state: pending (no frames yet), active (inferencing),
            idle (frames stopped)
      type: object
      required:
        - status
        - stream_id
        - ttl_seconds
        - credits_remaining_cents
        - cost_cents
        - seconds_charged
        - state
      title: KeepaliveResponse
      description: >-
        Keepalive response with billing summary. Streams expire after TTL
        seconds without a keepalive.
    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.
  securitySchemes:
    API Key:
      type: http
      description: Provide your API key in the Authorization header as 'Bearer <api_key>'
      scheme: bearer

````