ApiGear MQTT Topic Mapping
This is the wire specification for running ObjectAPI interfaces over MQTT v5. It defines how an interface's members map to MQTT topics and payloads. The mapping is transport-level and language-independent — a service generated by any template interoperates with a client generated by any other.
Formal document: ApiGear MQTT Spec v0.1 (PDF).
Topic structure
All topics are built from the module name, interface name, a verb, and the member name, separated by /:
{moduleName}/{interfaceName}/{verb}/{memberName}
| Verb | Member | Direction | Purpose |
|---|---|---|---|
rpc | operation | client → service | Invoke an operation (request) |
sig | signal | service → client | Signal broadcast |
prop | property | service → client | Property value notification (retained) |
set | property | client → service | Property change request |
Using an interface Hello in module io.world as an example:
| Direction | Topic | Purpose |
|---|---|---|
| Client → Service | io.world/Hello/set/last | Set property request |
| Service → Client | io.world/Hello/prop/last | Property change notification (retained) |
| Client → Service | io.world/Hello/rpc/say | Operation invocation |
| Service → Client | io.world/Hello/rpc/say/{clientId}/result | Operation reply (per-client) |
| Service → Client | io.world/Hello/sig/justSaid | Signal broadcast |
Operations (request / response)
Operations use a request topic and a per-client response topic.
Request — the client publishes; the service subscribes:
Topic: {moduleName}/{interfaceName}/rpc/{functionName}
Content: JSON array of the operation arguments, e.g. [42]
MQTT v5: CorrelationData = unique call id (UUID); ResponseTopic = the reply topic below
Response — the service publishes to the caller's ResponseTopic; that client subscribes:
Topic: {moduleName}/{interfaceName}/rpc/{functionName}/{UniqueClientID}/result
Content: JSON-encoded return value
MQTT v5: CorrelationData = the same call id, echoed back unchanged
The CorrelationData property carries the unique call id as opaque bytes, which the service echoes back on
the reply. This lets multiple clients invoke the same operation concurrently without their replies colliding —
each client matches the echoed id to the call it made.
Internal (non-API) operations
Operations not declared in the API (template-internal helpers) use the same rpc verb with an underscore
prefix on the function name, so they never clash with generated operations:
{moduleName}/{interfaceName}/rpc/_{functionName}
Signals
The service publishes; clients subscribe:
Topic: {moduleName}/{interfaceName}/sig/{signalName}
Content: JSON array of the signal arguments
Properties
Property handling is split into a change request and a value notification:
Set (change request) — the client publishes a desired value; the service subscribes:
Topic: {moduleName}/{interfaceName}/set/{propertyName}
Content: JSON-encoded property value
Notify (value) — the service publishes the current value; clients subscribe:
Topic: {moduleName}/{interfaceName}/prop/{propertyName}
Content: JSON-encoded property value
Property value notifications are published with retain = true. A newly-subscribing client therefore receives the current value immediately on subscription — no separate handshake is needed.
Payloads & QoS
- Payloads are JSON-encoded. Operation requests carry an args-only array (e.g.
[42]); the call id rides on the MQTT v5CorrelationDataproperty rather than inside the payload. - Property values and signal argument arrays are plain JSON.
- Subscribe/publish use QoS 1 (at-least-once delivery) by default.
MQTT v3.1.1 fallback
MQTT 3.1.1 has no user properties, so the v3 mapping moves the version into the topic and embeds the correlation data and response topic inside the payload:
Request: {moduleName}/{interfaceName}/rpc/v3/{functionName}
Content: Data { correlationData (call id) + ResponseTopic }
Response: {moduleName}/{interfaceName}/rpc/v3/{functionName}/{UniqueClientID}/result
Content: Data { correlationData (call id) }
Prefer MQTT v5 where the broker supports it; it keeps payloads clean and uses native correlation.
Implemented by
Related: ApiGear over NATS · ObjectLink · Protocol Mappings