Skip to content

platform sdk access rules and schedules

Andre Lafleur edited this page Oct 8, 2026 · 12 revisions

About access rules and schedules

An AccessRule defines who can pass through which access points and on which schedule. A Schedule defines time coverage used by access rules and other Security Center features. Use the two entities together to configure access by person, access point, and time.

Access rules

An AccessRule ties three things together:

  • Who: the cardholders or cardholder groups the rule grants (or denies) access to.
  • When: the schedule the rule honors. Outside the schedule, the rule does not grant access.
  • What: the access points the rule was attached to. Doors and elevators add access rules to specific sides; the rule's RelatedAccessPoints collection reports the resulting attachments.
AccessRule rule = engine.GetEntity<AccessRule>(ruleGuid);

Console.WriteLine($"{rule.Name}");
Console.WriteLine(
    $"  Type: {rule.AccessRuleType}, denying: {rule.IsDenyingRule}");
Console.WriteLine($"  Cardholders: {rule.Cardholders.Count}");
Console.WriteLine($"  Schedule: {rule.Schedule?.Name}");
Console.WriteLine($"  Valid: {rule.StartTime:d} to {rule.EndTime:d}");

Properties

  • AccessRuleType (read-only): the rule type, either Permanent or Temporary. The type is set when the rule is created and cannot be changed afterward. System rules are identified separately by IsSystemRule.
  • IsDenyingRule (read+write bool): when true, the rule explicitly denies access; when false, it grants. Deny rules take precedence over grant rules at the same access point.
  • IsSystemRule (read-only bool): true for built-in rules created by Security Center itself. System rules are typically not editable.
  • Cardholders (read-only IReadOnlyList<Guid>): the cardholder Guids the rule applies to. Mutate through the methods below; do not modify the list directly.
  • Schedule (read+write Schedule) and ScheduleGuid (read+write Guid): the schedule the rule honors.
  • StartTime (read+write DateTime) and EndTime (read+write DateTime): bound the rule's validity window. Outside this window the rule does not grant access regardless of the schedule. These properties are settable only on Temporary rules; assigning either on a Permanent rule is rejected.
  • RelatedAccessPoints (read-only collection): every access point the rule was attached to. The attachment is bidirectional: doors and elevators add or remove rules through Door.AddAccessRule(Guid, AccessRuleSide) and Elevator.AddAccessRule(Guid).

Membership management

Manage the cardholder set on a rule through these methods:

  • AddCardholders(Guid cardholderId): add a single cardholder.
  • AddCardholders(IEnumerable<Guid> cardholderIds): add a batch.
  • RemoveCardholders(Guid cardholderId): remove a single cardholder.
  • RemoveCardholders(IEnumerable<Guid> cardholderIds): remove a batch.
  • ClearCardholders(): remove every cardholder from the rule.

Each returns bool. true means the call was accepted; it does not mean the membership list changed. Adding a cardholder that is already a member returns true and leaves the list unchanged. Compare Cardholders before and after when your application needs to know whether the membership actually changed.

AccessRule rule = engine.GetEntity<AccessRule>(ruleGuid);

rule.AddCardholders(new[] { newCardholderA, newCardholderB });
rule.RemoveCardholders(retiredCardholderGuid);

Membership checks

AccessRule.IsMember(Guid entityGuid) and AccessRule.IsMember(Entity entity) test whether the supplied entity is listed directly in the rule's Cardholders collection:

bool covered = rule.IsMember(cardholderGuid);

The collection can contain cardholder guids and cardholder-group guids. IsMember returns true only for those exact guids; it does not expand a group into its cardholders. To find rules that cover a cardholder, including rules assigned through a group, use Cardholder.AccessRules.

Attaching a rule to a door or elevator

Access rules become effective when attached to a door side or elevator. The attachment is stored on the location entity, not the rule:

Door door = engine.GetEntity<Door>(doorGuid);

door.AddAccessRule(rule.Guid, AccessRuleSide.In);
// ...
door.RemoveAccessRule(rule.Guid, AccessRuleSide.In);

Elevator.AddAccessRule(Guid) applies the rule to the floors currently associated with the elevator. If you add a floor later, call the method again to apply the rule to the new floor as well.

Elevator elevator = engine.GetEntity<Elevator>(elevatorGuid);

elevator.AddAccessRule(rule.Guid);
elevator.RemoveAccessRule(rule.Guid);

After attaching, the rule's RelatedAccessPoints collection reports the new access points. Door.FetchAccessRulesForSide(AccessRuleSide) returns the rules currently attached to a specific door side.

Access rules related to a cardholder

Cardholder.AccessRules lists every access rule that applies to this cardholder: rules that list the cardholder directly, rules inherited through cardholder group membership, and the system rules that apply to all cardholders. The collection contains both grant and deny rules, so check IsDenyingRule before treating a returned rule as a grant. This is the reverse lookup of AccessRule.Cardholders:

Cardholder cardholder = engine.GetEntity<Cardholder>(cardholderGuid);

foreach (Guid ruleGuid in cardholder.AccessRules)
{
    AccessRule rule = engine.GetEntity<AccessRule>(ruleGuid);
    Console.WriteLine($"  {rule.Name} (denying: {rule.IsDenyingRule})");
}

