Skip to content

platform sdk custom events

Andre Lafleur edited this page Sep 11, 2026 · 13 revisions

Custom events

Applications can raise custom events on entities, monitor them in real time, and use them to trigger actions.

About custom events

Custom events are user-defined events that supplement the built-in Security Center events. They allow you to:

  • Define events specific to your integration or workflow
  • Raise events on any entity in the system
  • Display events in the Monitoring task
  • Trigger event-to-action rules (see Event-to-actions)

Access the custom event service

Access the ICustomEventService through the SystemConfiguration entity:

var systemConfig = (SystemConfiguration)engine.GetEntity(SystemConfiguration.SystemConfigurationGuid);
ICustomEventService customEventService = systemConfig.CustomEventService;

Custom event ownership

Custom events have an owner that determines who can delete them:

Owner Created by Can be deleted by
None (local) SDK applications Anyone with the GeneralSettingsEvents privilege
Plugin Plugin roles Anyone with the GeneralSettingsEvents privilege
Federated system External Security Center Cannot be deleted locally

When a plugin creates a custom event, the event is automatically associated with that plugin's subtype GUID. This ensures the custom event remains available as long as the plugin is registered. Because it is a local custom event, any caller with the GeneralSettingsEvents privilege can remove it.

SDK applications create local custom events with no owner. These events can be deleted by any user with sufficient privileges.

Custom events from federated Security Center systems appear in your system but cannot be modified or deleted locally.

Inspect ownership

Use the Owner property to get the GUID of the custom event's owner:

CustomEvent evt = customEventService.GetCustomEvent(1001);
Guid owner = evt.Owner;

For local events created by SDK applications, Owner returns Guid.Empty. For plugin-owned events, Owner returns the plugin's subtype GUID. For federated events, Owner returns the federation role GUID.

Use the LocalCustomEvent property to check whether a custom event can be deleted:

if (evt.LocalCustomEvent)
{
    customEventService.Remove(evt);
}

This property returns true for local and plugin-owned events, and false for federated events. You can remove events only when this property returns true.

Create custom events

Use ICustomEventBuilder to define a new custom event:

ICustomEventBuilder builder = customEventService.CreateCustomEventBuilder();

CustomEvent customEvent = builder
    .SetName("Equipment Malfunction")
    .SetEntityType(EntityType.CustomEntity)
    .Build();

The SetName() and SetEntityType() methods are required. The entity type specifies which entities can raise this event.

Specify a custom event identifier (ID)

By default, the system assigns the next available ID when the event is added. To specify a particular ID:

CustomEvent customEvent = builder
    .SetName("Equipment Malfunction")
    .SetEntityType(EntityType.CustomEntity)
    .SetId(1001)
    .Build();

Add custom events to the system

After building a custom event, add it to the system:

CustomEventUpdateResult result = customEventService.Add(customEvent);

if (result.Success)
{
    int assignedId = result.Id;
}

The CustomEvent.Id property is also updated with the assigned ID after a successful add.

Adding, updating, and removing custom events require the caller to hold the GeneralSettingsEvents privilege. If the current user lacks the privilege, these methods throw an SdkException with SdkError.UnsufficientPrivilege. Building an event with ICustomEventBuilder does not require the privilege.

Custom event names must be unique. Add throws an ArgumentException if an event with the same name already exists. Choose a distinct name or update the existing event instead.

Ownership when adding

When called from a plugin, the custom event is automatically owned by that plugin. When called from an SDK application, the custom event is local (no owner).

Plugins can create local custom events instead of plugin-owned events by passing Guid.Empty:

CustomEventUpdateResult result = customEventService.Add(Guid.Empty, customEvent);

Add multiple custom events

Use AddAsync to add multiple custom events in one asynchronous operation:

CustomEvent event1 = builder.SetName("Event One").SetEntityType(EntityType.Camera).Build();
CustomEvent event2 = builder.SetName("Event Two").SetEntityType(EntityType.Door).Build();

CustomEventUpdateResult[] results = await customEventService.AddAsync(event1, event2);

Localize custom event names

CustomEvent.Id is the value used to reference the custom event definition in SDK operations. Name is stored display text, and Security Center does not resolve it through a per-client resource key. Native Security Center pages display the same stored name after the client language changes.

Create one custom event for the event meaning, not one event per language. Use its ID in integration logic. A custom Workspace view can map that ID to an integration resource key and resolve the label with Workspace.Culture. For this pattern, see Workspace SDK localization.

Retrieve custom events

After creating custom events, you can inspect the full collection or retrieve individual definitions by identifier.

Get all custom events

IReadOnlyList<CustomEvent> allEvents = customEventService.CustomEvents;

foreach (CustomEvent evt in allEvents)
{
    Console.WriteLine($"ID: {evt.Id}, Name: {evt.Name}, EntityType: {evt.SourceEntityType}");
}

Get a specific custom event

Retrieve by ID:

CustomEvent evt = customEventService.GetCustomEvent(1001);

Retrieve by ID and owner (for plugin-owned custom events):

CustomEvent evt = customEventService.GetCustomEvent(1001, ownerRoleGuid);

Retrieve by name:

CustomEvent evt = customEventService.GetCustomEvent("Equipment Malfunction");

Check whether a custom event exists

bool exists = customEventService.Contains(1001);

Update custom events

