Implementation reference

Net-X-Router REST API

This page documents the HTTP commands implemented by the current Net-X-Router service. The primary control endpoint is /config. Most operations use an action, a paramid, and an optional value in the query string.

Audited against the Net-X-Router source on 2026-07-20.

Quick start

GET/heartbeat
{"alive":true,"service":"netxrouter","status":"ok"}
GET/config?action=get&paramid=eParamID_StatusAll

Returns all 16 input slots, their basic transport analysis, redundancy state, and their destination slots.

GET/config?action=set&paramid=eParamID_XPT_Destination1_Status&value=3

In traditional routing mode, connects Source 3 to Destination 1. Use value=0 to disconnect it.

{"name":"eParamID_XPT_Destination1_Status","value":"3","value_name":"3"}
GET/config?action=get_events&after=0&limit=100

Returns the latest router events and a sequence cursor for subsequent polling.

Request contract

ItemContract
Base URLhttp://<router-host>:<http-port>
MethodThe current UI and examples use GET. The callback reads commands from the request URI query string.
Parameter endpoint/config?action=get|set&paramid=<id>&value=<value>. Legacy parameter clients may use /options with the same query.
configidLegacy clients send configid=0. It is accepted but not used by Net-X-Router.
EncodingPercent-encode every query value. This is essential for JSON, URLs, ampersands, passwords, spaces, and license keys.
IndexingRoute, setup, monitor, analyzer selection, and button parameter IDs are 1-based. The index field inside StatusAll is 0-based.
Response formatMost responses are compact JSON. Several compatibility operations deliberately return plain text such as ok, true, or 16.
Unknown commandUsually returns HTTP 200 with {} or a generic empty-value object. Validate the body; do not treat HTTP 200 alone as command success.
State-changing operations currently place their values in the URL. Use the API only on a trusted control network and avoid logging URLs that contain passwords or license keys.

Endpoint index

CommandPurposeResponse
GET /heartbeatLightweight liveness checkJSON object
GET /config?heartbeat=1Heartbeat compatibility formJSON object
action=connectLegacy UI connection handshake{"connectionid":"42"}
action=getRead a parameterParameter-specific
action=setWrite a parameterParameter-specific
action=wait_for_config_eventsConsume queued UI configuration changesJSON array
action=get_eventsSearch or incrementally poll the event historyJSON object
?licenseRead license stateJSON object
?versionRead current/latest version informationJSON object
?generateSiteCodeGenerate a site codePlain text
?registerLicenseKeyRegister a license keyPlain true/false
?directoryPasswordSet web directory Basic Auth passwordPlain ok/fail

/options is a compatibility alias for general action=connect|get|set parameter requests. Use /config for new clients and for heartbeat, events, and configuration-event polling. /descriptors has one special compatibility response documented under Signal switching.

Health and system

GET/heartbeat
GET/config?heartbeat=1

Both forms are independent of stream/router state and return the same body:

{
  "alive": true,
  "service": "netxrouter",
  "status": "ok"
}
GET/config?action=connect

Compatibility handshake used by the web parameter framework. The connection ID is currently fixed.

{"connectionid":"42"}
GET/config?action=get&paramid=eParamID_SysName

Returns the plain text service name:

netxrouter

Events

GET/config?action=get_events&after=<sequence>&limit=<1..500>&severity=<name>&query=<text>

This is the non-destructive, searchable event feed used by the Events page.

QueryDefaultMeaning
after0With zero, return the latest matching events. Otherwise return matching events whose sequence is greater than this cursor.
limit100Number of results, clamped to 1 through 500.
severityallExact, case-insensitive severity name: debug, info, warning, or error. Empty and all disable this filter.
queryemptyCase-insensitive substring match against the compact JSON representation of each event.
{
  "available": true,
  "events": [ ... ],
  "oldest_sequence": "1",
  "latest_sequence": "84",
  "next_sequence": "84",
  "has_more": false,
  "history_capacity": 2000,
  "truncated": false
}

If event initialization failed, the response also contains error. If truncated is true, the requested cursor predates the oldest event still retained.

Event object

