MistServer API Explained: How to Automate Streams, Pushes & Monitoring on a VPS

MistServer controls everything — starting a push, adding a stream, pulling live viewer stats — through a single JSON API on port 4242, no plugin or separate REST layer required. Send an HTTP GET or POST to /api with a command parameter containing a JSON object, and MistController executes it and replies in JSON. On a VPS, this means you can script MistServer the same way you’d script Wowza’s REST API or Flussonic’s HTTP API — cron a nightly push, kick off a restream on a webhook, or scrape stats into Prometheus — without touching the built-in web dashboard.

Key Takeaways

  • MistServer’s entire configuration and control surface is one JSON API on port 4242 (/api or /api2), not a REST resource tree like Wowza or Ant Media use.
  • Localhost API calls skip authentication by default — if you reverse-proxy the API port, you must forward X-Real-IP or X-Forwarded-For or every proxied request will be treated as trusted localhost traffic.
  • Remote authentication uses an MD5 challenge-response handshake (CHALL → hash password+challenge → OK), not a static API key or bearer token.
  • addstream, push_start, deletestream, and nuke_stream cover the core lifecycle of a stream: adding a source, relaying it elsewhere, removing it cleanly, or force-killing a stuck session.
  • Prometheus-compatible metrics are built in — start the controller with --prometheus PASSPHRASE and scrape /PASSPHRASE.json on the same port 4242, no third-party exporter needed.

How Do You Send a Command to the MistServer API?

Every MistServer action — reading config, adding a stream, starting a push — goes through the same door: an HTTP GET or POST to the controller’s API port (4242 by default) with a command parameter holding a JSON object. Point a browser at http://your-vps-ip:4242 directly and you get MistServer’s built-in web interface, which is itself just a client of this same API. Point a script at /api or /api2 and you always get raw JSON back — /api2 additionally sets "minimal":1 automatically, which trims the verbose streams/config/log blocks MistServer otherwise attaches to every response for historical reasons.

In practice, most people don’t hand-build the URL encoding. MistServer ships a bash helper, mist_api.sh, that wraps this into a mistCall function:

mistCall '{"addstream":{"livestream01":{"source":"push://localhost@password"}}}'

Response:

{"LTS":1,"authorize":{"local":true,"status":"OK"},"streams":{"incomplete list":1,"livestream01":{"name":"livestream01","source":"push://localhost@password"}}}

LTS is a legacy field kept for backward compatibility across versions — every response includes it. On our own MistServer test VPS, we wired mistCall into a systemd oneshot unit that adds a fresh push-based stream slot before each scheduled broadcast and tears it down afterward with deletestream, instead of hand-editing the config file and restarting the controller.

How Does MistServer API Authentication Work?

If the API is called from the same machine running MistServer, there’s no authentication step at all — every local request is trusted automatically, which is what the "local":true field in the response above confirms. That’s convenient for scripts running on the VPS itself, but it’s also the single most common misconfiguration we see: put MistServer behind an nginx reverse proxy without forwarding X-Real-IP or X-Forwarded-For, and MistServer sees every proxied request as coming from 127.0.0.1 — meaning anyone who can reach the proxy gets unauthenticated, full-control API access.

For genuine remote access, MistServer uses a challenge-response handshake instead of a static token:

  1. Send {"authorize":{"username":"admin","password":""}} with no password.
  2. MistServer replies with {"authorize":{"status":"CHALL","challenge":"<random-string>"}}.
  3. Compute password_hash = MD5( MD5("your-plaintext-password") + challenge ).
  4. Resend {"authorize":{"username":"admin","password":"<password_hash>"}} — a status of "OK" means you’re authenticated for the rest of that connection.

A status of "NOACC" means no account exists yet, and MistServer will let you create one via {"authorize":{"new_username":"...","new_password":"..."}} — but only in that no-account state, and MistServer’s own docs are explicit that this bootstrap path is plaintext and unsafe over a public network. Do that step once, over SSH tunnel or localhost, not over the open internet.

How Do You Add, Push, and Remove a Stream Through the API?

Four calls cover most day-to-day stream lifecycle automation:

  • addstream creates a new stream and its source. {"addstream":{"livestream01":{"source":"push://localhost@password"}}} sets up a push-ingest slot; optional fields like DVR (buffer window in ms) and segmentsize can be included in the same call.
  • push_start sends a live stream to an external target — RTMP, SRT, HLS pull, whatever the target protocol supports. {"push_start":{"stream":"livestream01","target":"rtmp://a.rtmp.youtube.com/live2/<key>"}} kicks off a restream immediately. There’s no response to confirm success, which is a real operational gotcha: you need to follow up with push_list to see whether the push actually connected.
  • deletestream removes a stream’s configuration cleanly: {"deletestream":["livestream01"]}.
  • nuke_stream force-kills every connection tied to a stream and resets its internal state — the tool of choice when a stream is stuck rather than merely offline: {"nuke_stream":"livestream01"}.

