You can connect to the websocket from your client side frontend code running in the iFrame.

  1. Create the websocket client:

    import { WhopClientSdk } from "@whop/api";
    
    const whopApi = WhopClientSdk();
    
    const websocket = whopApi.websocketClient({
      joinExperience: "exp_XXXX", // optional, you can join a specific experience channel (ie, the one you are currently viewing).
      joinCustom: "some_custom_channel", // optional, you can join a custom channel.
    });
  2. Add event handlers for messages:

    websocket.on("appMessage", (message) => {
      console.log("Received custom message:", message);
    
      // message.isTrusted is true if and only if the message was sent from your server with your private app API key.
    
      // message.json is the JSON string you sent from your server / client.
    
      // if you sent the message from the client using websocket.broadcast,
      // message.fromUserId will include the user id of the user who sent the message.
    });
  3. Handle connection status changes:

    websocket.on("connectionStatus", (status) => {
      console.log("Websocket Status Updated:", status);
    });
    
    websocket.on("connect", () => {
      console.log("Websocket Connected");
    });
    
    websocket.on("disconnect", () => {
      console.log("Websocket Disconnected");
    });
  4. Connect to the websocket and start receiving events:

    websocket.connect();
  5. Optional: Disconnect from the websocket:

    websocket.disconnect();

Send messages from the client

You can send messages from the client to the server by using the websocket.broadcast function.

  1. Create a websocket client as above, and make sure you are connected by calling websocket.connect().

  2. Send a custom message via websocket.

    websocket.broadcast({
      message: JSON.stringify({ hello: "world" }),
      target: "everyone",
    });

    The target field is the same as the one you would pass to whopApi.sendWebsocketMessage on the server.

Send messages from your server

You can broadcast trusted websocket messages from your server to connected clients by using the whopApi.sendWebsocketMessage function.

  1. Construct an instance of the whop server sdk and pass your API key:

    import { WhopServerSdk } from "@whop/api";
    
    const whopApi = WhopServerSdk({
      appApiKey: process.env.WHOP_API_KEY,
    });
  2. Send a custom string message via websocket.

    // Send to all users currently on your app across all experiences / views.
    whopApi.sendWebsocketMessage({
      message: JSON.stringify({ hello: "world" }),
      target: "everyone",
    });
    
    // send to all users currently on this experience
    // (only works if the experience belongs to your app)
    whopApi.sendWebsocketMessage({
      message: JSON.stringify({ hello: "world" }),
      target: { experience: "exp_XXXX" },
    });
    
    // create a custom channel that your websocket client can subscribe to.
    // Only works if when connecting on the client, you pass the same custom channel name.
    whopApi.sendWebsocketMessage({
      message: JSON.stringify({ hello: "world" }),
      target: { custom: "some_custom_channel" },
    });
    
    // send to a specific user on your app
    whopApi.sendWebsocketMessage({
      message: JSON.stringify({ hello: "world" }),
      target: { user: "user_XXXX" },
    });

Receive messages on your server

Before you start, make sure you are using NodeJS 22.4 or higher, or Bun to run your server.

Use the server websocket API to receive events such as chat messages as forum posts for a particular user on your server. You can use these events to build real-time apps such as chat bots and AI-agents that react to events on the platform.

  1. Construct (or reuse) an instance of the whop server sdk and pass your API key:

    import { WhopServerSdk } from "@whop/api";
    
    const whopApi = WhopServerSdk({
      appApiKey: process.env.WHOP_API_KEY,
    });
  2. Create your websocket client and add handlers for messages / status changes:

    const websocket = whopApi
      // Pass the user id of the user you want to receive events for
      .withUser("user_v9KUoZvTGp6ID")
      // Construct the websocket client
      .websocketClient();
  3. Add event handlers for messages:

    websocket.on("message", (message) => {
      console.log("Received Message:", message);
    
      const chatMessage = message.feedEntity?.dmsPost;
      if (chatMessage) {
        // handle the chat message
      }
    
      const forumPost = message.feedEntity?.forumPost;
      if (forumPost) {
        // handle the forum post
      }
    });
  4. Add event handlers for status changes (same as client API):

    websocket.on("connectionStatus", (status) => {
      console.log("Websocket Status Updated:", status);
    });
    
    // Or you can also listen to the connect and disconnect events:
    websocket.on("connect", () => {
      console.log("Websocket Connected");
    });
    
    websocket.on("disconnect", () => {
      console.log("Websocket Disconnected");
    });
  5. Connect to the websocket and start receiving events:

    websocket.connect();
  6. Optional: Disconnect from the websocket:

    websocket.disconnect();