FieldTypeDescription
sequencedecimal stringRouter-local polling sequence.
event_iddecimal stringdtEvents numeric event ID.
event_typestringFor example source.missing, source.restored, source.ts_problem, destination.connected, or button.lock_changed.
source_id, source_namestringOriginating router object.
messagestringDisplayable description.
severity, severity_namenumber, stringNumeric dtEvents severity and normalized name.
action, dedupe_key, correlation_idstringLifecycle/search metadata.
utc_ns, ptp_ns, pts, duration_msdecimal stringHigh-range integer values are strings to avoid JSON number precision loss.
utc_isostring, optionalUTC ISO-8601 timestamp when utc_ns is nonzero.
timecode, unitsstringOptional media/value context.
value, thresholdnumberOptional measured and threshold values.
details_jsonstringOriginal dtEvents details JSON.
detailsobject/array, optionalParsed form of details_json when valid.
GET/config?action=wait_for_config_events

Legacy UI configuration-event queue. It returns an array and removes the returned events from the queue.

[
  {"param_id":"eParamID_XPT_Source1_Line_1","str_value":"Camera 1"},
  {"param_id":"eParamID_XPT_Destination1_Locked","int_value":1}
]
wait_for_config_events is destructive. Use get_events for the searchable router event history.

Parameter API

All parameter commands use this canonical form:

GET /config?action=get&configid=0&paramid=<parameter-id>
GET /config?action=set&configid=0&paramid=<parameter-id>&value=<percent-encoded-value>

The tables below use N for a 1-based source or destination number from 1 through 16 and L for button label line 1 or 2.

Routing

Traditional mode

GETeParamID_XPT_DestinationN_Status

Get the 1-based source routed to Destination N. Value 0 means no source.

GETaction=set&paramid=eParamID_XPT_DestinationN_Status&value=<source>

Route the destination to a source, or disconnect with value=0.

{
  "name": "eParamID_XPT_Destination1_Status",
  "value": "3",
  "value_name": "3"
}

If a locked destination rejects the change, the response retains the current route and adds "locked":true.

Multi-output mode

GETeParamID_XPT_SourceN_Status

Returns the configured destination map for Source N.

GETaction=set&paramid=eParamID_XPT_SourceN_Status&value=<source>,<destination>,<true|false>

Enable or disable one source/destination connection. Both numbers in the CSV value are 1-based. The parameter's N should match the source in the value.

{
  "name": "eParamID_XPT_Source2_Status",
  "value": {
    "1": {
      "enabled": true,
      "disabled": false,
      "disable": false,
      "url": "srt://192.168.50.80:9000?mode=caller",
      "type": 3
    }
  }
}

A rejected locked-destination change adds "locked":true.

Compatibility detail: in this response, each connection's url and type currently echo the source input URL/type. Use eParamID_StatusAll when destination URL/type values are required.

Destination locking

GETeParamID_XPT_DestinationN_Locked
GETaction=set&paramid=eParamID_XPT_DestinationN_Locked&value=<0|1>
{"name":"eParamID_XPT_Destination1_Locked","value":true}

A locked destination rejects route changes in both router modes. Setting the value to 0 unlocks it.

Router mode

GET/config?action=get&paramid=eParamID_XPT_ChangeRouterMode0
GET/config?action=get&paramid=eParamID_XPT_ChangeRouterMode1

The mode is encoded in the parameter ID: 0 is traditional and 1 is multi-output. The service reloads saved settings for the selected mode and returns plain text ok.

Input/output setup

GETaction=set&paramid=eParamID_SetupIO_Source_N&value=<json>
GETaction=set&paramid=eParamID_SetupIO_Destination_N&value=<json>

The setup value is a percent-encoded JSON object:

{
  "type": 3,
  "url": "srt://192.168.50.80:9000?mode=caller&latency=120",
  "disabled": false
}
FieldTypeMeaning
typeinteger or numeric stringProtocol type ID from the protocol table below.
urlstringComplete transport or file URL. The URL scheme selects the transport implementation.
disabledboolean/number/stringOnly applied to file sources/destinations. disable is accepted as a compatibility alias.

A successful update returns plain text ok. Reconfiguring a source preserves its configured destination relationships.

Remove an input or output

Send the same setup parameter with an empty URL:

{"type":10,"url":"","disabled":false}

Source removal disconnects and destroys the source. Destination removal is implemented for traditional mode.

Setup parameters are write-oriented. A get request currently returns plain ok, not the saved configuration. Read current setup from eParamID_StatusAll.

Percent-encoding example

