Ir al contenido

HTTP API

Esta página aún no está disponible en tu idioma.

Request and response bodies are JSON. Endpoints that take a body expect Content-Type: application/json. The base URL throughout this page is http://headend.local:8080; substitute the address and the port you configured with --port.

Channel identifiers in paths are the numeric id from the configuration file. They are reused after a delete, so a script that caches an identifier across a reconfiguration can act on the wrong channel.

MethodPathPurpose
GET/loginThe login page itself. Of no use to a script; listed so that an unexpected HTML response to an API call is recognisable as a redirect to it.
POST/api/loginExchange username and password for a session cookie. Credentials are the values of CASTMUX_WEB_USERNAME and CASTMUX_WEB_PASSWORD.
POST/api/logoutInvalidate the current session.

With curl, store the cookie in a jar on login and present the jar afterwards:

Terminal window
# log in, keeping the session cookie
curl -s -c cookies.txt \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"correct-horse-battery"}' \
http://headend.local:8080/api/login
# now call an authenticated endpoint with the same jar
curl -s -b cookies.txt \
http://headend.local:8080/api/viewers
MethodPathPurpose
GET/api/versionVersion, commit and build time of the running binary. Deliberately unauthenticated, so a monitoring system can confirm what is deployed on every appliance in an estate without being given credentials to change anything on them.
Terminal window
curl -s http://headend.local:8080/api/version
# {"version":"3.1.0","commit":"9f2c41a","buildTime":"2026-04-08T09:12:44Z"}
MethodPathPurpose
Lifecycle
POST/api/channelsCreate a channel. The body is the same shape as one entry under streams in the configuration file. The assigned identifier is returned.
PUT/api/channels/{id}Replace the settings of an existing channel. A running channel is restarted if the change affects how it runs.
DELETE/api/channels/{id}Remove a channel. Stops it first. The identifier becomes available for reuse.
POST/api/channels/{id}/restartRestart one channel without touching the others. The first thing to try when a single channel is misbehaving and the rest are healthy.
State
POST/api/streams/{id}/activeEnable or disable a channel. A disabled channel keeps its configuration but is never started.
POST/api/streams/{id}/force-always-onToggle the always-on override. On, the channel runs continuously; off, it runs when viewer detection sees somebody watching.
Inspection
GET/api/channels/{id}/logsRecent engine output for one channel. This is where a source error appears in the words the origin actually used, rather than as a generic failure.
GET/api/channels/resolutionsThe resolution currently selected for each channel, and whether it is an exact match for the requested profile or the closest rung the origin offered. Served from cache; it does not block on origin fetches.
Preview
POST/api/channels/{id}/previewStart a browser-viewable preview of a channel.
POST/api/channels/{id}/preview/stopStop it. Previews consume real CPU, so stop them explicitly rather than relying on closing the page.
Terminal window
# create a channel
curl -s -b cookies.txt -X POST \
-H 'Content-Type: application/json' \
-d '{
"name": "Example One",
"description": "Main lounge line-up",
"active": true,
"force_always_on": false,
"engine": "tsduck",
"resolution_profile": "hd",
"source": {"type": "hls", "url": "https://origin.example.net/one/master.m3u8"},
"destination": {"address": "239.10.0.1", "port": 5000}
}' \
http://headend.local:8080/api/channels
MethodPathPurpose
GET/api/viewersViewer state for every channel in one call. Use this for polling rather than looping over channels, which multiplies the request count by the size of the line-up.
GET/api/streams/{id}/viewersDetail for one channel: the list of client addresses currently joined, the count, a flag for whether an IGMP querier is present on the segment, and a flag for whether detection is degraded.
MethodPathPurpose
Measurement
GET/api/metricsSystem metrics and per-channel metrics in one document: CPU, memory, uptime, per channel state and throughput. Cached for about two seconds server-side, so polling faster than that returns the same numbers and only costs you request handling.
GET/api/network-statsInterface-level counters and reachability results for the hosts in ping_hosts.
GET/api/udp-bitrateMeasured bitrate actually leaving the network port, per channel. This is the engine-agnostic liveness signal: it reflects what is on the wire rather than what a decoder claims it is producing.
Administration
PUT/api/settingsReplace the global settings. PUT only — there is no GET variant, so read current settings from the configuration file.
POST/api/restart-allRestart every channel. Starts are staggered by startup_stagger_seconds, so the whole line-up does not come back at once and fail together.
POST/api/rebootReboot the appliance. Every channel is off air for the duration; this is not a remedy for a channel fault.
MethodPathPurpose
Multiplexes
GET/api/dvb/muxesList the configured multiplexes with their RF parameters and current state. Unlike channels, multiplexes do have a read endpoint.
POST/api/dvb/muxesCreate a multiplex.
PUT/api/dvb/muxes/{id}Update RF parameters or signalling identifiers. Changing frequency, modulation or symbol rate interrupts the carrier.
DELETE/api/dvb/muxes/{id}Remove a multiplex. The channels it carried are not deleted.
POST/api/dvb/muxes/{id}/activeStart or stop transmission of the carrier.
Contents and operations
POST/api/dvb/muxes/{id}/channelsAssign the channels carried, and their order. The order determines service identifiers, so reordering re-identifies services and can require televisions to re-tune. Append rather than insert where you have the choice.
GET/api/dvb/muxes/{id}/logsMultiplexer and modulator output for this carrier.
POST/api/dvb/muxes/{id}/hot-swapExchange the contents of a running multiplex without dropping the carrier, so sets stay tuned rather than reporting no signal during the change.
POST/api/dvb/muxes/{id}/suspendSuspend the multiplex temporarily, for maintenance on the modulator or the cable network, without deleting the configuration.
MethodPathPurpose
POST/api/hdmi/activeEnable or disable the HDMI output.
POST/api/hdmi/configSet which channel is presented on the HDMI port and how it is rendered.
GET/api/hdmi/metricsState and throughput of the HDMI output.
GET/api/hdmi/logsOutput from the HDMI rendering process.

