Application Calendars

Not every scheduling use case is based on access to people’s calendars. As we’ve worked with customers across a range of industries we’ve discovered a number of situations where these customers want to leverage the power of Cronofy’s scheduling API without linking it to a “real” calendar.

Examples we’ve seen include:

  • Interview scheduling for retail store managers
  • Booking meetings at expos
  • Scheduling in-store consultations
  • Tracking assignment of workshop equipment

These, and many other use cases are why we’ve built Application Calendars.

Application Calendars are really a specialized type of Cronofy Account that automatically gets created with one Profile with one Calendar.

  "token_type": "bearer",
  "access_token": {RANDOM_TOKEN},
  "expires_in": 3600,
  "refresh_token": {RANDOM_TOKEN},
  "scope": "read_write",
  "application_calendar_id": "my-unique-string",
  "sub": "apc_567236000909002",
  "linking_profile": {
    "provider_name": "cronofy",
    "profile_id": "pro_n23kjnwrw2",
    "profile_name": "n23kjnwrw2"

You’ll see that it has an access_token and refresh_token to allow interaction with the Application Calendar through any API endpoints that are authorized with User credentials.

The sub value allows you to use this calendar in Availability queries.

Creating an Application Calendar #

As is common with the Cronofy API, you specify the application_calendar_id so it operates as an upsert operation. You can lazily create the calendar as you need it.

curl -v --header "Content-Type: application/json" \
    --data "{\"client_id\": \"{CLIENT_ID}\",\"client_secret\": \"{CLIENT_SECRET}}\",\"application_calendar_id\": \"{APPLICATION_CALENDAR_ID}}\"}" \
cronofy = '{CLIENT_ID}', client_secret: '{CLIENT_SECRET}')

application_calendar = cronofy.application_calendar("{APPLICATION_CALENDAR_ID}")
sub = application_calendar.sub;
var cronofy = new CronofyOAuthClient("{CLIENT_ID}", "{CLIENT_SECRET}");