const value = encodeURIComponent(JSON.stringify({
  type: 3,
  url: "srt://192.168.50.80:9000?mode=caller&latency=120",
  disabled: false
}));

fetch("/config?action=set&configid=0&paramid=eParamID_SetupIO_Source_1&value=" + value);

Status and usage

GET/config?action=get&paramid=eParamID_StatusAll

Returns an array with exactly one object for each input slot. The top-level input index is 0-based.

[
  {
    "index": 0,
    "status": 3,
    "type": 10,
    "disabled": false,
    "disable": false,
    "url": "file:///G:/test.ts?loop=1",
    "datarate": 18,
    "analysis": { ...basic analyzer object... },
    "redundancy": {"enabled":false},
    "destinations": [
      {
        "status": 4,
        "status_msg": "",
        "enabled": true,
        "type": 2,
        "url": "rtp://239.1.1.1:5000",
        "datarate": 18,
        "disabled": false,
        "disable": false,
        "redundancy": {"enabled":false}
      }
    ]
  }
]

Unconfigured inputs contain only index and status:0. A source in the illegal state can also include status_msg. Destination arrays contain 16 entries when the source is configured; optional configuration fields appear when that source/destination pair exists.

Basic analyzer object

Each active input is analyzed on a separate best-effort, low-priority path. StatusAll.analysis is a cached snapshot refreshed at most four times per second.

FieldType
enabled, lockedboolean
analysis_leveloff, basic, or full
packets, bytes, sync_errors, transport_errors, continuity_errors, duplicate_packets, missing_packets, problem_countdecimal string
duration_sec, bitrate_mbps, packet_ratenumber
program_count, stream_count, video_streams, audio_streams, metadata_streamsinteger
codecsarray of unique codec display names
streamsarray of {program_number,pid,pid_hex,category,codec_name}
GET/config?action=get&paramid=eParamID_Usage
{"cpu":12,"mem":123456789,"netIn":66,"netOut":28}

cpu is system CPU use, mem is the system-used-memory value reported by the platform helper, and netIn/netOut are aggregate router data rates in Mbps.

GET/config?action=get&paramid=eParamID_ButtonsPerType

Returns the maximum source count and destination count as plain text. The current value is:

16

Transport stream analyzer

The selected analyzer uses full TS analysis. It is independent of the selected route and the web monitor source.

GETeParamID_TsAnalyzeSource
GETaction=set&paramid=eParamID_TsAnalyzeSource&value=<0..16>

Select a 1-based input. Value 0 closes/disconnects the selected analyzer.

{"name":"eParamID_TsAnalyzeSource","sourceIndex":4,"value":"4"}
GETeParamID_TsAnalyzeConfig
GETaction=set&paramid=eParamID_TsAnalyzeConfig&value=<0|1>

Enable or disable full analysis for the selected source. The setting is persistent and defaults to enabled.

{"name":"eParamID_TsAnalyzeConfig","value":"1","enabled":true}
GETeParamID_TsAnalyzeStatus
{
  "name": "eParamID_TsAnalyzeStatus",
  "sourceIndex": 4,
  "source": {
    "index": 4,
    "input": { ...full analyzer object... }
  }
}

If no configured input is selected, source is omitted.

Full analyzer object

The object under source.input contains:

GroupFields
State/countersenabled, analysis_level, locked, packets, bytes, sync_errors, transport_errors, continuity_errors, duplicate_packets, missing_packets, problem_count
Transporttransport_stream_id, pat_version, duration_sec, bitrate_mbps, packet_rate
Programsprograms[] with program_number, PMT/PCR PIDs in decimal and hex, pmt_version, program descriptors[], components[], and optional PMT/PCR stats.
ComponentsPID, stream type, category, codec identifiers/display name, registration, language(s), parsed details, descriptors, and optional PID stats.
All PIDspids[] and optional null_pid.

PID statistics object

{
  "pid": 256,
  "pid_hex": "0x0100",
  "packets": "12345",
  "bytes": "2320860",
  "payload_packets": "12000",
  "adaptation_packets": "345",
  "continuity_errors": "0",
  "duplicate_packets": "0",
  "missing_packets": "0",
  "discontinuities": "0",
  "scrambled": false,
  "has_pcr": true,
  "pcr_jitter_ms": 0.04,
  "pcr_drift_ms": 0.12
}

