Skip to content

LiveMan HTTP API ​

Live777 Cluster Manager

WHIP && WHEP ​

POST /whip/:streamId

Response: [201]

POST /whep/:streamId

Response: [201]


PATCH /session/:streamId/:sessionId

Response: [204]

DELETE /session/:streamId/:sessionId

Response: [204]

Recording & Playback ​

Recording and playback related APIs (proxy and index listing)

List Streams with Recording Index ​

GET /api/playback

Response: [200] application/json

json
["camera01", "roomA", "web-0001"]

List Index by Stream ​

GET /api/playback/{stream}

Response: [200] application/json

json
[
  { "year": 2025, "month": 7, "day": 24, "mpd_path": "camera01/2025/07/24/manifest.mpd" }
]

Get Segment File via Proxy ​

GET /api/record/object/{path}

  • path: URL-encoded storage path of the recorded object (e.g. camera01/2025/07/24/manifest.mpd)

Response: [200] Binary media data, content-type inferred by extension (e.g. application/dash+xml for .mpd, video/mp4 for .m4s/.mp4).

Response: [200] application/dash+xml

xml
<?xml version="1.0"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" ...>
  <!-- MPEG-DASH manifest content -->
</MPD>

Get Segment File ​

Proxy access to recorded segment files.

GET /api/record/object/{path}

Path parameter: Storage path of the segment file (URL encoded)

Response: [200] Binary media data or [302] redirect to storage URL

Node ​

GET /api/nodes/

Response: [200]

  • alias: String, Alias must be unique
  • url: String, Node API URL
  • status: StringEnum("running" | "stopped"), Node contact health: the latest poll result for poll nodes (any HTTP response counts as reachable), the SSE connection state for sse nodes, and the discovery presence for net4mqtt nodes
  • duration: String, Round-trip of the latest node contact (e.g. "12ms"): the poll RTT for poll nodes, the SSE connect handshake RTT for sse nodes, or the /api/info fetch RTT whenever liveman refreshes the node's build info; "-" until the first successful contact
  • info: Object, optional — the node's own GET /api/info build information (version, gitHash, buildTime, features), cached by liveman and refetched on reconnect; absent until the first successful fetch

For Example:

json
[
  {
    "alias": "buildin-0",
    "url": "http://127.0.0.1:55581",
    "status": "running",
    "duration": "3ms",
    "info": {
      "version": "v0.10.2",
      "gitHash": "b789a64",
      "buildTime": "2026-09-28T10:00:00+00:00",
      "features": ["webui", "cascade", "recorder", "source-all"]
    }
  },
  {
    "alias": "buildin-1",
    "url": "http://127.0.0.1:55582",
    "status": "running",
    "duration": "5ms"
  },
  {
    "alias": "buildin-2",
    "url": "http://127.0.0.1:55583",
    "status": "stopped",
    "duration": "-"
  }
]

Source ​

Source management is proxied to a named node ({alias}): liveman rewrites each request to the same path on that node and forwards it with the node's bearer token injected, so cluster clients manage per-node sources through liveman only. Request/response bodies are the node's liveion source API — see live777 API / Source. An unknown alias fails with [503].

GET /api/sources/{alias}

List the node's sources.

POST /api/sources/{alias}/{stream}

Create a source. On success liveman eagerly registers the stream→node mapping so WHEP routing sees it before the next node snapshot.

GET /api/sources/{alias}/{stream}

Get source info.

DELETE /api/sources/{alias}/{stream}

Delete the source.

GET /api/sources/{alias}/{stream}/state

Get the source runtime state.

GET /api/sources/{alias}/{stream}/bitrate

Get the encoder bitrate telemetry.

GET /api/sources/{alias}/{stream}/tier

Get the source quality tiers.

POST /api/sources/{alias}/{stream}/tier

Apply a source quality tier.

Stream ​

Get all Stream ​

This API will merge all nodes streams

GET /api/streams/