var applicationCalendar = cronofy.ApplicationCalendar("{APPLICATION_CALENDAR_ID}");
var sub = applicationCalendar.Sub;
var cronofy = new Cronofy({
  client_id: '{CLIENT_ID}',
  client_secret: '{CLIENT_SECRET}'

var options = {
  application_calendar_id: "{APPLICATION_CALENDAR_ID}"

    .then(function (applicationCalendar) {
        var sub = applicationCalendar.sub;
$cronofy = new Cronofy(array("client_id" => "{CLIENT_ID}", "client_secret" => "{CLIENT_SECRET}"));

$application_calendar = $cronofy->application_calendar("{APPLICATION_CALENDAR_ID}");
$sub = $application_calendar['sub'];
cronofy = pycronofy.Client(client_id='{CLIENT_ID}', client_secret='{CLIENT_SECRET}')

application_calendar = cronofy.application_calendar('{APPLICATION_CALENDAR_ID}')
sub = application_calendar['sub']

See Application Calendar docs for more info.

Adding Events to Application Calendars #

The data hierarchy for Application Calendars is the same as for User accounts.

Application Calendar > Profiles > Calendars

In order to create an Event in an Application Calendar you need to obtain the calendar_id for the Calendar. Application Calendars only have one Profile and one Calendar.

The List Calendars endpoint allows you to get access to this.

ACCESS_TOKEN is the access_token value for the Application Calendar you’ve created.

curl -v --header "Authorization: Bearer {ACCESS_TOKEN}" \
cronofy = '{ACCESS_TOKEN}')

calendars = cronofy.list_calendars
calendar_id = calendars.first.calendar_id
var cronofy = new CronofyAccountClient("{ACCESS_TOKEN}");

var calendars = cronofy.GetCalendars();
var calendar_id = calendars.First().CalendarId;
var cronofy = new Cronofy({
  access_token: '{ACCESS_TOKEN}'

    .then(function (response) {
        var calendar_id = response.calendars[0].calendar_id;
$cronofy = new Cronofy('', '', '{ACCESS_TOKEN}', '');

$calendars = $cronofy->list_calendars();
$calendar_id = reset($calendars)[0]['calendar_id'];
cronofy = pycronofy.Client(access_token="{ACCESS_TOKEN}")

calendars = cronofy.list_calendars()
calendar_id = calendars[0]['calendar_id']

This will give you a response similar to this.

  "calendars": [
      "provider_name": "cronofy",
      "profile_id": "pro_n23kjnwrw2",
      "profile_name": "n23kjnwrw2",
      "calendar_id": "cal_n23kjnwrw2_jsdfjksn000",
      "calendar_readonly": false,
      "calendar_deleted": false

You can then create an Event by using the ACCESS_TOKEN value for the Application Calendar and the calendar_id for the Calendar.

curl -v --header "Authorization: Bearer {ACCESS_TOKEN}" \
    --header "Content-Type: application/json" \
    --data "{\"event_id\": \"qTtZdczOccgaPncGJaCiLg\",\"summary\": \"Board meeting\",\"description\": \"Discuss plans for the next quarter.\",\"start\": \"2021-01-28T15:30:00Z\",\"end\": \"2021-01-28T17:00:00Z\",\"location\": {\"description\": \"Board room\"}}" \{CALENDAR_ID}/events
cronofy = '{ACCESS_TOKEN}')
new_event = {
  event_id: "qTtZdczOccgaPncGJaCiLg",
  summary: "Board meeting",
  description: "Discuss plans for the next quarter.",
  start: Time.parse("2021-01-28T15:30:00Z"),
  end: Time.parse("2021-01-28T17:00:00Z"),
  location: {
    description: "Board room"

cronofy.upsert_event(calendar_id, new_event)
var cronofy = new CronofyAccountClient("{ACCESS_TOKEN}");
var eventBuilder = new UpsertEventRequestBuilder()
                        .Summary("Event summary")
                        .Description("Event description")
                        .Start(2021, 1, 28, 17, 00)
                        .End(2021, 1, 28, 17, 30)
                        .Location("Meeting room");

cronofy.UpsertEvent(calendarId, eventBuilder);
var options = {
    access_token: '{ACCESS_TOKEN}',
    event_id: "qTtZdczOccgaPncGJaCiLg",
    summary: "Board meeting",
    description: "Discuss plans for the next quarter.",
    start: "2021-01-28T15:30:00Z",
    end: "2021-01-28T17:00:00Z",
    location: {
        description: "Board room"

    .then(function () {
        // Success
$cronofy = new Cronofy('', '', '{ACCESS_TOKEN}', '');

$params = array(
    'calendar_id' => $calendarId,
    'event_id' => 'qTtZdczOccgaPncGJaCiLg',
    'summary' => 'Board meeting',
    'description' => 'Discuss plans for the next quarter.',
    'start' => '2021-01-28T15:30:00Z',
    'end' => '2021-01-28T17:00:00Z'

import pycronofy

cronofy = pycronofy.Client(access_token="{ACCESS_TOKEN}")
event = {
    'event_id': "qTtZdczOccgaPncGJaCiLg",
    'summary': "Board meeting",
    'description': "Discuss plans for the next quarter.",
    'start': "2021-01-28T15:30:00Z",
    'end': "2021-01-28T17:00:00Z",
    'location': {
        'description': "Board room"
cronofy.upsert_event(calendar_id=calendar_id, event=event)

Also see docs for the Upsert Events endpoint

Using Application Calendars with scheduling functions #

As Application Calendars are a specialized version of a standard Cronofy Account, they can be used in exactly the same way as Cronofy Accounts in Availability queries.

You can treat them as members in Availability queries alongside User and Resource accounts.

  "participants": [
      "members": [
        { "sub": "apc_567236000909002" },
        { "sub": "acc_678347111010113" }
      "required": "all"
  "required_duration": { "minutes": 60 },
  "available_periods": [
      "start": "2021-01-28T09:00:00Z",
      "end": "2021-01-28T18:00:00Z"
      "start": "2021-01-29T09:00:00Z",
      "end": "2021-01-29T18:00:00Z"

You can assign Availability Rules and Available Periods using the access_token for the Application Calendar.

You can use the Availability Query to drive Real-Time Schedulng links.

UI Elements #

They are also fully supported by UI Elements. You generate an element_token in exactly the same way. Passing the sub value for the Application Calendar.

POST /v1/element_tokens HTTP/1.1

Authorization: Bearer {API_KEY}
Content-Type: application/json

  "version": "1",
  "permissions": ["agenda"],
  "subs": ["apc_567236000909002"],
  "origin": "http://localhost"

Summary #

Application Calendars allow you to leverage all of the power of Cronofy’s rich scheduling features and UI elements without needing a “real” calendar to act as the data store.

They are designed to be used as drop in replacements for, or to work alongside User and Resource Accounts. Greatly extending the scheduling use cases you can support.

To understand how Application Calendars work in relation to Accounts and Billing please review the Application Calendar FAQ.

For any questions or to let us know what you’re building with Application Calendars, just email