Descriptor-derived details vary by stream. They can include video profile/level, frame dimensions and rate, scan type, audio layer/profile/channel configuration, ISO-639 language/audio type, AC-3/E-AC-3 properties, caption services, component names, and registration identifiers.

Web monitor control

These commands control which router input feeds the fixed WebRTC monitor. WebRTC signaling and media are served by the dtx_webrtc output on the separate port returned by MonitorStatus; they are not served by the REST port.

GETeParamID_MonitorSource
GETaction=set&paramid=eParamID_MonitorSource&value=<0..16>

Select a 1-based input. Value 0 closes the monitor output.

{"sourceIndex":1}
GETeParamID_MonitorConfig

Returns whether the monitor output exists. Configuration is automatic; a set currently has no additional effect.

{"active":true}
GETeParamID_MonitorStatus
{
  "sourceIndex": 1,
  "active": true,
  "status": 4,
  "webrtcPort": 9100,
  "processingActive": true,
  "videoFramesSent": 1523,
  "audioFramesSent": 3046,
  "ringBytesDropped": 0,
  "tsBytesReceived": 28492340,
  "ringDropEvents": 0,
  "maxRingDropBytes": 0,
  "ringBytesAvailable": 1316,
  "lastVideoFrameAgeMs": 16,
  "lastAudioFrameAgeMs": 8,
  "sourceUrl": "file:///G:/test.ts?loop=1",
  "sourceType": 10,
  "sourceStatus": 3,
  "sourceDatarate": 18
}

The processing/ring/frame fields appear only while the monitor output exists. The source fields appear only while a valid configured input is selected. Frame ages are -1 until the corresponding media type has been produced.

Connect the browser peer to http://<router-host>:<webrtcPort>/webrtc.

Buttons and compatibility parameters

Button lists

ParameterActionResponse
eParamID_SourceButtonsgetArray of {"name":"SRC 1","id":"src_01"}.
eParamID_DestinationButtonsgetArray of {"name":"DEST 1","id":"dst_01"}.

Button labels

Parameter patternActionsValue
eParamID_XPT_SourceN_Line_Lget, setSource label line text.
eParamID_XPT_DestinationN_Line_Lget, setDestination label line text.
{"name":"eParamID_XPT_Source1_Line_1","value":"Camera 1","value_name":"Camera 1"}

Button colour classes

GETeParamID_Button_Settings_N
GETaction=set&paramid=eParamID_Button_Settings_N&value={"classes":"<class>"}

N = 1..16 for sources and 17..32 for destinations. The value and value_name response fields contain a JSON string for compatibility:

{
  "name": "eParamID_Button_Settings_1",
  "value": "{\"classes\":\"blue\"}",
  "value_name": "{\"classes\":\"blue\"}"
}

Signal-switching compatibility

RequestResponse
/config?action=get&paramid=eParamID_SignalSwitching{"name":"eParamID_SignalSwitching","value":"0","value_name":"Normal"}
/descriptors?action=get&alt=json&paramid=eParamID_SignalSwitchingA one-element enum descriptor array containing Normal (0), Dual Mode (1), and Quad Mode (2).

This parameter is read-only in Net-X-Router. The current application always reports Normal; the old switch-mode selector is hidden by the UI.

Alarm/identify compatibility

Get requests whose parameter IDs begin with any of the following prefixes return a default value of zero:

eParamID_Suppress eParamID_PSAlarm eParamID_ReferenceAlarm eParamID_TemperatureAlarm eParamID_IdentifyLed

{"name":"eParamID_PSAlarm","value":"0"}

Licensing and web access

GET/config?license
{
  "status": "1",
  "temporary": "False",
  "option": "0",
  "optionstring": "",
  "description": "Registered on ..."
}
GET/config?version
{
  "currentVersion": "8.0.123",
  "newestVersion": "8.0.124",
  "needsUpdate": "1",
  "updateURL": "...",
  "updateDescription": ["..."]
}
GET/config?generateSiteCode&username=<name>&email=<email>

Returns the generated site code as plain text.

GET/config?registerLicenseKey&key=<key>

Returns plain text true when registration succeeds, otherwise false.

GET/config?directoryPassword&password=<password>

Creates/updates the web directory's Basic Auth files for user admin. Returns plain text ok or fail.

License keys, site identity data, and passwords are sensitive. They are query parameters in the current API and can appear in browser, proxy, or server logs.

Shared values

Stream status

