Skip to content
Export

Control API

Purpose

pkg/controlapi exposes a localhost JSON and WebSocket API so applications in any language can use Reticulum destinations, announces, links, and requests without embedding the Go transport stack.

The server is optional and disabled by default.

Enable in config

[reticulum]
enable_control_api = yes
rpc_key = <64 hex characters>
control_api_host = 127.0.0.1
control_api_port = 37430

rpc_key is a 32-byte value encoded as hex. The same key authenticates shared-instance RPC when configured.

Generate a key with a cryptographic random source. Example using OpenSSL:

openssl rand -hex 32

Authentication

All /v1 routes require:

Authorization: Bearer <hex rpc_key>

Requests without a valid bearer token are rejected.

HTTP routes

Method Path Description
GET /v1/health Liveness probe (process up, transport id, uptime). Not mesh integrity scoring
GET /v1/status Interface statistics, including Go local integrity counters when present
GET /v1/paths Path table snapshot
POST /v1/sessions Create session (identity)
DELETE /v1/sessions/{id} Tear down session
POST /v1/sessions/{id}/destinations Register destination
POST /v1/sessions/{id}/destinations/{hash}/announce Send announce
POST /v1/sessions/{id}/destinations/{hash}/requests Bridge request path to WebSocket
POST /v1/sessions/{id}/path/request Request path to destination
GET /v1/sessions/{id}/events WebSocket event stream

Lifecycle routes (Go node integration):

Method Path Description
POST /v1/lifecycle/resume Resume after pause
POST /v1/lifecycle/pause Pause interfaces
POST /v1/lifecycle/refresh-paths Refresh stale paths

Binary fields (hashes, app data, link payloads) are hex- or base64-encoded as documented in pkg/controlapi/protocol.go.

Status integrity fields (Go daemon)

GET /v1/status mirrors shared-instance interface stats. Against a Reticulum-Go daemon each interface object may include:

JSON field Meaning
ifac_fail IFAC verify failures
hmac_fail Link HMAC failures
announce_sig_fail Invalid announce signatures
unpack_fail Packet unpack failures
integrity_fail_rate Windowed fails / (fails + accepted)
stale_closes Links closed after going stale
link_stale_close Same lifetime total as exposed on the iface
keepalive_timeout Transitions into keepalive stale

These counters are local observability only. They do not change packet accept or reject policy. For scored findings use reticulum-go slow. See Security and CLI utilities.

Sessions

A session owns:

  • One identity
  • Destinations registered under that identity
  • Links opened or accepted by the session

Typical flow:

POST /v1/sessions
  -> session id

POST /v1/sessions/{id}/destinations
  -> register app destination

POST /v1/sessions/{id}/destinations/{hash}/announce
  -> publish announce

GET /v1/sessions/{id}/events (WebSocket)
  -> subscribe to announces, links, requests

WebSocket events

Server to client JSON events include:

Event Meaning
announceEvent Remote announce received
linkEstablishedEvent Link is active
linkFailedEvent Outbound link failed
linkDataEvent Data received on link
linkClosedEvent Link closed
requestIncomingEvent Request arrived on registered path

Client to server commands include:

Command Meaning
subscribeAnnouncesCommand Filter announces
linkOpenCommand Open outbound link
linkSendCommand Send on link
linkCloseCommand Close link
requestRespondCommand Answer a request

Full type definitions: pkg/controlapi/protocol.go.

Links via API

Register a destination with link acceptance enabled for inbound links.

Outbound: send linkOpenCommand over the events WebSocket after the path exists (from announce or path request).

Both directions receive linkEstablishedEvent when ready, then linkDataEvent for peer data.

Requests via API

Register a request path with POST .../destinations/{hash}/requests. Incoming requests appear as requestIncomingEvent. Respond with requestRespondCommand before the handler timeout.

Handlers block the underlying link goroutine until response or timeout. Keep processing short.

Example client

examples/control-client/client.py is a Python reference client for the API.

Security notes

  • Default bind is loopback only
  • Do not expose the control API to untrusted networks without additional protection
  • Treat rpc_key as a secret comparable to an API token
  • See Security

Implementation files

File Role
server.go HTTP server and routing
session.go Session state
protocol.go Request and event types
ws.go WebSocket handling
auth.go Bearer validation
lifecycle.go Lifecycle routes

Daemon wiring: cmd/reticulum-go/main.go starts controlapi.Server when enabled.

Related documents

Dart and Flutter

Path: bindings/dart/ (package rns_control).

Control API client

HTTP and WebSocket client for a local or LAN reticulum-go daemon. Import package:rns_control/rns_control.dart.

import 'package:rns_control/rns_control.dart';

final client = ControlClient(rpcKey: rpcKey);
final session = await client.createSession();
final events = client.openEvents(session.sessionId);
events.subscribeAnnounces();

Coverage includes health, status, paths, sessions, destinations, announce, request handlers, lifecycle, and WebSocket commands or events. Authenticated WebSocket upgrades require dart:io (Flutter mobile or desktop). Browser clients cannot set the Authorization header on WebSocket.

In-process FFI

For embedding without a daemon, use package:rns_control/ffi.dart over librns on Linux, Android, and Windows. See librns Dart FFI.

task build-librns
task test-dart
# or
make -C bindings/dart test

Add to a Flutter app with a path dependency:

dependencies:
  rns_control:
    path: ../Reticulum-Go/bindings/dart
R
Reticulum-Go

A Go implementation of the Reticulum Network Stack. Building the future of resilient, sovereign communications.

Implementation License: Apache-2.0

Follow Development

Links

Quad4 Software

Backed by Quad4 Software. Building privacy-first, secure, efficient software.

quad4.io
© 2026 Quad4 Software. All rights reserved.
Deployed using Coolify