CardholderGroup.AccessRules is the equivalent collection for a cardholder group.

Schedules

A Schedule defines time coverage. Schedules are referenced by access rules, by camera recording modes (through ScheduledRecordingMode), by alarm schedules, and by many other "when" decisions throughout the system.

Schedule schedule = engine.GetEntity<Schedule>(scheduleGuid);

bool open = schedule.IsTimeCovered(DateTime.UtcNow);
Console.WriteLine($"Schedule '{schedule.Name}' active right now: {open}");

Properties

  • Coverage: Gets or sets the schedule's days, times, and date ranges as a Coverage object. Reading the property returns a copy. Assign the modified copy back to Schedule.Coverage to save your changes.
  • SupportTwilightCoverage (read-only bool): true when the schedule supports sunset and sunrise rules. Do not assign a twilight schedule to an access rule.
  • AccessRules (read-only IReadOnlyCollection<Guid>): every access rule that currently honors this schedule. This is the reverse lookup of AccessRule.Schedule.

Methods

  • IsTimeCovered(DateTime time): returns true if the supplied moment falls inside the schedule's coverage. Use this for runtime "is this allowed now?" checks. Coverage is compared in local time: a DateTime whose Kind is Utc is converted to local time first, while a value whose Kind is Local or Unspecified is used as-is. Pass DateTime.UtcNow (or a Local value with the correct Kind) so the comparison lands on the moment you intend, especially near day or twilight boundaries.
  • Reset(): clears the schedule's coverage.

Twilight coverage

When SupportTwilightCoverage is true, the schedule's Coverage can include rules that are evaluated relative to local sunset and sunrise instead of fixed clock times. These schedules are not valid for access rules. Use a schedule without twilight coverage when you assign AccessRule.Schedule or AccessRule.ScheduleGuid.

Putting it together

A typical "grant" rule wires four entities:

  1. A Schedule that defines when access is permitted.
  2. An AccessRule that references the schedule and lists the cardholders or groups.
  3. One or more Door or Elevator entities that attach the rule to specific sides.
  4. The Cardholder (or CardholderGroup) entries the rule grants.
AccessRule rule = engine.GetEntity<AccessRule>(ruleGuid);
Schedule schedule = engine.GetEntity<Schedule>(scheduleGuid);
Door door = engine.GetEntity<Door>(doorGuid);

// Set the schedule on the rule.
rule.Schedule = schedule;

// Add a cardholder group as a member.
rule.AddCardholders(groupOrCardholderGuids);

// Attach the rule to the door's IN side.
door.AddAccessRule(rule.Guid, AccessRuleSide.In);

For evaluating whether a specific cardholder's credential currently grants access at a door side or floor, use Credential.HasAccess(Door.DoorSide, DateTime) and Credential.HasAccess(Floor, DateTime). These methods evaluate the configured access rights, credential status, and schedule coverage at the moment you supply, without involving the reader. Where antipassback is enforced, a result of Granted means the configuration allows access, not that the reader will grant it on the next presentation.

Creating an access rule

The end-to-end workflow to grant a set of cardholders access to a door side on a schedule. The result is a persisted AccessRule attached to a door's IN side, with the configured cardholders covered.

Prerequisites

  • You must be logged on with privileges to create access rules.
  • A Schedule must exist (or be created alongside the rule).
  • The cardholders or cardholder groups, and the target door, must already exist.

Procedure

  1. Create the access rule with the type you need. Use AccessRuleType.Temporary when the rule must have start and end dates. Use AccessRuleType.Permanent when the rule does not expire.

    AccessRule rule = engine.CreateAccessRule(
        "Office hours - Lobby",
        AccessRuleType.Temporary);
  2. Set the schedule the rule honors.

    Schedule schedule = engine.GetEntity<Schedule>(scheduleGuid);
    rule.Schedule = schedule;
  3. Add the cardholders or cardholder groups the rule applies to. Pass cardholder and group guids in the same call.

    rule.AddCardholders(new[] { cardholderA, cardholderB, employeeGroupGuid });
  4. For a temporary rule, set the start and end dates. After EndTime, the rule stops granting access immediately. Security Center does not delete the temporary access rule at EndTime; it keeps the expired rule for a grace period, then automatically deletes the rule entity. The default grace period is 7 days.

    rule.StartTime = DateTime.UtcNow;
    rule.EndTime = DateTime.UtcNow.AddYears(1);
  5. Attach the rule to a door side. The attachment is what makes the rule effective at the reader.

    Door door = engine.GetEntity<Door>(doorGuid);
    door.AddAccessRule(rule.Guid, AccessRuleSide.In);
  6. Verify the rule grants access at a given moment. Credential.HasAccess returns an AccessResult reporting whether access would be granted at the reader at that time.

    Credential credential = engine.GetEntity<Credential>(credentialGuid);
    AccessResult result = credential.HasAccess(door.DoorSideIn, DateTime.UtcNow);

To attach a rule to an elevator instead, use Elevator.AddAccessRule(Guid). The rule applies to the cabin reader and the floors configured on the elevator; no side parameter exists.

To bulk-update an existing rule's membership, use AddCardholders(IEnumerable<Guid>) or RemoveCardholders(IEnumerable<Guid>). To clear membership entirely, call ClearCardholders().

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