--- sidebar_position: 4 --- # Plugin API Reference `TojuClientPluginApi` is the object passed to a plugin activation context. The runtime freezes the API object before passing it to plugin code. This page is the compact map. Use the focused API pages for concrete copy-paste examples with literal input data. ## Focused API Pages - [Context and Logging](./api/context-and-logging.md) - [Profile API](./api/profile.md) - [Users and Roles API](./api/users-and-roles.md) - [Server API](./api/server.md) - [Channels API](./api/channels.md) - [Messages and Typing API](./api/messages-and-typing.md) - [Events API](./api/events.md) - [Message Bus API](./api/message-bus.md) - [P2P and Media API](./api/p2p-and-media.md) - [Storage API](./api/storage.md) - [UI API](./api/ui.md) ## Activation Types ```ts interface TojuPluginDisposable { dispose: () => void; } interface TojuPluginActivationContext { api: TojuClientPluginApi; manifest: TojuPluginManifest; pluginId: string; subscriptions: TojuPluginDisposable[]; } interface TojuClientPluginModule { activate?: (context: TojuPluginActivationContext) => Promise | void; deactivate?: (context: TojuPluginActivationContext) => Promise | void; onPluginDataChanged?: (context: TojuPluginActivationContext, event: unknown) => Promise | void; onServerRequirementsChanged?: (context: TojuPluginActivationContext, snapshot: PluginRequirementsSnapshot) => Promise | void; ready?: (context: TojuPluginActivationContext) => Promise | void; } ``` ## Profiles ```ts interface PluginApiProfileUpdate { description?: string; displayName: string; } interface PluginApiAvatarUpdate { avatarHash: string; avatarMime: string; avatarUrl: string; } ``` | Method | Capability | Description | | --- | --- | --- | | `profile.getCurrent()` | `profile.read` | Returns the current `User` or `null`. | | `profile.update(profile)` | `profile.write` | Updates display name and optional description. | | `profile.updateAvatar(avatar)` | `profile.write` | Updates avatar URL, MIME type, and hash metadata. | ## Users and Roles | Method | Capability | Description | | --- | --- | --- | | `users.getCurrent()` | `users.read` | Returns current `User` or `null`. | | `users.list()` | `users.read` | Returns known users. | | `users.readMembers()` | `users.read` | Returns active room members. | | `users.setRole(userId, role)` | `roles.manage` | Updates a user's role. | | `users.kick(userId)` | `users.manage` | Kicks a user. | | `users.ban(userId, reason?)` | `users.manage` | Bans a user with optional reason. | | `roles.list()` | `roles.read` | Returns room roles. | | `roles.setAssignments(assignments)` | `roles.manage` | Replaces role assignments. | ## Server ```ts interface PluginApiServerSettingsUpdate { description?: string; isPrivate?: boolean; maxUsers?: number; name?: string; password?: string; topic?: string; } interface PluginApiPluginUserRequest { avatarUrl?: string; displayName: string; id?: string; } ``` | Method | Capability | Description | | --- | --- | --- | | `server.getCurrent()` | `server.read` | Returns the current `Room` or `null`. | | `server.registerPluginUser(request)` | `users.manage` | Adds a plugin-owned user and returns its id. | | `server.updatePermissions(permissions)` | `server.manage` | Updates partial room permissions. | | `server.updateSettings(settings)` | `server.manage` | Updates room settings. | ## Channels ```ts interface PluginApiChannelRequest { id?: string; name: string; position?: number; } ``` | Method | Capability | Description | | --- | --- | --- | | `channels.list()` | `channels.read` | Returns current room channels. | | `channels.select(channelId)` | `channels.read` | Selects a channel. | | `channels.addAudioChannel(request)` | `channels.manage` | Adds a voice channel. | | `channels.addVideoChannel(request)` | `channels.manage` | Registers a video channel section. | | `channels.rename(channelId, name)` | `channels.manage` | Renames a channel. | | `channels.remove(channelId)` | `channels.manage` | Removes a channel. | ## Messages ```ts interface PluginApiMessageAsPluginUserRequest { channelId?: string; content: string; pluginUserId: string; } ``` | Method | Capability | Description | | --- | --- | --- | | `messages.readCurrent()` | `messages.read` | Returns current visible messages. | | `messages.send(content, channelId?)` | `messages.send` | Sends a message and returns the created `Message`. | | `messages.sendAsPluginUser(request)` | `messages.send` | Emits a message from a registered plugin user. | | `messages.setTyping(isTyping, channelId?)` | `messages.send` | Broadcasts current typing state for a channel. | | `messages.subscribeTyping(handler)` | `messages.read` | Subscribes to peer typing state. | | `messages.edit(messageId, content)` | `messages.editOwn` | Edits a plugin message. | | `messages.delete(messageId)` | `messages.deleteOwn` | Deletes a plugin message. | | `messages.moderateDelete(messageId)` | `messages.moderate` | Performs a moderation delete. | | `messages.sync(messages)` | `messages.sync` | Syncs an array of messages into state. | ## Events ```ts interface PluginApiEventSubscription { eventName: string; handler: (event: PluginEventEnvelope) => void; } interface PluginEventEnvelope { emittedAt?: number; eventId?: string; eventName: string; payload: TPayload; pluginId: string; serverId: string; sourcePluginUserId?: string; sourceUserId?: string; type: 'plugin_event'; } ``` | Method | Capability | Description | | --- | --- | --- | | `events.publishServer(eventName, payload)` | `events.server.publish` | Sends a declared plugin event through the signaling server. | | `events.subscribeServer(subscription)` | `events.server.subscribe` | Subscribes to a declared server plugin event. | | `events.publishP2p(eventName, payload)` | `events.p2p.publish` | Sends a declared plugin event over peer paths. | | `events.subscribeP2p(subscription)` | `events.p2p.subscribe` | Registers a P2P event subscription. | ## Message Bus ```ts interface PluginApiMessageBusEnvelope { channelId?: string; eventId: string; messages?: Message[]; payload?: unknown; pluginId: string; roomId: string; sentAt: number; sourcePeerId?: string; sourceUserId?: string; topic: string; } interface PluginApiMessageBusLatestRequest { channelId?: string; includeDeleted?: boolean; limit?: number; sinceTimestamp?: number; targetPeerId?: string; topic?: string; } interface PluginApiMessageBusPublishRequest extends PluginApiMessageBusLatestRequest { includeLatestMessages?: boolean; includeSelf?: boolean; payload?: unknown; topic: string; } interface PluginApiMessageBusSubscription { channelId?: string; handler: (event: PluginApiMessageBusEnvelope) => void; latestMessageLimit?: number; replayLatest?: boolean; topic?: string; } ``` | Method | Capability | Description | | --- | --- | --- | | `messageBus.publish(request)` | `events.p2p.publish`, optionally `messages.read` | Publishes a plugin-bus event, optionally including latest messages. | | `messageBus.sendLatestMessages(request?)` | `events.p2p.publish` and `messages.read` | Sends a latest-message snapshot. | | `messageBus.subscribe(subscription)` | `events.p2p.subscribe`, optionally `messages.read` | Subscribes to plugin-bus events, optionally replaying latest messages. | ## P2P and Media ```ts interface PluginApiAudioClipRequest { volume?: number; url: string; } interface PluginApiCustomStreamRequest { label?: string; stream: MediaStream; } ``` | Method | Capability | Description | | --- | --- | --- | | `p2p.connectedPeers()` | `p2p.data` | Returns connected peer ids. | | `p2p.broadcastData(eventName, payload)` | `p2p.data` | Broadcasts plugin data. | | `p2p.sendData(peerId, eventName, payload)` | `p2p.data` | Sends plugin data targeted to a peer. | | `media.playAudioClip(request)` | `media.playAudio` | Plays an audio URL at optional volume. | | `media.addCustomAudioStream(request)` | `media.addAudioStream` | Contributes an audio `MediaStream`. | | `media.addCustomVideoStream(request)` | `media.addVideoStream` | Registers a video `MediaStream` contribution. | | `media.setInputVolume(volume)` | `audio.volume` | Sets local input volume. | | `media.setOutputVolume(volume)` | `audio.volume` | Sets local output volume. | ## Storage | Method | Capability | Description | | --- | --- | --- | | `clientData.read(key)` | `storage.local` | Reads async plugin-local data. | | `clientData.write(key, value)` | `storage.local` | Writes async plugin-local data. | | `clientData.remove(key)` | `storage.local` | Removes async plugin-local data. | | `serverData.read(key)` | `storage.serverData.read` | Reads local per-user/per-server data. | | `serverData.write(key, value)` | `storage.serverData.write` | Writes local per-user/per-server data. | | `serverData.remove(key)` | `storage.serverData.write` | Removes local per-user/per-server data. | | `storage.get(key)` | `storage.local` | Legacy synchronous local read. | | `storage.set(key, value)` | `storage.local` | Legacy synchronous local write. | | `storage.remove(key)` | `storage.local` | Legacy synchronous local remove. | ## UI Contributions ```ts interface PluginApiActionContribution { icon?: string; label: string; run: () => Promise | void; } interface PluginApiPageContribution { label: string; path: string; render: () => HTMLElement | string; } interface PluginApiPanelContribution { label: string; order?: number; render: () => HTMLElement | string; } interface PluginApiSettingsPageContribution { label: string; order?: number; render: () => HTMLElement | string; settingsKey?: string; } interface PluginApiChannelSectionContribution { label: string; order?: number; type?: 'audio' | 'custom' | 'video'; } interface PluginApiEmbedRendererContribution { embedType: string; render: (payload: unknown) => HTMLElement | string; } interface PluginApiDomMountRequest { element: HTMLElement; position?: InsertPosition; target: Element | string; } ``` | Method | Capability | Description | | --- | --- | --- | | `ui.registerAppPage(id, contribution)` | `ui.pages` | Adds a plugin app page. | | `ui.registerSettingsPage(id, contribution)` | `ui.settings` | Adds a plugin settings page. | | `ui.registerSidePanel(id, contribution)` | `ui.sidePanel` | Adds a side panel. | | `ui.registerChannelSection(id, contribution)` | `ui.channelsSection` | Adds a channel section. | | `ui.registerComposerAction(id, contribution)` | `ui.pages` | Adds a composer action. | | `ui.registerProfileAction(id, contribution)` | `ui.pages` | Adds a profile action. | | `ui.registerToolbarAction(id, contribution)` | `ui.pages` | Adds a toolbar action. | | `ui.registerEmbedRenderer(id, contribution)` | `ui.embeds` | Adds an embed renderer. | | `ui.mountElement(id, request)` | `ui.dom` | Mounts plugin-owned DOM into a target element or selector. | ## Context and Logger | Method | Capability | Description | | --- | --- | --- | | `context.getCurrent()` | None | Reads current user, server, active text channel, and active voice channel. | | `logger.debug(message, data?)` | None | Writes a debug plugin log entry. | | `logger.info(message, data?)` | None | Writes an info plugin log entry. | | `logger.warn(message, data?)` | None | Writes a warning plugin log entry. | | `logger.error(message, data?)` | None | Writes an error plugin log entry. |