Skip to navigation

WebSocket clients

View as Markdown
Enterprise feature

This feature is available only for the Enterprise plan. To get started, reach out to support@buildwithfern.com.

Fern generates typed WebSocket clients from your AsyncAPI channel definitions. The generated clients handle connection management, typed send/receive messages, and automatic reconnection.

Fern generates WebSocket clients for TypeScript, Python, Java, C#, and Rust. Go generates types only, and Ruby isn’t yet supported.

Enable WebSocket client generation

Add the config flag to the relevant generator in your generators.yml:

groups:
ts-sdk:
generators:
- name: fernapi/fern-typescript-sdk
version: ...
config:
generateWebSocketClients: true

Java generates WebSocket clients by default with no additional configuration.

Generated SDK behavior

Given an AsyncAPI channel definition like:

asyncapi.yml
asyncapi: 3.0.0
info:
title: Plant Monitoring Service
version: 1.0.0
channels:
plantUpdates:
address: /plants/{plant_id}/updates
parameters:
plant_id:
description: Plant identifier
messages:
SensorReading:
$ref: '#/components/messages/SensorReading'
PlantStatus:
$ref: '#/components/messages/PlantStatus'
operations:
sendReading:
action: send
channel:
$ref: '#/channels/plantUpdates'
messages:
- $ref: '#/channels/plantUpdates/messages/SensorReading'
receivePlantStatus:
action: receive
channel:
$ref: '#/channels/plantUpdates'
messages:
- $ref: '#/channels/plantUpdates/messages/PlantStatus'
components:
messages:
SensorReading:
payload:
type: object
properties:
temperature:
type: number
humidity:
type: number
PlantStatus:
payload:
type: object
properties:
health:
type: string
needsWater:
type: boolean

Fern generates the following client code.

Send methods are named send + the operation name from the spec. The sendReading operation produces sendSendReading in TypeScript, Python, Java, and Rust. C# uses overloaded Send() methods instead.

Receive handling varies by language:

  • TypeScript — a generic socket.on("message", handler) callback
  • Python — typed responses from ws.recv()
  • Java — per-message-type handlers like onPlantStatus(handler)
  • C# — typed Event<T> properties like PlantStatus.Subscribe(handler)
  • Rust — a typed enum from ws.recv()

The TypeScript SDK generates a typed socket class with send methods, event handlers, and a ReconnectingWebSocket that automatically retries dropped connections.

const client = new PlantClient({ token: "..." });
const socket = await client.plantUpdates.createPlantUpdatesConnection({
plantId: "plant-123",
});
socket.on("open", () => {
console.log("Connected");
});
socket.on("message", (message) => {
// message is typed as PlantStatus
console.log(message.health);
});
socket.on("error", (error) => {
console.error(error);
});
socket.sendSendReading({ temperature: 22.5, humidity: 65 });
socket.close();

Authentication

In TypeScript, Python, Java, and Rust, WebSocket clients automatically inherit the authentication configured on the root client. Headers — including bearer tokens, API keys, and custom headers — are sent with the WebSocket handshake request.

const client = new PlantClient({
token: "your-bearer-token",
});
// Auth headers are forwarded to the WebSocket handshake
const socket = await client.plantUpdates.createPlantUpdatesConnection({
plantId: "plant-123",
});

In C#, the WebSocket client is constructed with an Options object that includes the connection URL and channel parameters. Configure authentication through the HttpInvoker option or by setting headers on the underlying client.

Defining WebSocket channels

WebSocket clients are generated from channel definitions in your AsyncAPI specification. For defining channels, messages, and operations, see Publish/subscribe operations.