Extension event envelope
ExtensionEvent is the in-process payload delivered to an extension that implements IEventExtension. Every extension event uses the same envelope; the event name determines whether Data has an event-specific shape.
Runtime shape
Section titled “Runtime shape”public record ExtensionEvent( string EventType, string EntityType, int EntityId, Dictionary<string, object?>? Data = null){ public string CanonicalEventType { get; init; } = EventType;}The following JSON shows the equivalent property values for reference. Cove passes the C# object directly and does not serialize an HTTP request.
{ "eventType": "video.updated", "canonicalEventType": "video.updated", "entityType": "video", "entityId": 42, "data": null}Envelope fields
Section titled “Envelope fields”| C# property | JSON notation | Runtime type | Contract |
|---|---|---|---|
CanonicalEventType | canonicalEventType | string | Stable canonical name. Route new handlers on this value. |
EventType | eventType | string | Compatibility event name. It can retain a legacy spelling. |
EntityType | entityType | string | Lowercase kind of the affected entity. |
EntityId | entityId | int | Cove database identifier of the affected entity. |
Data | data | Dictionary<string, object?>? | Event-specific values, or null when the event has no additional payload. |
CanonicalEventType and EventType normally match. Audio and text lifecycle notifications retain dotless compatibility names in EventType, while CanonicalEventType uses the documented noun.verb form.
Payload families
Section titled “Payload families”| Family | Canonical names | Data shape |
|---|---|---|
| Entity lifecycle | <entity>.created, <entity>.updated, <entity>.deleted | null |
| Ratings | rating.created, rating.updated, rating.deleted | { "entity": { "userId", "aspect", "value" } } |
Only EntityEvent values cross this extension boundary. Internal job progress and server lifecycle events are not ExtensionEvent payloads.
Handler rules
Section titled “Handler rules”- Route on
CanonicalEventTypeunless maintaining a handler for a legacyEventTypevalue. - Treat the payload as an invalidation signal and fetch current entity state when needed.
- Expect a deleted entity to be unavailable by the time its handler runs.
- Make handlers idempotent because delivery is best effort and is not an audit log.
- Make handlers safe for concurrent execution; independently queued events can overlap.
- Do not assume replay, retry, or global ordering.