ApiGear NATS Subject Mapping
This is the wire specification for running ObjectAPI interfaces over NATS. It defines how an interface's members map to NATS subjects and payloads. The mapping is transport-level and language-independent — a service generated by any template interoperates with a client generated by any other.
Subject structure
NATS subjects use . as the separator. They are built from the module name, interface name, a verb, and
the member name:
{moduleName}.{interfaceName}.{verb}.{memberName}
| Verb | Member | Direction | Purpose |
|---|---|---|---|
rpc | operation | client → service | Invoke an operation (request/reply) |
sig | signal | service → client | Signal broadcast |
set | property | client → service | Property change request |
prop | property | service → client | Property value notification |
The property verbs match the MQTT mapping: set carries a change request to
the service, and prop carries the value notification back to clients.
Operations (request / reply)
Operations use NATS's native request/reply. The client publishes a request; the service subscribes and replies on the request's reply subject:
Subject: {moduleName}.{interfaceName}.rpc.{functionName}
Content: JSON array of the operation arguments (string-encoded)
Internal (non-API) operations
Operations not declared in the API use the rpc verb with an underscore prefix on the function name:
{moduleName}.{interfaceName}.rpc._{functionName}
Signals
The service publishes; clients subscribe:
Subject: {moduleName}.{interfaceName}.sig.{signalName}
Content: JSON array of the signal arguments (string-encoded)
Properties
Change request — the client publishes a desired value; the service subscribes:
Subject: {moduleName}.{interfaceName}.set.{propertyName}
Content: JSON-encoded property value (string)
Value notification — the service publishes the current value; clients subscribe:
Subject: {moduleName}.{interfaceName}.prop.{propertyName}
Content: JSON-encoded property value (string)
Connectivity messaging
NATS has no broker-side retained state, so ApiGear adds explicit messages for service discovery and initial state synchronisation:
| Message | Subject | Content | Direction |
|---|---|---|---|
| Service available | {moduleName}.{interfaceName}.service.available | empty | service → client |
| Init request | {moduleName}.{interfaceName}.init | clientId | client → service |
| Init response | {moduleName}.{interfaceName}.init.resp.{clientId} | initial state (JSON object) | service → client |
A client subscribes to service.available, then sends an init request carrying its clientId; the service
replies on init.resp.{clientId} with the current property values so the client starts in sync.
Payloads
Payloads are string-encoded JSON (nlohmann::json). Operation and signal arguments are JSON arrays;
property values and init responses are JSON elements/objects.
Implemented by
Related: ApiGear over MQTT · ObjectLink · Protocol Mappings