--- sidebar_position: 7 --- # Events API Plugin events allow plugins to publish and subscribe to declared server or P2P events. ## Required Capabilities | Method | Capability | | --- | --- | | `events.publishServer(eventName, payload)` | `events.server.publish` | | `events.subscribeServer(subscription)` | `events.server.subscribe` | | `events.publishP2p(eventName, payload)` | `events.p2p.publish` | | `events.subscribeP2p(subscription)` | `events.p2p.subscribe` | ## Declare Events in the Manifest ```json { "events": [ { "eventName": "poll:vote", "direction": "p2pHint", "scope": "channel", "maxPayloadBytes": 2048 }, { "eventName": "moderation:flag", "direction": "serverRelay", "scope": "server", "maxPayloadBytes": 4096 } ] } ``` ## Publish and Subscribe to P2P Events ```js export function activate(context) { context.subscriptions.push(context.api.events.subscribeP2p({ eventName: 'poll:vote', handler: (event) => { context.api.logger.info('Vote received', { optionId: event.payload?.optionId, voterName: event.payload?.voterName, eventId: event.eventId }); } })); context.api.events.publishP2p('poll:vote', { pollId: 'raid-night-2026-04-29', optionId: 'dungeon', voterName: 'Alice' }); } ``` ## Publish and Subscribe to Server Events ```js export function activate(context) { context.subscriptions.push(context.api.events.subscribeServer({ eventName: 'moderation:flag', handler: (event) => { context.api.logger.warn('Moderation flag received', { messageId: event.payload?.messageId, reason: event.payload?.reason }); } })); context.api.events.publishServer('moderation:flag', { messageId: 'msg-20260429-flagged', reason: 'Possible spam link', reportedBy: 'user-alice-01' }); } ``` Example event envelope: ```json { "type": "plugin_event", "eventName": "poll:vote", "pluginId": "example.polls", "serverId": "room-7ebdde75", "eventId": "event-1777473600000-1", "emittedAt": 1777473600000, "payload": { "pollId": "raid-night-2026-04-29", "optionId": "dungeon", "voterName": "Alice" } } ```