Repository navigation
platform sdk 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.
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
RelatedAccessPointscollection 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}");-
AccessRuleType(read-only): the rule type, eitherPermanentorTemporary. The type is set when the rule is created and cannot be changed afterward. System rules are identified separately byIsSystemRule. -
IsDenyingRule(read+writebool): whentrue, the rule explicitly denies access; whenfalse, it grants. Deny rules take precedence over grant rules at the same access point. -
IsSystemRule(read-onlybool):truefor built-in rules created by Security Center itself. System rules are typically not editable. -
Cardholders(read-onlyIReadOnlyList<Guid>): the cardholder Guids the rule applies to. Mutate through the methods below; do not modify the list directly. -
Schedule(read+writeSchedule) andScheduleGuid(read+writeGuid): the schedule the rule honors. -
StartTime(read+writeDateTime) andEndTime(read+writeDateTime): bound the rule's validity window. Outside this window the rule does not grant access regardless of the schedule. These properties are settable only onTemporaryrules; assigning either on aPermanentrule 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 throughDoor.AddAccessRule(Guid, AccessRuleSide)andElevator.AddAccessRule(Guid).
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);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.
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.
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.
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}");-
Coverage: Gets or sets the schedule's days, times, and date ranges as aCoverageobject. Reading the property returns a copy. Assign the modified copy back toSchedule.Coverageto save your changes. -
SupportTwilightCoverage(read-onlybool):truewhen the schedule supports sunset and sunrise rules. Do not assign a twilight schedule to an access rule. -
AccessRules(read-onlyIReadOnlyCollection<Guid>): every access rule that currently honors this schedule. This is the reverse lookup ofAccessRule.Schedule.
-
IsTimeCovered(DateTime time): returnstrueif the supplied moment falls inside the schedule's coverage. Use this for runtime "is this allowed now?" checks. Coverage is compared in local time: aDateTimewhoseKindisUtcis converted to local time first, while a value whoseKindisLocalorUnspecifiedis used as-is. PassDateTime.UtcNow(or aLocalvalue with the correctKind) so the comparison lands on the moment you intend, especially near day or twilight boundaries. -
Reset(): clears the schedule's 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.
A typical "grant" rule wires four entities:
- A
Schedulethat defines when access is permitted. - An
AccessRulethat references the schedule and lists the cardholders or groups. - One or more
DoororElevatorentities that attach the rule to specific sides. - The
Cardholder(orCardholderGroup) 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.
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.
- You must be logged on with privileges to create access rules.
- A
Schedulemust exist (or be created alongside the rule). - The cardholders or cardholder groups, and the target door, must already exist.
-
Create the access rule with the type you need. Use
AccessRuleType.Temporarywhen the rule must have start and end dates. UseAccessRuleType.Permanentwhen the rule does not expire.AccessRule rule = engine.CreateAccessRule( "Office hours - Lobby", AccessRuleType.Temporary);
-
Set the schedule the rule honors.
Schedule schedule = engine.GetEntity<Schedule>(scheduleGuid); rule.Schedule = schedule;
-
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 });
-
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 atEndTime; 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);
-
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);
-
Verify the rule grants access at a given moment.
Credential.HasAccessreturns anAccessResultreporting 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().
- About access control: The access control hub.
- About cardholders and credentials: Cardholder and credential lifecycle in depth.
- About doors, areas, elevators, and access points: The location entities and their per-access-point wiring.
- Door templates: Reusable door configuration projected across many doors.
- Overview
- Connecting to Security Center
- SDK certificates
- Referencing SDK assemblies
- ASP.NET hosting
- SDK compatibility
- Migrating to modern .NET
- Entities
- Entity cache
- Entity loading, cache, and query options
- Detecting entity changes
- Entity change event reference
- Transactions
- Security Center events
- Actions
- Security Desk
- Custom events
- Event-to-actions
- Managing macros
- ReportManager
- ReportManager query reference
- Access control raw events
- DownloadAllRelatedData and StrictResults
- Privileges
- Partitions
- Entity write restrictions
- About custom fields
- About video
- About cameras
- Enrolling a video unit
- Ingesting third-party video
- Archiver and auxiliary archiver roles
- Archive transfer
- About access control
- About cardholders and credentials
- About doors, areas, elevators, and access points
- About access rules and schedules
- About access control units and interface modules
- Enrolling an access control unit
- Door templates
- Visitors
- Mobile credentials
- About threat levels
- About alarms
- About incidents
- Maps
- Logging
- Overview
- Localization
- Certificates
- Lifecycle
- Threading
- State management
- Configuration
- Restricted configuration
- Events
- Queries
- Request manager
- Database
- Entity ownership
- Engine extensions
- Entity mappings
- Server management
- Custom privileges
- Custom entity types
- Resolving non-SDK assemblies
- Deploying plugins
- Modern .NET support
- Overview
- Localization
- Certificates
- Creating modules
- Tasks
- Pages
- Components
- Tile extensions
- Services
- Contextual actions
- Custom actions
- Options extensions
- Configuration pages
- Monitors
- Shared components
- Commands
- Extending events
- Map extensions
- Timeline providers
- Image extractors
- Credential encoders
- Credential readers
- Cardholder fields extractors
- Badge printers
- Content builders
- Dashboard widgets
- Incidents
- Logon providers
- Pinnable content builders
- Custom report pages
- Overview
- Getting started
- Media file formats
- MediaPlayer
- VideoSourceFilter
- MediaExporter
- MediaFile
- G64 converters
- FileCryptingManager
- PlaybackSequenceQuerier
- PlaybackStreamReader
- OverlayFactory
- PtzCoordinatesManager
- AudioTransmitter
- AudioRecorder
- AnalogMonitorController
- Camera blocking
- Overview
- Getting started
- Referencing entities
- Entity operations
- About access control in the Web SDK
- About video in the Web SDK
- Users and user groups
- Partitions
- Custom fields
- Custom card formats
- Actions
- Events and alarms
- Incidents
- Reports
- Tasks
- Macros
- Custom entity types
- System endpoints
- Performance guide
- Reference
- Endpoints
- Constants
- Enumerations
- Under the hood
- Troubleshooting