Create Schedules

Overview

Schedules define when access is permitted through doors or areas. They are fundamental building blocks that connect to access levels, determining when cardholders can enter controlled spaces. Schedules can contain multiple time intervals and can optionally specify holiday exception types to activate during specific holidays.


Schedule Concepts

Concept Description
ScheduleInfo The main schedule object containing one or more time durations
ScheduleDurationItem A single time window defining days, start time, and duration
DayMask Bit mask representing days of the week when schedule is active
HolidayExceptions Flag values (1-8) indicating which holiday types activate this schedule
IsAlways Special flag for 24/7 access schedules

Understanding DayMask

The DayMask is a 7-bit value where each bit represents a day of the week:

Bit Position Day Value
0 Sunday 1
1 Monday 2
2 Tuesday 4
3 Wednesday 8
4 Thursday 16
5 Friday 32
6 Saturday 64

Common DayMask Values:

Pattern Binary Value Description
Weekdays 0111110 62 Monday through Friday
Weekend 1000001 65 Saturday and Sunday
All Days 1111111 127 Every day
Mon/Wed/Fri 0101010 42 Alternating weekdays
Single Day (Monday) 0000010 2 Monday only

Creating a Standard Weekday Schedule

This creates a typical 9 AM to 5 PM, Monday through Friday schedule:

var standardSchedule = await client.AddScheduleAsync(currentInstance,
    new ScheduleInfo
    {
        CommonName = "StandardBusinessHours",
        ScheduleDurations = new ScheduleDurationItem[]
        {
            new ScheduleDurationItem
            {
                // DayMask 62 = Monday through Friday (binary: 0111110)
                DayMask = 62,
                
                // Start at 9:00 AM
                StartingAt = new TimeSpan(9, 0, 0),
                
                // Duration of 8 hours (ends at 5:00 PM)
                Duration = TimeSpan.FromHours(8)
            }
        }
    });

Console.WriteLine($"Created schedule: {standardSchedule.CommonName} (Key: {standardSchedule.Key})");

Schedule Examples

24/7 Access Schedule

var alwaysAccessSchedule = await client.AddScheduleAsync(currentInstance,
    new ScheduleInfo
    {
        CommonName = "24-7-Access",
        IsAlways = true  // Special flag for continuous access
    });

Extended Hours Schedule (Multiple Durations)

// Split shift: 6 AM - 10 AM and 2 PM - 10 PM, weekdays only
var extendedSchedule = await client.AddScheduleAsync(currentInstance,
    new ScheduleInfo
    {
        CommonName = "ExtendedHours",
        ScheduleDurations = new ScheduleDurationItem[]
        {
            // Morning shift
            new ScheduleDurationItem
            {
                DayMask = 62,  // Weekdays
                StartingAt = new TimeSpan(6, 0, 0),   // 6:00 AM
                Duration = TimeSpan.FromHours(4)      // Until 10:00 AM
            },
            // Afternoon/Evening shift
            new ScheduleDurationItem
            {
                DayMask = 62,  // Weekdays
                StartingAt = new TimeSpan(14, 0, 0),  // 2:00 PM
                Duration = TimeSpan.FromHours(8)      // Until 10:00 PM
            }
        }
    });

Weekend Only Schedule

var weekendSchedule = await client.AddScheduleAsync(currentInstance,
    new ScheduleInfo
    {
        CommonName = "WeekendOnly",
        ScheduleDurations = new ScheduleDurationItem[]
        {
            new ScheduleDurationItem
            {
                DayMask = 65,  // Saturday (64) + Sunday (1)
                StartingAt = new TimeSpan(8, 0, 0),
                Duration = TimeSpan.FromHours(12)
            }
        }
    });

Night Shift Schedule (Crosses Midnight)

// Night shift from 10 PM to 6 AM - duration can cross midnight
var nightSchedule = await client.AddScheduleAsync(currentInstance,
    new ScheduleInfo
    {
        CommonName = "NightShift",
        ScheduleDurations = new ScheduleDurationItem[]
        {
            // Sunday through Thursday nights (10 PM to 6 AM)
            new ScheduleDurationItem
            {
                DayMask = 31,  // Sun-Thu (binary: 0011111)
                StartingAt = new TimeSpan(22, 0, 0),  // 10:00 PM
                Duration = TimeSpan.FromHours(8)      // 8 hours (crosses midnight to 6:00 AM)
            }
        }
    });

Schedules with Holiday Exceptions

Configure schedules to be active during specific holiday types:

// Get holiday types configuration to understand available types
var holidayTypes = await client.GetHolidayTypesConfigurationAsync(currentInstance);