Update a custom event's name using CustomEventUpdateInfo:

var updateInfo = new CustomEventUpdateInfo
{
    Id = 1001,
    Name = "Equipment Failure"
};

CustomEventUpdateResult result = customEventService.Update(updateInfo);

To get the updated CustomEvent object:

CustomEventUpdateResult result = customEventService.Update(updateInfo, out CustomEvent updatedEvent);

Remove custom events

Remove by ID:

CustomEventUpdateResult result = customEventService.Remove(1001);

Remove by name:

CustomEventUpdateResult result = customEventService.Remove("Equipment Malfunction");

Remove by object:

CustomEventUpdateResult result = customEventService.Remove(customEvent);

You can remove any local custom event, whether it has no owner or is plugin-owned, if you have the GeneralSettingsEvents privilege. Custom events from a federated system are not local and cannot be removed.

Raise custom events

To raise a custom event on an entity:

  1. Build the event using ActionManager.BuildEvent.
  2. Cast to CustomEventInstance and set the event ID and message.
  3. Call RaiseEvent.
var eventInstance = (CustomEventInstance)engine.ActionManager.BuildEvent(
    EventType.CustomEvent,
    sourceEntityGuid);

eventInstance.Id = new CustomEventId(1001);
eventInstance.Message = "Sensor detected anomaly at 14:30";

engine.ActionManager.RaiseEvent(eventInstance);

Custom event IDs must be 1 or greater. Passing 0 or a negative value to CustomEventId throws an ArgumentException.

Report access control custom events

An Access Manager role records custom events raised on supported access control entities that it manages. By default, the role excludes events raised on source entities owned by a plugin. This restriction concerns the source entity, not the owner of the custom event definition.

To retrieve a recorded event, use the activity report query that matches the source entity type:

Source entity Native report query Key result columns
Access-control area AreaActivityQuery SourceGuid, AccessPointGroupGuid, CustomEventMessage
Cardholder CardholderActivityQuery SourceGuid, CardholderGuid, CustomEventMessage
Credential CredentialActivityQuery SourceGuid, CredentialGuid, CustomEventMessage
Door DoorActivityQuery SourceGuid, AccessPointGroupGuid, CustomEventMessage

To query only specific custom events, create a new activity report query. Before executing it, clear its Events and CustomEvents collections, and then add the required IDs to CustomEvents. Create a new query when changing the event filters after execution. Door activity queries include event filters by default.

Use the positive custom event ID when you filter a report query by custom event. The returned row exposes the same custom event ID as a negative EventType value. For example, a custom event with ID 1001 appears as -1001 in the activity report results.

AccessControlRawEventQuery can also show that the Access Manager recorded the event in its raw stream, but it is an incremental stream query and does not expose CustomEventMessage. Use the native activity report when your application needs the custom event message or the entity-specific report columns.

For area events, use an access control area that participates in the access control topology. Use the activity report queries listed above to retrieve recorded custom events.

A camera associated with a door-side access point or an area remains the source of any custom event raised on that camera. These associations do not cause the Access Manager role to record camera-sourced custom events. To create a door activity record, raise the custom event on the door.

Add related entities

Associate additional entities with the event:

eventInstance.AddRelatedEntity(relatedCameraGuid);
eventInstance.AddRelatedEntities(new[] { entity1Guid, entity2Guid });

Include hidden payload

Send data that is not displayed in the user interface (UI) but is available to SDK applications:

eventInstance.ExtraHiddenPayload = "{\"sensorId\": 42, \"reading\": 98.6}";

Subscribe to custom events

Subscribe to the Engine.EventReceived event and check for CustomEventReceivedEventArgs:

engine.EventReceived += OnEventReceived;

private void OnEventReceived(object sender, EventReceivedEventArgs e)
{
    if (e is CustomEventReceivedEventArgs customEventArgs)
    {
        int eventId = customEventArgs.CustomEventId;
        string message = customEventArgs.Message;
        string hiddenPayload = customEventArgs.ExtraHiddenPayload;
        Guid sourceEntity = customEventArgs.SourceGuid;

        Console.WriteLine($"Custom event {eventId}: {message}");
    }
}

Note

To receive events for an entity, that entity must be loaded in the Engine entity cache. Use engine.GetEntity to load the entity before expecting to receive its events.

Monitor custom event definition changes

Subscribe to changes in the custom event definitions. The handler in this example refreshes the custom event collection after a change:

var systemConfig = (SystemConfiguration)engine.GetEntity(SystemConfiguration.SystemConfigurationGuid);
systemConfig.CustomEventsChanged += OnCustomEventsChanged;

private void OnCustomEventsChanged(object sender, EventArgs e)
{
    IReadOnlyList<CustomEvent> events = systemConfig.CustomEventService.CustomEvents;
}

Custom events with custom entity types

When defining a custom entity type, specify which custom events it supports:

var descriptor = new CustomEntityTypeDescriptor(
    id: customTypeGuid,
    name: "Evidence Locker",
    capabilities: CustomEntityTypeCapabilities.IsVisible,
    version: new Version(1, 0, 0));

    descriptor.SupportedCustomEvents = new[] { 1001, 1002, 1003 };

See also

Platform SDK

Plugin SDK

Workspace SDK

Media SDK

Macro SDK

Web SDK

Synergis RIO

Media Gateway

Genetec Web Player

Clone this wiki locally