The games modality lives in its own subpath. Import the Games client plus its publisher/subscription handles from there.
The TypeScript and Python surfaces mirror each other method-for-method. They differ only in idiomatic case (publishStatepublish_state) and in keyword vs options style. Both use the same MoQT substrate, so a TS player and a Python authority interoperate on the wire.

Games — the client

Use one Games instance per (room, player), or per (room, server) for the authority. The client opens the session lazily on the first publish or subscribe. It reuses the session for every channel.
string
required
Bearer token for the relay session, scoped to (tenant, room, player?).
string
required
The room that every channel binds to. All three channels live under game/<roomId>/….
string
Player identity. Omit it for the authoritative server. It is required for publishInput and publishEvent. It becomes the from header on every frame.
string
Relay hostname. Defaults to the platform relay.
(state, reason?) => void
Connection-state callback. state is a ConnectionState (0 Connecting · 1 Connected · 2 Reconnecting · 3 Closed · 4 Failed).
WebTransportFactory
Inject a custom WebTransport factory (for a Node polyfill or tests). Optional.
The constructor throws (Error / GamesError) if token or roomId/room_id is missing.

Namespace accessors

Use these read-only helpers to inspect the raw tracks or to interoperate with them:

state — server → all

publishState(args?) → StatePublisher

Authority-only. Opens the state track and returns a StatePublisher. State frames carry no from header, because the source is always the authority. They use the datagram lane at priority 100.
number
Tick-rate hint for the relay’s admission control and the recorder. It does not pace your writes. You drive the loop. Optional.

subscribeState(cb) → GamesSubscription

Player-side. Subscribes to the authority’s state. It calls your callback with each snapshot’s raw bytes. Returns a GamesSubscription that you can close().

StatePublisher

void
Publish one state snapshot. priority defaults to 100. The SDK stamps timestamps from a monotonic clock.
void
Close the state track.

input — each player → server

publishInput() → FromPublisher

Player-only. Returns a FromPublisher that prefixes every frame with this client’s playerId. Input uses the datagram lane at priority 100. The call throws if the client has no playerId.

subscribeInputs(cb) → GamesSubscription

Authority-side. Receives every player’s input on one callback. The SDK decodes the from header, so you get (playerId, bytes) for each frame. You do not manage a subscription for each player.
The SDK silently drops malformed input frames (bad from header). It does not throw into your callback, so one bad packet cannot stall the tick loop. The relay logs the dropped frames as wire-format rejects.

event — any → any (reliable)

publishEvent(args) → FromPublisher

Either role. Opens a reliable, ordered event channel and returns a FromPublisher. Events use a subgroup stream at priority 50. Delivery is guaranteed and in order. The SDK stamps the server’s events with from = "_authority". A player’s events carry the player’s id.
string
required
Event channel name, for example chat, ready, or rpc.use_item. Each channel is its own track under game/<room>/event/<channel>.

subscribeEvents(args, cb) → GamesSubscription

Either role. Subscribes to one event channel. The callback gets the decoded sender id and the raw event bytes.

FromPublisher

Both publishInput and publishEvent return this handle. It prefixes every write with the caller’s from id.
void
Publish one frame. priority defaults to the channel default (100 for input, 50 for events). The SDK adds the from header for you.
void
Close the underlying track.

Handles & lifecycle

GamesSubscription

Every subscribe* method returns this handle. It has read-only ns / name plus:
void
Stop receiving on this channel.

Games.close()

Closes the single underlying session. This closes every publisher and subscription on the session. After close(), the next publish or subscribe opens a fresh session.

Connection events

There is no separate event emitter. The onState / on_state callback that you pass to the constructor delivers the connection lifecycle. The underlying session auto-reconnects with capped backoff. It replays every publish and subscribe on reconnect, so your channels reattach without code on your side.

Wire helpers (advanced)

The SDK exports the from-header codec. Use it for interop tests, or for callers that bypass the high-level client but stay wire-compatible:

Other languages

The Go and Rust SDKs expose the same (room, player) model and the same three channels over the shared MoqtClient. Method names use each language’s idiomatic case. Package coordinates: github.com/clutchcall/clutchcall-sdk/go, clutchcall. Unity games use the Netcode transport drop-in. They do not call this client directly.