ValueNameMeaning
0OffNo threads/no signal.
1WaitingWaiting for an input signal or peer.
2ConnectedTransport connected.
3ReceivingInput data is being received.
4SendingOutput data is being sent.
5ClosingTransport is closing.
6IllegalInvalid configuration or transport error; inspect status_msg.

Protocol type IDs

IDProtocolInputOutputNotes
1UDP transport streamYesYesudp://
2RTP transport streamYesYesrtp://
3SRTYesYesCaller/listener and two-link redundancy.
4RISTWindowsWindowsrist://
5ZixiLicensed buildTraditional/Windows buildCompile-time and SDK/license dependent. Multi-output output factory does not currently create Zixi.
6TCPNoNoReserved for a future uncompressed transport; do not configure.
7HLSYesYeshls://
8RTMPYesYesrtmp://host:port/app/stream-key
9WHIP/WebRTCNoYeswhip://; used for encoded browser output/monitoring.
10FileYesYes188-byte TS only. 192-byte M2TS/AVCHD is rejected.

SRT redundancy status

An SRT redundancy object in StatusAll contains:

{
  "enabled": true,
  "mode": "active-active",
  "role": "caller",
  "expectedLinks": 2,
  "connectedLinks": 2,
  "activeLinks": 2,
  "healthy": true,
  "primary": "192.168.100.10:9000",
  "secondary": "192.168.50.10:9000"
}

Active-backup status can also include stabilityMs. Non-redundant transports return at least {"enabled":false}.

Protocol URL options

The complete URL is carried inside the setup JSON. These options are part of that URL, not top-level REST query parameters.

SRT

srt://primary.example:9000?mode=caller&latency=200&password=secret
srt://primary.example:9000?mode=caller&redundancy=active-active&secondary=backup.example:9000&interface=192.168.100.236&secondary_interface=192.168.50.80
srt://primary.example:9000?mode=caller&redundancy=active-backup&secondary=backup.example:9000&stability=60
OptionValues/meaning
modecaller or listener. The transport also recognizes the first letter; rendezvous exists for non-redundant use but is not offered by the current UI.
latencyMilliseconds. Active-backup enforces at least 200 ms.
password / passphraseSRT passphrase. password takes precedence.
userSRT username/stream identity field used by the transport.
interfacePrimary local interface address.
redundancyactive-active (aliases active_active, hitless, broadcast) or active-backup (aliases active_backup, backup).
secondaryhost:port. Caller redundancy requires a valid secondary. The alternate form is secondary_host plus optional secondary_port.
secondary_interfaceOptional local interface address for the secondary link.
stabilityActive-backup failover stability time in milliseconds, minimum 60.

Redundant rendezvous mode is rejected. Listener redundancy relies on the peer establishing the compatible two-link SRT group.

File

file:///G:/streams/golden.ts?loop=1&chunk=7
file:///G:/captures/output.ts?append=1&chunk=7
OptionMeaning
loop=1Loop a file input.
append=1Append to a file output.
chunk=NFile read/write TS packet grouping; the setup UI constrains N to 1..64.

WHIP/WebRTC output

whip://host/path?vbitrate=2500&abitrate=128&width=1280&height=720&fps=30

Optional output controls are signaling/media port, vbitrate and abitrate in kbps, output width/height, and fps.

TLS protocol names

rtmps, hlss, and whips are not currently advertised by the UI because their TLS/certificate paths are not ready. Do not use them as supported secure transports.

Client implementation notes

  • Poll /heartbeat separately from stream status. A live service can legitimately report every stream as Off or Illegal.
  • For the main/details UI, poll StatusAll. It is the authoritative combined source, destination, basic-analysis, and redundancy snapshot.
  • For events, begin with after=0, retain next_sequence, and send that value as the next after cursor.
  • Use TsAnalyzeStatus only for the currently selected full analyzer. Basic analysis for every active input is already present in StatusAll.
  • The monitor and analyzer source selections are independent. Changing either does not change the router's selected source/destination path.
  • Use value=0 to clear monitor/analyzer selection or a traditional destination route.
  • Inspect locked after route writes and status_msg when a status is Illegal.
  • Integer counters that can grow large are serialized as decimal strings. Parse them with a 64-bit integer type or JavaScript BigInt when exactness matters.
  • The REST callback returns compatibility fallbacks for unknown requests. Treat an unexpected schema as an unsupported command.