A worked example: log in, create three channels, create a multiplex, and assign the channels to it in the order they should appear. This is the whole commissioning sequence for a small site, and it is worth scripting because typing three channels into a form is where transposed multicast addresses come from.

#!/usr/bin/env bash
set -euo pipefail
BASE="http://headend.local:8080"
JAR="$(mktemp)"
# 1. log in ------------------------------------------------------------
curl -sf -c "$JAR" -H 'Content-Type: application/json' \
-d "{\"username\":\"$CASTMUX_USER\",\"password\":\"$CASTMUX_PASS\"}" \
"$BASE/api/login" > /dev/null
# 2. create the channels ------------------------------------------------
# name | multicast group | source playlist
CHANNELS=(
"Example One|239.10.0.1|https://origin.example.net/one/master.m3u8"
"Example Two|239.10.0.2|https://origin.example.net/two/master.m3u8"
"Example News|239.10.0.3|https://origin.example.net/news/master.m3u8"
)
IDS=()
for row in "${CHANNELS[@]}"; do
IFS='|' read -r NAME GROUP URL <<< "$row"
ID=$(curl -sf -b "$JAR" -X POST -H 'Content-Type: application/json' \
-d "{
\"name\": \"$NAME\",
\"active\": true,
\"force_always_on\": true,
\"engine\": \"tsduck\",
\"resolution_profile\": \"hd\",
\"source\": {\"type\": \"hls\", \"url\": \"$URL\"},
\"destination\": {\"address\": \"$GROUP\", \"port\": 5000}
}" \
"$BASE/api/channels" | sed -n 's/.*"id":\([0-9]*\).*/\1/p')
echo "created $NAME as id $ID"
IDS+=("$ID")
# respect the stagger: three HLS origins opened at once is the
# failure this setting exists to prevent
sleep 3
done
# 3. create the multiplex ------------------------------------------------
MUX=$(curl -sf -b "$JAR" -X POST -H 'Content-Type: application/json' \
-d '{
"name": "Mux A",
"device": 0,
"frequency": 474000000,
"qam": 256,
"symbol_rate": 6900,
"network_id": 1,
"ts_id": 1,
"network_name": "Seaview Court",
"active": true
}' \
"$BASE/api/dvb/muxes" | sed -n 's/.*"id":\([0-9]*\).*/\1/p')
# 4. assign the channels, in line-up order -------------------------------
# this order fixes the service IDs; changing it later means a re-tune
LIST=$(IFS=,; echo "${IDS[*]}")
curl -sf -b "$JAR" -X POST -H 'Content-Type: application/json' \
-d "{\"channel_ids\": [$LIST]}" \
"$BASE/api/dvb/muxes/$MUX/channels"
rm -f "$JAR"

Two details in that script are not incidental. The sleep 3 between creations matches startup_stagger_seconds: three HLS origins opened simultaneously is the exact condition the stagger exists to avoid, and a build script is the easiest way to recreate it. And the channels are assigned in one call rather than three, because assignment order sets the service identifiers — building the list first and posting it once means the line-up is numbered as intended on the first attempt.

  • Errors are JSON. A failed request returns an appropriate status code and a JSON body describing the problem. An HTML response means the request was not authenticated and was redirected to the login page — check the cookie jar before debugging the body.
  • PUT /api/settings replaces, it does not merge. Send the complete set of global settings; anything omitted reverts to its default. The new settings are applied to running channels without restarting them.
  • Reads are incomplete. Channels can be created, updated and deleted through the API but not enumerated through it. Multiplexes can be listed. Until that is even, any script that needs the current configuration should read the configuration file.
  • Rate limiting is not a substitute for cached data. /api/metrics is cached for about two seconds; a dashboard polling it every 250 ms produces eight identical answers and no extra information.

A full read API, whole-configuration export and import, and API tokens in place of session cookies are all roadmap. They are listed with the rest on the roadmap page.