Controlling Available Periods with a sub calendar
Required plan: EmergingAvailable Periods are part of Cronofy’s Managed Availability suite of features. They allow you to record specific times that user’s are available and have them automatically included whenever that user is included in an Availability query.
One option for allowing users to control their availablity is to link Available Periods to events in a sub calendar. We’re not currently recommending this as an approach but several customers are experimenting with this so we thought we’d share how to approach it.
1. Create a Sub Calendar #
First, you will need the profile_id
for the calendar account to create the calendar in.
curl -v -G --header "Authorization: Bearer {ACCESS_TOKEN}" \
-d 'tzid=Etc/UTC' https://api.cronofy.com/v1/profiles
cronofy = Cronofy::Client.new(access_token: '{ACCESS_TOKEN}')
profiles = cronofy.list_profiles
Then you can create the calendar in that profile.
curl -v --header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--data "{\"profile_id\": \"{PROFILE_ID}\",\"name\": \"Availability\"}" \
https://api.cronofy.com/v1/calendars
cronofy = Cronofy::Client.new(access_token: '{ACCESS_TOKEN}')
calendar = cronofy.create_calendar("{PROFILE_ID}", "Availability")
calendar_id = calendar.calendar_id
Track the calendar_id
of the new calendar as you’ll need that for the next step.
2. Setup Push Notification Channel #
You now need to create a channel to receive notications of any changes to events in that calendar.
The callback_url
can be any public URL that Cronofy can post to. You will want to include any parameters in this URL to allow you to identify the user it relates to, eg a user id or similar. This will allow you to look up the access_token
for the user to perform the updates required when ever something changes.
curl -v --header "Authorization: Bearer {ACCESS_TOKEN}" \
--header "Content-Type: application/json" \
--data "{\"callback_url\": \"{CALLBACK_URL}\",\"filters\": { \"calendar_ids\": [ \"{CALENDAR_ID}\" }}" \
https://api.cronofy.com/v1/channels
cronofy = Cronofy::Client.new(access_token: '{ACCESS_TOKEN}')
cronofy.create_channel("{CALLBACK_URL}", { calendar_ids: [ calendar_id ] })
3. Process Change Notifications #
The standard pattern for processing notifications comes into play here. Your app will receive notifications similar to the following.
POST {CALLBACK_URL_PATH} HTTP/1.1
Host: {CALLBACK_URL_HOST}
Content-Type: application/json; charset=utf-8
{
"notification": {
"type": "change",
"changes_since": "2024-11-12T07:24:16Z"
},
"channel": {
"channel_id": "chn_54cf7c7cb4ad4c1027000001",
"callback_url": "{CALLBACK_URL}",
"filters": {}
}
}
The key value here is the changes_since
parameter. You pass this to the Read Events endpoint as the last_modified
parameter to retrieve the events that have changed.
curl -v -G --header "Authorization: Bearer {ACCESS_TOKEN}" \
-d 'tzid=Etc/UTC' https://api.cronofy.com/v1/events?last_modified={CHANGES_SINCE}&calendar_ids[]={CALENDAR_ID}&include_deleted=1&include_moved=1
cronofy = Cronofy::Client.new(access_token: '{ACCESS_TOKEN}')
options = {
last_modified: {CHANGES_SINCE},
calendar_ids: [ {CALENDAR_ID} ],
include_deleted: true,
include_moved: true
}
events = cronofy.read_events(options)
You then iterate over the events and either upsert or delete Available Periods.
events.each do |event|
if event.deleted
cronofy.delete_available_period(event.event_uid)
else
period = {
available_period_id: event.event_uid,
start: event.start,
end: event.end
}
cronofy.upsert_available_period(period)
end
end
Because Cronofy is using an upsert pattern that allows you to specify the available_period_id
, just using the event.event_uid
value means there is no state to be stored. Your code can just deal with each change as it appears.
4. Use in Availability Queries #
You can then enable the Managed Availability features for any user you have set up for this kind availability tracking.