The STREAMNAME argument to push_start also supports wildcards, which matters if you run a multi-tenant setup: foo matches only the exact stream foo, foo+ matches every stream published under the foo+ wildcard pattern, and foo+bar matches only the specific wildcard value bar. We use this on shared VPS instances to push every stream under a client47+ prefix to that client’s own restream target with a single rule, instead of maintaining one push_start call per stream.

MistServer API vs Wowza, Flussonic & Ant Media APIs

EngineDefault API portRequest formatAuth modelResponse style
MistServer4242Single command JSON param over GET/POSTMD5 challenge-response, localhost bypassJSON, single endpoint (/api, /api2)
Wowza Streaming Engine8087REST resource paths (/v2/servers/.../applications)Basic/Digest auth via Server.xmlJSON, resource-per-URL
Flussonic Media Server80/443REST collection paths (/streamer/api/v3/)Basic/Bearer, JSON Merge Patch on PUTJSON, resource-per-URL
Ant Media Server5080REST resource paths (/rest/v2/broadcasts)JWT / API key headerJSON, resource-per-URL

The practical difference: Wowza, Flussonic, and Ant Media all model their APIs as REST resources — a URL per stream, per application, per broadcast. MistServer models it as a single RPC-style endpoint where the JSON payload itself decides what happens. That’s less discoverable if you’re used to REST tooling like Postman collections or OpenAPI specs — MistServer has no published OpenAPI schema — but it’s also fewer round trips: you can bundle an addstream and a push_start into one HTTP request instead of two separate calls.

Can You Monitor a MistServer VPS with Prometheus?

Yes, and it’s built into the controller rather than needing a separate exporter binary. Start (or restart) MistController with --prometheus yoursecretpassphrase, and MistServer exposes metrics on the same API port at /yoursecretpassphrase in native Prometheus text format, or /yoursecretpassphrase.json for a JSON version of the same data. Some of the exposed metrics are stream-bound and only populate while that stream has at least one active session — worth knowing before you assume a “missing” metric means a monitoring bug rather than an idle stream. Point your existing Prometheus scrape config at that path on port 4242 alongside whatever you’re already collecting from the VPS host itself (CPU, network, disk), and you get stream-level and server-level metrics in the same dashboard without standing up a second exporter process.

Is the MistServer API Production-Ready for Automation?

For scripted control — adding streams, starting pushes, pulling config and stats — yes, and the single-endpoint model is genuinely simpler to wrap in a shell script than negotiating REST auth headers across three different resource paths. Where it’s honestly weaker than Wowza or Flussonic is community tooling: there’s no official Postman collection, no OpenAPI/Swagger spec, and far fewer third-party client libraries — you’re working from the mist_api.sh bash wrapper, a PHP example, and the docs themselves. For event notifications rather than polling, MistServer’s separate triggers system is the better fit: triggers push a payload to a URL or executable the moment something happens (stream start, push end, user connect), rather than you polling the API on a timer. Treat the API as the control plane and triggers as the event plane — using both together, the way we do on our own MistServer VPS deployments, covers most automation needs without extra middleware.

Frequently Asked Questions

What port does the MistServer API use by default?

Port 4242, for both the JSON command API and the built-in web interface — the same port serves both, and MistServer decides which to return based on whether the request targets /api//api2 or any other path.

Do API calls from the same server require a password?

No — MistServer trusts any request originating from localhost automatically and skips authentication, which is why reverse-proxied deployments must forward X-Real-IP or X-Forwarded-For to avoid accidentally exposing unauthenticated control access.

Can I add and remove streams entirely through the API, without editing config files?

Yes — the addstream call creates a stream and its source in one request, and deletestream removes it cleanly; nuke_stream is available separately to force-kill a stuck stream’s connections rather than just deconfigure it.

Does MistServer support WebSockets for the API?

Yes, at ws://your-server:4242/ws — the WebSocket variant only supports the HTTP-header style of authentication (an Authorization: json {...} header), not the in-band challenge-response flow used over plain HTTP.

Is there a way to monitor MistServer without polling the API on a timer?

Yes — use triggers for event-driven notifications (stream start/stop, push end, etc. posted to a URL or executable the moment they happen) and the built-in Prometheus endpoint for periodic metrics scraping, rather than polling the JSON API in a loop.

Conclusion

MistServer trades REST-style discoverability for a single, scriptable JSON endpoint that covers config, stream lifecycle, and stats in one place — once you know the command parameter pattern and the localhost-auth-bypass gotcha, it’s one of the more compact APIs to automate against on a VPS. Combined with triggers for event push and native Prometheus metrics, it’s enough to run unattended without a third-party orchestration layer.

Get a pre-installed MistServer VPS from StreamingVPS.com — go live in 60 seconds, API and all.

Sources consulted: MistServer API docs, Authentication, push_start, Triggers, Prometheus Instrumentation, Bash API example. See also our guides on the MistServer setup on a VPS, Wowza REST API, and Flussonic HTTP API. Last updated 2026-07-11 by the StreamingVPS.com Engineering Team.

Leave a Reply

Your email address will not be published. Required fields are marked *