React Example

You can use the WhopWebsocketProvider component to wrap your app and provide the websocket client and status to your components.

my-app.tsx
"use client";

import type { proto } from "@whop/api";
import { useCallback, useState } from "react";
import {
  WhopWebsocketProvider,
  useWebsocket,
  useWebsocketStatus,
} from "./websocket-provider";

export function MyApp({ experienceId }: { experienceId: string }) {
  const [message, setMessage] = useState("");

  const onAppMessage = useCallback((message: proto.common.AppMessage) => {
    setMessage(message.json);
  }, []);

  return (
    <WhopWebsocketProvider
      joinExperience={experienceId}
      onAppMessage={onAppMessage}
    >
      <div>{message}</div>
      <ComponentThatSendsMessages />
      <ComponentThatDisplaysConnectionStatus />
    </WhopWebsocketProvider>
  );
}

function ComponentThatSendsMessages() {
  const websocket = useWebsocket();

  function handleClick() {
    websocket.broadcast({ message: "Hello, world!", target: "everyone" });
  }

  return (
    <div>
      <button type="button" onClick={handleClick}>
        Send Message
      </button>
    </div>
  );
}

function ComponentThatDisplaysConnectionStatus() {
  const status = useWebsocketStatus();

  return (
    <div>
      <p>Connection Status: {status}</p>
    </div>
  );
}
websocket-provider.tsx
"use client";

import {
  type WebsocketStatus,
  WhopClientSdk,
  type WhopWebsocketClientBrowser,
  type proto,
} from "@whop/api";
import {
  type PropsWithChildren,
  createContext,
  use,
  useEffect,
  useState,
} from "react";

const whopApi = WhopClientSdk();
const WebsocketContext = createContext<WhopWebsocketClientBrowser>(
  whopApi.websocketClient({})
);
const WebsocketStatusContext = createContext<WebsocketStatus>("disconnected");

export function useWebsocket() {
  return use(WebsocketContext);
}

export function useWebsocketStatus() {
  const status = use(WebsocketStatusContext);
  return status;
}

export function WhopWebsocketProvider({
  children,
  joinCustom,
  joinExperience,
  onAppMessage,
}: PropsWithChildren<{
  joinCustom?: string;
  joinExperience?: string;
  onAppMessage: (message: proto.common.AppMessage) => void;
}>) {
  const [websocket, setWebsocket] = useState<WhopWebsocketClientBrowser>(() =>
    whopApi.websocketClient({})
  );

  const [connectionStatus, setConnectionStatus] =
    useState<WebsocketStatus>("disconnected");

  useEffect(() => {
    const websocket = whopApi.websocketClient({
      joinCustom,
      joinExperience,
    });
    setWebsocket(websocket);
    websocket.on("connectionStatus", setConnectionStatus);
    return websocket.connect();
  }, [joinExperience, joinCustom]);

  useEffect(() => {
    if (websocket) {
      websocket.on("appMessage", onAppMessage);
      return () => {
        websocket.off("appMessage", onAppMessage);
      };
    }
  }, [onAppMessage, websocket]);

  return (
    <WebsocketContext.Provider value={websocket}>
      <WebsocketStatusContext.Provider value={connectionStatus}>
        {children}
      </WebsocketStatusContext.Provider>
    </WebsocketContext.Provider>
  );
}