---
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.
