Skip to content

REST and WebSocket API

Everything the CONNECT panel does, it does through a documented HTTP and WebSocket surface on port 5100. Your own tools can use the same surface: read signals, write signals, create interfaces, run discovery.

Every request follows the access rule: local callers pass, remote callers present X-API-Key.

ws://<host>:5100/ws wss:// behind a TLS reverse proxy

This is the live channel — the same one the browser HMI uses. It speaks the rv WebSocket Realtime v2 protocol, JSON over WebSocket, which is also spoken by realvirtual Core and the ctrlX bridge.

On connect the client receives a complete baseline before anything else:

  1. import_answer — all signal types and their current values, so the client can register every signal correctly without waiting.
  2. data — a full snapshot of current values.
  3. From then on: data messages carrying only what changed, on a fixed 10 ms tick.

The baseline is always sent before the client joins the broadcast, so a delta can never overtake it.

Gateway to client

TypePayload
import_answerSignal types and current values
dataSignal values — full snapshot on connect, deltas afterwards
config_answerThe configuration, in response to config_get
discover_answerDiscovery results for one interface

Client to gateway

TypeEffect
dataValues are written into the gateway — this is how a client commands the machine
import_requestRequests a fresh import_answer
config_getRequests the configuration
subscribeSignal subscription hint

A value message looks like this:

{
"type": "data",
"version": 2,
"signals": { "Conveyor1Running": true, "Actual_Temp": 234, "Motor1_Speed": 1.45 }
}
  • Only the latest value per signal per tick is sent; a value that changes and reverts within one tick collapses to its current value, which is correct for an HMI.
  • The gateway sends nothing while nothing changes — an idle connection costs nothing.
  • A heartbeat runs every 30 seconds; clients idle for 90 seconds are closed.
  • A configuration change resends a full snapshot, so no client is left with a stale set.

Authentication for a WebSocket upgrade uses ?apikey=<key>, because a browser cannot set headers on a handshake.

Method and pathPurpose
GET /healthLiveness, version, build and capability flags — answers without authentication
GET /health/detailSignal and client counts, license state
GET /signalsAll signals with types, count and version
GET /configThe complete configuration
PUT /configReplace the complete configuration
GET /config/interfacesList interfaces
POST /config/interfacesCreate an interface
PUT /config/interfaces/{id}Replace an interface — also used for tag-table re-import
DELETE /config/interfaces/{id}Remove an interface
POST /signals/validateValidate a protocol address without saving anything
POST /discover/{id}/startRun discovery on a live interface
POST /discover/{id}/bindRegister and persist selected discovered signals
GET /interface-typesAvailable interface types and what each one supports

Additional endpoints exist for the optional services: /history/* for recorded data, /cad/step-to-glb and /cad/jt-to-glb for CAD conversion, /diagnose and /comments for AI diagnosis, and /update/* for updates.

Configuration writes are persisted atomically and applied by hot-reload: affected interfaces restart, the gateway does not.

Terminal window
# Is the gateway up?
curl http://localhost:5100/health
# All current signals
curl -H "X-API-Key: $KEY" http://localhost:5100/signals
# Validate an address before creating a signal
curl -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"interfaceType":"S7","protocolAddress":"DB1.DBX0.0","dataType":"Bool"}' \
http://localhost:5100/signals/validate
Wire typeDirection
PLCInputBool, PLCInputInt, PLCInputFloatWritten by realvirtual, read by the PLC
PLCOutputBool, PLCOutputInt, PLCOutputFloatWritten by the PLC, read by realvirtual

See configuring interfaces for what that means in practice.