Viewer URL parameters & transport

Query parameters you can append to a Wallflower.tv watch or broadcast URL, and how the origin → edge transport hint (xport) works. Developer reference.

Watch / broadcast selectors

ParameterExampleMeaning
stream?stream=ab5ki Broadcast as a given 5-char stream id (broadcaster path).
node?node=<52-char key> Watch a broadcast by its stream key — the broadcaster's Ed25519 public key rendered as base32(publicKey), minted in the browser. Your browser resolves the key to a live origin off the public Mainline DHT (a signed pkarr record; no directory server). The key is itself the capability to watch (a legacy ?luke= alias resolves the same DHT path). Access is token-gated at the relay, but the Worker auto-mints your subscribe token from the key — you never handle a token. This is distinct from the origin relay's own iroh EndpointId, which is a transport address, not the stream name.
publish?publish=1 Go live as a node id: the browser mints an Ed25519 key, assigns an origin, and self-publishes a signed pkarr record to the Mainline DHT so ?node= viewers can resolve it. The broadcaster connects with a publish-scoped token (put:[key]) — the origin is gated.
viewer-cdn direct-mode only?viewer-cdn=ams.moqcdn.net A direct-mode override that forces which provisioning fleet serves this viewer's edge (a cross-cluster edge pulling from the origin, Mode B). Ignored on the brokered production deployment (wallflower.tv / multicast.video): there the broker (cdnadmin) owns box selection and geo-routes the viewer to its nearest fleet automatically — and as of 2026-07-19 makes a non-origin fleet cluster-pull the origin with no override needed (the brokered viewer path returns before this param is read). Use ?geo= to exercise steering on the brokered path; viewer-cdn only takes effect where the app runs in direct mode (calling its own fleet box's /assign).
publisher-cdn direct-mode only?publisher-cdn=ams.moqcdn.net A direct-mode override for which provisioning fleet the broadcaster's origin is assigned on (broadcaster path, incl. ?publish=1). Ignored under brokered (wallflower.tv / multicast.video) — the broker geo-places the origin on the broadcaster's nearest fleet. Must be an allowed fleet host where it does apply (direct mode).
geo?geo=47.60,-122.33 Testing override for the viewer/broadcaster location, forwarded to the broker as hints.geo so geo-nearest routing can be exercised from anywhere (normally derived from request.cf). Works on the origin-placement, fleet-watch, and ?node= edge-placement paths. Since 2026-07-19 this drives real cross-fleet playback: geo-steering a fleet-watch (Model A) viewer to a fleet that isn't the broadcaster's origin makes that fleet cluster-pull the origin over host:port and play — so cross-cluster edge (Mode B) is now automatic under geo routing, no longer only under ?viewer-cdn=.
origin?origin=host:port Testing override on the fleet watch path: force the host:port origin the edge pulls from (normally derived by the Worker). The old &origin=HOST:PORT browser form of the retired luke directory gateway is gone; on the ?node= path the origin comes from the signed DHT record, not this param.
xport transport hint?xport=iroh Selects the origin → edge transport. See below.

xport — origin → edge transport hint

On a cross-cluster (?viewer-cdn=) or enterprise watch URL, xport tells the TinyMoQ CDN how the edge should pull the stream from the origin:

ValueEffect
irohThe edge pulls from the origin over iroh — mainline-DHT discovery, NAT-friendly, so the origin needs no public host:port.
(absent / any other value)Default: the edge pulls over native QUIC by host:port. The request is byte-identical to a URL with no xport at all.
Gated-origin caveat (2026-07). Origins are now token-gated, and the edge's pull token reaches the origin only over the host:port QUIC connect. So on the live fleet a cross-box pull uses host:port even when ?xport=iroh is requested — the iroh transport does not yet carry the pull token to a gated origin. Iroh origin-pull stays the design target for NAT'd origins (the current fleet is publicly reachable); the fix is deferred.

How the hint travels (it is forwarded verbatim, never interpreted client-side):

Mode B (?viewer-cdn=):
  browser URL ?xport=iroh
    -> GET /api/streams/<id>/route?viewer-cdn=…&xport=iroh   (player)
    -> Worker /route reads xport, calls assignRelay(…, xport)
    -> GET https://<edge>/assign?broadcast=…&xport=iroh        (server-side)

Mode C (enterprise, on-net edge):
  browser URL ?xport=iroh
    -> GET https://<relay>/assign?broadcast=…&xport=iroh        (browser preflight)
Two things people get wrong:

"Origin link" stats line

For a cross-cluster watch, the player confirms the actual origin → edge transport by polling a public, read-only endpoint on the edge (~1.5 s after connect, re-polling every 5 s; the line is hidden on unknown or any error):

GET https://<edge-host>/edge_xport?broadcast=<rawBroadcastId>
  (port 443, no auth, CORS *; the broadcast id is substring-matched)

-> { "xport": "iroh" | "quic" | "unknown", "origin": "<host:port>" }

It renders one of:

xportStats line shown
irohOrigin link: iroh / DHT
quicOrigin link: <origin> (QUIC)
unknown / error(line hidden)

See also

Full architecture (PDF) — infrastructure, routing & the three-hop transport model that xport plugs into.