Status: Draft. This page records the proposed field names and transport format for a future real-time feed from IPSC3 networks to RadioID.net. It is a planning specification and is not currently a live public IPSC3 service.
Every participating IPSC3 server will publish call and peer events to the IPSC3 master API host. RadioID.net will then use one connection to receive the combined feed for all registered IPSC3 servers.
IPSC3 servers
-> authenticated WebSocket publishers
-> api.ipsc3.net aggregation service
-> RadioID.net Socket.IO connection
Calls must be reported once for the originating or ingress session. IPSC3 must not publish a separate session event for every repeater, hotspot, POC client, or trunk in a talkgroup fanout.
The consumer-facing interface retains the BrandMeister Last Heard Socket.IO shape. The exact connection parameters are:
| Setting | Required value |
|---|---|
| Socket.IO URL | https://api.ipsc3.net |
| Socket.IO path | /lh/socket.io |
| Underlying WebSocket URL | wss://api.ipsc3.net/lh/socket.io/?EIO=4&transport=websocket; the Socket.IO client constructs this URL. |
| Socket.IO / Engine.IO version | Socket.IO 4.x using Engine.IO 4. |
| Namespace | Default namespace /. No custom namespace is used. |
| Transport | WebSocket only. Long polling is not required. |
| Consumer authentication | None initially, matching the BrandMeister feed. The optional Socket.IO auth.resume_event_id value is a replay cursor, not a credential. |
| TLS | TLS 1.2 or newer is required; TLS 1.3 is preferred. The client must verify the public certificate and hostname. Plain ws:// is not supported. |
| Subscription event | After every connection, emit join with the exact string everything. |
| Data event | The server emits mqtt. |
| Status event | The server may emit feed_status with live, replay_started, replay_complete, or replay_unavailable. |
const socket = io("https://api.ipsc3.net", {
path: "/lh/socket.io",
transports: ["websocket"],
auth: {
resume_event_id: lastProcessedEventID || null
}
});
socket.on("connect", () => {
socket.emit("join", "everything");
});
socket.on("mqtt", envelope => {
const event = JSON.parse(envelope.payload);
});
Call events use the outer topic LH. The outer
payload value is a JSON-encoded string and must be decoded a
second time.
{
"topic": "LH",
"payload": "{\"Event\":\"Session-Stop\", ...}"
}IPSC3-server-to-API publishing will use normal JSON over an authenticated TLS WebSocket connection with a separate per-server credential. That publisher interface is not the public Socket.IO consumer connection. JSON is encoded as a string only by the RadioID.net compatibility adapter at the final consumer boundary.
EventID and supply it as auth.resume_event_id on its next connection.Replay to true.EventID, NetworkSessionID, Start, and Stop. It is not a new event.feed_status with replay_unavailable and then continues live.EventID before committing an event.| Field | Type and permitted value | IPSC3 meaning |
|---|---|---|
Event | JSON string enum: Session-Start or Session-Stop | Call lifecycle event. Session-Stop is the authoritative completed-call event. |
SessionType | JSON integer, unsigned 8-bit: 0..255; initially 7 | BrandMeister-compatible session classification for the initially supported voice case. Additional numeric values must be agreed with RadioID.net before private or data sessions use them. |
LinkName | JSON string, maximum 64 UTF-8 bytes | Ingress repeater or hotspot callsign, configured trunk name, or POC callsign. |
LinkTypeName | JSON string enum: Repeater, Hotspot, Trunk, or POC | Type of endpoint through which the call entered IPSC3. |
Slot | JSON integer, unsigned 8-bit: 1 or 2 | Effective IPSC3 DMR timeslot. |
ContextID | JSON integer, unsigned 32-bit: 0..4294967295 | Original DMR stream or context ID observed at ingress. |
SourceID | JSON integer, unsigned 32-bit; valid DMR IDs are normally 1..16777215 | Calling radio ID. RadioID.net resolves the callsign and name from this field. |
DestinationID | JSON integer, unsigned 32-bit; valid DMR destinations are normally 1..16777215 | Talkgroup number or private destination radio ID. |
DestinationName | JSON string, maximum 128 UTF-8 bytes; blank permitted | Configured IPSC3 talkgroup name. It may be blank for private calls. |
Start | JSON integer, unsigned 64-bit UTC Unix timestamp in seconds | Seconds since 1970-01-01T00:00:00Z when the accepted session began. No local timezone conversion is applied. |
Stop | JSON integer, unsigned 64-bit UTC Unix timestamp in seconds | Seconds since 1970-01-01T00:00:00Z when the session ended. Use 0 only in a Session-Start event. |
RSSI | JSON integer, signed 16-bit dBm: -200..0 | Measured ingress RSSI. Use 0 when unavailable and set RSSIValid to false. |
Master | JSON string, 1 to 64 ASCII characters | Configured identity of the reporting IPSC3 server, normally equal to ServerID, such as ipsc3-vkdmr. |
SourceCall and SourceName are deliberately not sent.
SourceID is authoritative and RadioID.net performs its own current
callsign and name lookup.
| Field | Type and permitted value | Purpose |
|---|---|---|
SchemaVersion | JSON integer, unsigned 16-bit: 1..65535; initially 1 | Version of the IPSC3 event schema. |
EventID | JSON ASCII string, 1 to 128 characters | Globally unique event identifier in the form ServerID:UUIDv7. It is generated once and retained during replay. |
ServerID | JSON ASCII string, 1 to 64 characters | Stable IPSC3 server identifier, such as ipsc3-vkdmr. |
Protocol | JSON string enum: IPSC, MMDVM, OpenBridge, Hytera, YSF, BMasterPlus, or POC | Protocol through which the session entered IPSC3. |
CallType | JSON string enum: GroupVoice, PrivateVoice, GroupData, or PrivateData | Explicit IPSC3 session classification. |
PeerID | JSON integer, unsigned 32-bit, or null | Configured DMR identity of the ingress repeater or base owner ID of an MMDVM hotspot. It is never IPSC3's internal database row ID. POC and trunk ingress use null. |
DurationMs | JSON integer, unsigned 64-bit | Call duration in milliseconds. |
PacketCount | JSON integer, unsigned 64-bit | Number of accepted packets in the ingress session. |
RxBytes | JSON integer, unsigned 64-bit, or omitted | Number of ingress bytes recorded for the session. |
TxBytes | JSON integer, unsigned 64-bit, or omitted | Number of transmitted bytes associated with the session. |
BER | JSON finite number from 0.0 to 100.0, or null | Ingress bit error rate percentage when available. |
RSSIValid | JSON Boolean | Distinguishes a measured RSSI from the compatibility value 0. |
EndReason | JSON string enum: terminator, timeout, disconnect, replaced, error, or unknown | Reason IPSC3 closed the session. |
OriginServerID | JSON ASCII string, 1 to 64 characters, or null | IPSC3 server that created NetworkSessionID. It remains unchanged as the call crosses IPSC3-aware links. |
NetworkSessionID | JSON ASCII string containing a canonical 36-character UUIDv7 | Identifies the same network call when it is observed across multiple IPSC3 servers. |
Replay | JSON Boolean; defaults to false | Indicates an event replayed after a connection interruption. |
PeerID identifies a real DMR RF endpoint where one exists. It
must not expose the reporting server's internal peers.id database
value. The rules are applied after classifying the ingress endpoint:
| Ingress | PeerID rule | Example |
|---|---|---|
| IPSC, Hytera, or provisioned MMDVM repeater | Configured repeater DMR ID. | VK2RCG uses 505201. |
| MMDVM hotspot | Base owner DMR ID after removing the configured MMDVM ESSID suffix. | Hotspot login 505254011 / VK2FLY-11 publishes 5052540. |
| POC client | null. SourceID identifies the transmitting user. | A POC transmission by VK2FLY publishes SourceID: 5052540 and PeerID: null. |
| DMR or non-DMR trunk | null. A trunk's configured network, system, or gateway ID is not an RF endpoint identity. | OZ-FREEDMR or a YSF reflector publishes PeerID: null and is identified by LinkName and Protocol. |
{
"SourceID": 5052562,
"PeerID": 505201,
"LinkName": "VK2RCG",
"LinkTypeName": "Repeater",
"Protocol": "IPSC"
}{
"SourceID": 5052562,
"PeerID": 5052540,
"LinkName": "VK2FLY-11",
"LinkTypeName": "Hotspot",
"Protocol": "MMDVM"
}{
"SourceID": 5052540,
"PeerID": null,
"LinkName": "VK2FLY",
"LinkTypeName": "POC",
"Protocol": "POC"
}{
"SourceID": 5053590,
"PeerID": null,
"LinkName": "OZ-FREEDMR",
"LinkTypeName": "Trunk",
"Protocol": "OpenBridge"
}Start and Stop are always UTC Unix timestamps in whole seconds. Unix timestamps are timezone-independent and no Australian or server-local offset is applied.EventID when it is first created. A replayed copy retains exactly the same EventID.Session-Start and Session-Stop are separate events and therefore have different EventID values, while sharing one NetworkSessionID.NetworkSessionID and sets itself as OriginServerID.NetworkSessionID.NetworkSessionID and OriginServerID, keyed to the transported stream. The receiving IPSC3 server adopts both values rather than creating replacements.ServerID as OriginServerID. The aggregator must not heuristically merge such calls, because matching only source, destination, stream ID, and time can join unrelated sessions.| Topic | Event values | Purpose |
|---|---|---|
LH | Session-Start, Session-Stop | Individual call lifecycle events. |
PEER | Peer-Connected, Peer-Disconnected, Peer-Status | Repeater, hotspot, trunk, and POC connection state. |
TG | Talkgroup-Activity | Aggregate active or idle talkgroup state changes rather than packet-level updates. |
SYSTEM | Server-Connected, Server-Disconnected, Server-Status | IPSC3 server and feed status. |
POC connections use the normal peer events with
LinkTypeName: "POC". A separate incompatible POC event structure
is not required.
This is the consumer-facing Socket.IO mqtt object. The
payload member is intentionally a JSON-encoded string.
{
"topic": "LH",
"payload": "{\"Event\":\"Session-Stop\",\"SessionType\":7,\"LinkName\":\"VK2RCG\",\"LinkTypeName\":\"Repeater\",\"Slot\":1,\"ContextID\":123456,\"SourceID\":5052562,\"DestinationID\":505,\"DestinationName\":\"Australia\",\"Start\":1786850000,\"Stop\":1786850010,\"RSSI\":-90,\"Master\":\"ipsc3-vkdmr\",\"SchemaVersion\":1,\"EventID\":\"ipsc3-vkdmr:01915f2a-7b1c-7a21-8d7e-6f9a2c450001\",\"ServerID\":\"ipsc3-vkdmr\",\"Protocol\":\"IPSC\",\"CallType\":\"GroupVoice\",\"PeerID\":505201,\"DurationMs\":10000,\"PacketCount\":167,\"RxBytes\":8851,\"TxBytes\":0,\"BER\":0.3,\"RSSIValid\":true,\"EndReason\":\"terminator\",\"OriginServerID\":\"ipsc3-vkdmr\",\"NetworkSessionID\":\"01915f2a-6a09-7df1-9d63-cbe3d4630012\",\"Replay\":false}"
}