// Create schedule that is active during holiday type 1 (e.g., Company Holidays)
var holidaySchedule = await client.AddScheduleAsync(currentInstance,
    new ScheduleInfo
    {
        CommonName = "HolidayAccess",
        ScheduleDurations = new ScheduleDurationItem[]
        {
            new ScheduleDurationItem
            {
                DayMask = 127,  // All days
                StartingAt = new TimeSpan(8, 0, 0),   // 8:00 AM
                Duration = TimeSpan.FromHours(4),     // 4 hours
                HolidayExceptions = 1  // Active on holidays marked as Type 1
            }
        }
    });

Note: HolidayExceptions uses flag values (1, 2, 4, 8, 16, 32, 64, 128) corresponding to holiday types 1-8. Combine flags to apply to multiple types: HolidayExceptions = 3 (types 1 and 2). When a holiday day matches the exception type, this schedule duration becomes active on that holiday.


Retrieving Existing Schedules

// Get all schedules in the instance
var allSchedules = await client.GetSchedulesAsync(currentInstance);

foreach (var schedule in allSchedules)
{
    Console.WriteLine($"Schedule: {schedule.CommonName}");
    Console.WriteLine($"  Always Active: {schedule.IsAlways}");
    Console.WriteLine($"  Duration Count: {schedule.ScheduleDurations?.Length ?? 0}");
    
    if (schedule.ScheduleDurations != null)
    {
        foreach (var duration in schedule.ScheduleDurations)
        {
            Console.WriteLine($"    Days: {duration.DayMask}, Start: {duration.StartingAt}, Length: {duration.Duration}");
        }
    }
}

// Get specific schedule by name
var specificSchedule = (await client.SearchAsync(currentInstance, "{\"_t_\": \"Schedule\", \"CommonName\":\"StandardBusinessHours\"}"))
    .OfType<ScheduleInfo>().FirstOrDefault();

cURL Examples

Create Weekday Schedule

curl -X POST \
  "https://api.us.acresecurity.cloud/api/f/INSTANCE_KEY/schedules" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "$type": "Feenics.Keep.WebApi.Model.ScheduleInfo, Feenics.Keep.WebApi.Model",
    "CommonName": "StandardBusinessHours",
    "ScheduleDurations": [
      {
        "$type": "Feenics.Keep.WebApi.Model.ScheduleDurationItem, Feenics.Keep.WebApi.Model",
        "DayMask": 62,
        "StartingAt": "09:00:00",
        "Duration": "08:00:00"
      }
    ]
  }'

Create 24/7 Schedule

curl -X POST \
  "https://api.us.acresecurity.cloud/api/f/INSTANCE_KEY/schedules" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "$type": "Feenics.Keep.WebApi.Model.ScheduleInfo, Feenics.Keep.WebApi.Model",
    "CommonName": "AlwaysActive",
    "IsAlways": true
  }'

List All Schedules

curl -X GET \
  "https://api.us.acresecurity.cloud/api/f/INSTANCE_KEY/schedules" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Best Practices

Practice Recommendation
Naming Use descriptive names like “Weekday-9AM-5PM” for easy identification
Midnight Crossing Durations can cross midnight - no need to split into separate items
Always Access Use IsAlways = true for 24/7 instead of creating 127/24hr duration
Holiday Exceptions Use HolidayExceptions flags (1-8) to activate schedules on specific holiday types
Testing Verify DayMask calculations match intended days before deployment
Documentation Add notes to schedules explaining their business purpose

DayMask Calculator

Use this helper method to calculate DayMask values:

public static int CalculateDayMask(
    bool sunday = false,
    bool monday = false,
    bool tuesday = false,
    bool wednesday = false,
    bool thursday = false,
    bool friday = false,
    bool saturday = false)
{
    int mask = 0;
    if (sunday) mask |= 1;
    if (monday) mask |= 2;
    if (tuesday) mask |= 4;
    if (wednesday) mask |= 8;
    if (thursday) mask |= 16;
    if (friday) mask |= 32;
    if (saturday) mask |= 64;
    return mask;
}

// Usage:
int weekdayMask = CalculateDayMask(
    monday: true, 
    tuesday: true, 
    wednesday: true, 
    thursday: true, 
    friday: true
);
// Returns: 62

Troubleshooting

Issue Cause Solution
Schedule not active Wrong DayMask Verify bit values match intended days
Access denied outside hours StartingAt/Duration mismatch Check time calculations, use 24-hour format
Schedule not active on holiday HolidayExceptions not set Set HolidayExceptions flag to match holiday type (1-8)
Overnight access failing Duration too long or DayMask wrong Verify duration crosses midnight correctly, check DayMask for active days
Schedule not found Wrong instance Verify currentInstance context