The data modality ships as a subpath of the ClutchCall SDK. Import the Data client. Bind a clientId. Then publish and subscribe against hierarchical topics. One Data instance reuses a single MoQT session across every publish and subscribe.

Import

Other languages expose the same surface under the equivalent subpath (github.com/clutchcall/clutchcall-sdk/go, clutchcall, com.clutchcall:clutchcall-sdk, ClutchCall.SDK). The method names and wire format are identical.

Data

The client. Construct one per process or device.

Constructor options

string
required
Bearer token for the relay session. It carries the tenant and the clientId claims. The same token authorizes every other modality.
string
required
This client’s stable id. The SDK attaches it as fromClientId on every published message. Subscribers use it to attribute the source.
string
Relay hostname. Defaults to the platform relay.
(state, reason?) => void
Optional connection-state callback. It fires as the underlying QUIC/MoQT session moves through Connecting → Connected → Reconnecting → Closed / Failed. The session reconnects automatically and replays subscriptions.
WebTransportFactory
Inject a custom WebTransport factory: a Node polyfill or a test double. This is optional. The browser SDK uses the native implementation.

Methods

publish(args)

Publish one message. The SDK adds the (fromClientId, topic) header and selects the MoQT track from the topic’s top-level segment.
string
required
Full hierarchical topic, e.g. sensors/room1/temperature. UTF-8, ≤ 255 bytes.
Uint8Array | bytes
required
Opaque payload bytes. Encode JSON / text / protobuf yourself.
boolean
default:"false"
false → lossy QUIC datagram lane (lowest latency). true → ordered, retried subgroup-stream lane (guaranteed in-order per publisher).
boolean
default:"false"
true → the relay caches the latest payload on this topic and delivers it to every late-joining subscriber on attach. To clear it, publish a zero-length payload with retained: true.
Returns a Promise<void> (TS) / None (Python). The promise resolves when the SDK hands the frame to the transport.
The top-level segment must be concrete. publish({ topic: "sensors/..." }) is valid. A topic that begins with + or # throws. The first segment selects the track.

subscribe(args, onMessage)

Subscribe with an MQTT-style filter. The callback fires for every matching message. The SDK opens one MoQT subscription on the filter’s top-level segment and filters the rest of the path client-side.
string
required
MQTT-style filter. + matches one segment. # matches the rest (trailing only). The top-level segment must be concrete.
(msg: DataMessage) => void
required
The SDK invokes it for every message whose topic matches the filter. The SDK silently drops malformed frames before the callback.
Returns a DataSubscription (TS: Promise<DataSubscription>). Call .close() to stop receiving.

close()

Stop every publication and subscription. Close the MoQT session. The method is idempotent.

Handles and types

DataMessage

What onMessage receives.
string
The full topic string that the publisher sent (not the filter).
string
The clientId of the publisher. Use it for attribution and per-client demux.
Uint8Array | bytes
The opaque message bytes.
boolean
true when this is a retained/bootstrap value that the relay re-emitted on attach. false for live traffic. The flag lets you treat a snapshot differently from updates.

DataSubscription

The handle that subscribe returns. It carries topicFilter and exposes:

Connection state and events

The data client does not raise per-message events beyond your onMessage callback. The optional onState constructor callback shows the lifecycle. It mirrors the underlying session:
On reconnect, the SDK replays your subscriptions automatically. The relay re-emits matching retained values. A transient drop thus restores current state without app code.

Wire helpers (advanced)

The subpath also exports the raw codec and matcher. Use them for interop tests, or for callers that must stay wire-compatible without the high-level client:
Both from_client_id and topic are bounded at 255 bytes. topLevelSegment throws on a leading wildcard. These helpers mirror the frame layout in Details.

Dropping to the substrate

The data modality is a thin convention over MoQT frames. If you need a shape that it does not cover, import @clutchcall/sdk/moqt. Use MoqtClient.publishFrame / subscribeFrame directly under your own namespace. The same auto-reconnect, capability routing, and relay fan-out apply. See Realtime Tracks.