--- sidebar_position: 3 --- # Capabilities Capabilities protect privileged app surfaces. A plugin must declare a capability in its manifest and the user must grant it before the runtime allows the corresponding API call. | Capability | API areas | Notes | | --- | --- | --- | | `profile.read` | `profile.getCurrent()` | Reads the current user. | | `profile.write` | `profile.update()`, `profile.updateAvatar()` | Updates local profile fields and avatar metadata. | | `users.read` | `users.getCurrent()`, `users.list()`, `users.readMembers()` | Reads users and server members. | | `users.manage` | `users.kick()`, `users.ban()`, `server.registerPluginUser()` | Can create plugin users and moderate members. | | `roles.read` | `roles.list()` | Reads server roles. | | `roles.manage` | `roles.setAssignments()`, `users.setRole()` | Changes role assignments or user roles. | | `messages.read` | `messages.readCurrent()`, message bus latest snapshots | Reads current channel messages. | | `messages.send` | `messages.send()`, `messages.sendAsPluginUser()` | Sends messages as the current user or registered plugin user. | | `messages.editOwn` | `messages.edit()` | Edits plugin-owned messages. | | `messages.deleteOwn` | `messages.delete()` | Deletes plugin-owned messages. | | `messages.moderate` | `messages.moderateDelete()` | Moderation delete path. | | `messages.sync` | `messages.sync()` | Syncs message arrays into client state. | | `channels.read` | `channels.list()`, `channels.select()` | Reads and selects channels. | | `channels.manage` | `channels.addAudioChannel()`, `channels.addVideoChannel()`, `channels.remove()`, `channels.rename()` | Mutates channel or channel-section state. | | `server.read` | `server.getCurrent()` | Reads active server. | | `server.manage` | `server.updatePermissions()`, `server.updateSettings()` | Updates server permissions or settings. | | `p2p.data` | `p2p.connectedPeers()`, `p2p.broadcastData()`, `p2p.sendData()` | Uses plugin peer data paths. | | `p2p.media` | Reserved peer media features. | Included for media-facing plugins. | | `media.playAudio` | `media.playAudioClip()` | Plays an audio URL locally. | | `media.addAudioStream` | `media.addCustomAudioStream()` | Adds a custom stream to voice handling. | | `media.addVideoStream` | `media.addCustomVideoStream()` | Registers custom video stream contribution. | | `audio.volume` | `media.setInputVolume()`, `media.setOutputVolume()` | Adjusts local voice volume. | | `audio.effects` | Reserved audio effect features. | Included for audio processing plugins. | | `ui.settings` | `ui.registerSettingsPage()` | Adds settings pages. | | `ui.pages` | `ui.registerAppPage()`, `ui.registerComposerAction()`, `ui.registerProfileAction()`, `ui.registerToolbarAction()` | Adds app pages and actions. | | `ui.sidePanel` | `ui.registerSidePanel()` | Adds side panels. | | `ui.channelsSection` | `ui.registerChannelSection()` | Adds channel sections. | | `ui.embeds` | `ui.registerEmbedRenderer()` | Renders custom embeds. | | `ui.dom` | `ui.mountElement()` | Mounts plugin-owned DOM into app targets. | | `storage.local` | `storage.*`, `clientData.*` | Reads and writes plugin-local data. | | `storage.serverData.read` | `serverData.read()` | Reads local per-user/per-server plugin data. | | `storage.serverData.write` | `serverData.write()`, `serverData.remove()` | Writes or removes local per-user/per-server plugin data. | | `events.server.publish` | `events.publishServer()` | Publishes declared server plugin events. | | `events.server.subscribe` | `events.subscribeServer()` | Subscribes to declared server plugin events. | | `events.p2p.publish` | `events.publishP2p()`, `messageBus.publish()`, `messageBus.sendLatestMessages()` | Publishes declared P2P/plugin bus events. | | `events.p2p.subscribe` | `events.subscribeP2p()`, `messageBus.subscribe()` | Subscribes to declared P2P/plugin bus events. | ## Recommended Practice Request the fewest capabilities possible. Separate broad features into optional plugin modules when a single plugin would otherwise need many unrelated grants.