Response: [200]

  • id: String, streamId
  • createdAt: Int, timestamp
  • publish: Object(PubSub), about publisher
  • subscribe: Object(PubSub), about subscriber
  • (publish | subscribe).leaveAt: Int, timestamp
  • (publish | subscribe).sessions: Array, sessions
  • (publish | subscribe).sessions.[].id: String, sessionId
  • (publish | subscribe).sessions.[].createdAt: Int, timestamp
  • (publish | subscribe).sessions.[].state: String, RTCPeerConnection/connectionState
  • (publish | subscribe).sessions.[].cascade: Optional(Object(Cascade)

For Example:

json
[
  {
    "id": "push",
    "createdAt": 1719326206862,
    "publish": {
      "leaveAt": 0,
      "sessions": [
        {
          "id": "08c1f2a0a60b0deeb66ee572bd369f80",
          "createdAt": 1719326206947,
          "state": "connected"
        }
      ]
    },
    "subscribe": {
      "leaveAt": 1719326206862,
      "sessions": []
    }
  },
  {
    "id": "pull",
    "createdAt": 1719326203854,
    "publish": {
      "leaveAt": 0,
      "sessions": [
        {
          "id": "41b2c52da4fb1eed5a3bff9a9a200d80",
          "createdAt": 1719326205079,
          "state": "connected",
          "cascade": {
            "src": "http://localhost:7777/whep/web-0",
            "resource": "http://localhost:7777/session/web-0/aabc02240abfc7f4800e8d9a6f087808"
          }
        }
      ]
    },
    "subscribe": {
      "leaveAt": 1719326203854,
      "sessions": []
    }
  },
  {
    "id": "web-0",
    "createdAt": 1719326195910,
    "publish": {
      "leaveAt": 0,
      "sessions": [
        {
          "id": "0dc47d8da8eb0a64fe40f461f47c2a36",
          "createdAt": 1719326196264,
          "state": "connected"
        }
      ]
    },
    "subscribe": {
      "leaveAt": 0,
      "sessions": [
        {
          "id": "aabc02240abfc7f4800e8d9a6f087808",
          "createdAt": 1719326204997,
          "state": "connected"
        },
        {
          "id": "dab1a9e88b2400cfd4bcfb4487588ef3",
          "createdAt": 1719326206798,
          "state": "connected",
          "cascade": {
            "dst": "http://localhost:7777/whip/push",
            "resource": "http://localhost:7777/session/push/08c1f2a0a60b0deeb66ee572bd369f80"
          }
        },
        {
          "id": "685beee8650b761116b581a4a87ca9b9",
          "createdAt": 1719326228314,
          "state": "connected"
        }
      ]
    }
  }
]

Get a Stream Details ​

This API will return a stream in all nodes

GET /api/streams/:streamId

Response: [200]

json
{
  "buildin-1": {
    "id": "web-0",
    "createdAt": 1719415906241,
    "publish": {
      "leaveAt": 0,
      "sessions": []
    },
    "subscribe": {
      "leaveAt": 0,
      "sessions": [
        {
          "id": "04eaae154975b61d62fc2e81b2b0862f",
          "createdAt": 1719415906274,
          "state": "connected"
        }
      ]
    }
  },
  "buildin-0": {
    "id": "web-0",
    "createdAt": 1719415876416,
    "publish": {
      "leaveAt": 0,
      "sessions": [
        {
          "id": "6ea2c116b93dde47032c7ea19349dc78",
          "createdAt": 1719415876510,
          "state": "connected"
        }
      ]
    },
    "subscribe": {
      "leaveAt": 0,
      "sessions": [
        {
          "id": "369227db507bf2addbb55313e0eb99a0",
          "createdAt": 1719415885569,
          "state": "connected"
        }
      ]
    }
  }
}

Streams SSE ​

This API pushes the same merged view as GET /api/streams/

GET /api/sse/streams

Server-Sent Events endpoint. Requires the same auth as admin routes.

Pushes the full merged snapshot of all streams (per-node snapshots merged by stream id) whenever the stored cluster state changes. Each SSE message is a JSON array of stream objects, in the same shape as GET /api/streams/ (including the statsScope marking). The optional ?nodes=<alias> query parameter (repeatable) restricts the view to the given nodes, exactly like GET /api/streams/.

The first message is sent when the connection is established; subsequent messages are sent on every state change, with identical consecutive payloads suppressed. Nodes updated by polling refresh on the poll cadence while at least one client is connected.

Released under the MPL-2.0 License.