Real-Time Scheduling

Required plan: Emerging

Description #

Returns a URL to a form where a user can select their preferred date and time for an event based upon live availability information.

URL format #

{data_center_url}/v1/real_time_scheduling

Example Request #

POST /v1/real_time_scheduling HTTP/1.1
Host: {data_center_url}
Authorization: Bearer {API_KEY}
Content-Type: application/json; charset=utf-8

{
  "oauth": {
    "redirect_uri": "{REDIRECT_URI}",
  },
  "event": {
    "event_id": "qTtZdczOccgaPncGJaCiLg",
    "summary": "Product Manager Interview at Globex",
    "tzid": "Europe/London"
  },
  "availability": {
    "participants": [
      {
        "members": [
          {
            "sub": "acc_5ba21743f408617d1269ea1e",
            "calendar_ids": ["cal_n23kjnwrw2_jsdfjksn234"]
          }
        ],
        "required": "all"
      }
    ],
    "required_duration": { "minutes": 60 },
    "query_periods": [
      { "start": "2024-07-27T09:00:00Z", "end": "2024-07-27T18:00:00Z" }
    ]
  },
  "target_calendars": [
    {
      "sub": "acc_5ba21743f408617d1269ea1e",
      "calendar_id": "cal_n23kjnwrw2_jsdfjksn234"
    }
  ],
  "callback_urls": {
    "completed_url": "http://www.example.com/callback",
    "no_times_suitable_url": "http://www.example.com/callback"
  },
  "redirect_urls": {
    "completed_url": "http://www.example.com/success"
  },
  "selection_mode": "no_confirm"
}

Example Response #

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "real_time_scheduling": {
    "real_time_scheduling_id": "sch_64b1859e8090ea21640c915f",
    "url": "{REAL_TIME_SCHEDULING_URL}"
  }
}

Request parameters #

data_center_url required

The URL for the data center you want to communicate with. Possible choices are:

  • api-au.cronofy.com - πŸ‡¦πŸ‡Ί Australia
  • api-ca.cronofy.com - πŸ‡¨πŸ‡¦ Canada
  • api-de.cronofy.com - πŸ‡©πŸ‡ͺ Germany
  • api-sg.cronofy.com - πŸ‡ΈπŸ‡¬ Singapore
  • api-uk.cronofy.com - πŸ‡¬πŸ‡§ United Kingdom
  • api.cronofy.com - πŸ‡ΊπŸ‡Έ United States

Find out more about Cronofy's data centers.

API_KEY required  #

The client_secret of the client.

oauth.redirect_uri required  #

The HTTP or HTTPS URI you wish the user to be redirected to after their Real-Time Scheduling journey.

event required  #

An object with the details of the event you wish to push into the user’s selected calendar. Details of what parameters this object can hold can be found in the create or update event documentation.

Note:

  • event.attendees are only supported when event_creation is set to single.
  • event.conferencing only supports built-in values. You may reference specific conferencing profiles for different organizers within the target_calendars.event.conferencing parameter.
  • Attachments and Subscriptions are supported as normal.
  • When a group requires only some of the members, the order the members are listed in will be used as a soft-preference for who is selected. If you want to evenly distribute events to members across several tokens, you should shuffle this list so each request has the members in a random order.
event.tzid required  #

The time zone to render the event with.

The start and end parameters should be omitted.

availability required  #
An object with the details of the availability query used to determine the available time periods for the user to choose for the event’s date and time. Details of what parameters this object can hold can be found in the Availability documentation.

availability.start_interval and availability.response_format both have an impact on the possible slots presented to the user and are discussed below.

availability.start_interval optional  #

A Duration describing the frequency that a sequence can start on.

For example, “every hour” or “every 15 minutes”.

Must be an increment of one of 5, 10, 15, 20, 30, or 60 minutes.

By default Real Time Scheduling will use the required duration to derive the interval of slots. For example, 60 minute slots will begin on the hour

  • 9:00am – 10:00am
  • 10:00am – 11:00am
  • 11:00am – 12:00pm

This works well when a calendar is mostly free, however if an hour-long meeting at 9:30am - 10:30am is scheduled we would only have the 11am slot available.

  • 9:00am – 10:00am
  • 10:00am – 11:00am
  • 11:00am – 12:00pm

To avoid this problem, we can set the slots to begin every 30 minutes for the same period of time would mean the following would be selectable.

  • 9:00am – 10:00am
  • 9:30am – 10:30am
  • 10:00am – 11:00am
  • 10:30am – 11:30am
  • 11:00am – 12:00pm
availability.response_format optional  #

A String which controls the generation of available slots. Can be one of the following values:

  • slots - Default, slots are considered per availability.start_interval but won’t overlap
  • overlapping_slots - slots are considered per availability.start_interval and can overlap
minimum_notice optional  #

A Duration. No slots starting before the period described after the current time will be displayed to the user when they select slots.

event_creation optional BETA  #

One of two values:

  • default or omitted - creates an event in each calendar listed in the target_calendars list.
  • single - creates an event in one target calendar - if multiple target_calendars are a match for the selected slot, then the order of the participants in the availability query is used to choose the preferred calendar.

You can use this capability along with event.attendees and target_calendars.attendee to set a primary event owner and set all other people as event attendees.

Please see the fully worked example below.

target_calendars optional  #

An array of mappings between Cronofy sub values and calendar IDs into which the final event will be inserted, along with other per-account event overrides.

Required for Cronofy to create events.

target_calendars.sub required  #

The internal Cronofy ID for the account, as an ASCII-only String.

target_calendars.calendar_id required  #

The calendar_id of the calendar you wish the event to be added to. This ID should belong to one of the profiles attached to the account identified by the sub.

target_calendars.attendee optional  #

Required for the account to be added to an event as an attendee based on presence in the result of the Availability Query.

Only used, and only allowed, when event_creation is set to single.

target_calendars.attendee.email required  #

The email address associated with the attendee as a String.

target_calendars.attendee.display_name optional  #

A human-friendly name associated with the attendee as a String, may be null.

target_calendars.event optional  #

Overrides to the event template used when the account is selected as the organizer of the event.

Only used, and only allowed, when event_creation is set to single.

target_calendars.event.conferencing optional  #

You may override the conferencing for the event on a per-organizer basis. This allows you to have multiple potential event organizers, each with their own personal conferencing profile. The format follows the format used when specifying conferencing on an event.

formatting.hour_format optional  #

A String of either h (12-hour format) or H (24-hour format). If omitted then the hour format to use will be determined by Cronofy.

callback_url optional  #

Deprecated. An alias for callback_urls.completed_url.

callback_urls.completed_url optional  #

A URL to call when a slot has been chosen and the full event details are known.

callback_urls.no_times_displayed_url optional  #

A URL to call when the user was shown a page with no available times.

callback_urls.no_times_suitable_url optional  #

A URL to call when the user indicates that none of the available times are suitable for them.

redirect_urls.completed_url optional  #

A URL to redirect the user to when the user has completed the process and chosen a slot.

A query string parameter of token will be added to this URL. The token can be used to retrieve the current status of a Real Time Scheduling link.

selection_mode optional  #

A String indicating how users select their time slot. Supports the following options:

  • no_confirm (Default) - Selecting a time books the event immediately
  • confirm - The user is taken to a confirmation page after selecting a time, before the event is booked

Response parameters #

real_time_scheduling.real_time_scheduling_id  #

The Cronofy unique identifier for the Real Time Scheduling link.

real_time_scheduling.url  #

The URL to direct the user to in order to authorize their calendar account and have the event inserted into their selected calendar.

Callback notifications #

Example Time Chosen callback
POST {CALLBACK_URL_PATH} HTTP/1.1
Host: {CALLBACK_URL_HOST}
Content-Type: application/json; charset=utf-8
Cronofy-HMAC-SHA256: {Base64(HmacSHA256(body_bytes, CLIENT_SECRET))}

{
  "notification": {
    "type": "real_time_scheduling_time_chosen"
  },
  "user": {
    "tzid": "Europe/Paris"
  },
  "event": {
    "event_id": "qTtZdczOccgaPncGJaCiLg",
    "start": {
      "time": "2024-07-27T10:00:00Z",
      "tzid": "Europe/London"
    },
    "end": {
      "time": "2024-07-27T11:00:00Z",
      "tzid": "Europe/London"
    },
    "summary": "Product Manager Interview at Globex"
  },
  "participants": [
    { "sub": "acc_5ba21743f408617d1269ea1e" }
  ]
}
Example No Times Displayed callback
POST {CALLBACK_URL_PATH} HTTP/1.1
Host: {CALLBACK_URL_HOST}
Content-Type: application/json; charset=utf-8
Cronofy-HMAC-SHA256: {Base64(HmacSHA256(body_bytes, CLIENT_SECRET))}

{
  "user": {
    "tzid": "Europe/Paris"
  },
  "notification": {
    "type": "real_time_scheduling_no_times_displayed"
  }
}
Example No Times Suitable callback
POST {CALLBACK_URL_PATH} HTTP/1.1
Host: {CALLBACK_URL_HOST}
Content-Type: application/json; charset=utf-8
Cronofy-HMAC-SHA256: {Base64(HmacSHA256(body_bytes, CLIENT_SECRET))}

{
  "user": {
    "tzid": "Europe/Paris"
  },
  "notification": {
    "type": "real_time_scheduling_no_times_suitable"
  }
}

Callback request headers #

Cronofy-HMAC-SHA256  #

Can optionally be used to verify that the notification was sent by Cronofy.

This HMAC uses the SHA256 algorithm, keyed with the application's client secret, to generate a Base64 encoded hash of the request body.

When an application has multiple active client secrets, a value is generated for each active secret, separated by commas. For example:

Cronofy-HMAC-SHA256: {HMAC_FROM_SECRET_1},{HMAC_FROM_SECRET_2}

Examples are available in our cronofy/notification-hmac-examples Github repository, and our API libraries include methods to verify this header.

Callback request parameters #

notification.type  #

A value of indicating the reason for the notification.

One of:

  • real_time_scheduling_no_times_displayed
  • real_time_scheduling_no_times_suitable
  • real_time_scheduling_time_chosen
user.tzid optional  #

An parameter that indicates the time zone of the user that triggered the callback, or the time zone that we were able to automatically detect for the user.

event optional  #

An object with the details of the event created by an available time slot being selected. Details of what parameters this object can hold can be found in the create or update event documentation.

Only provided with real_time_scheduling_time_chosen notifications.

participants optional  #

An array of all the participants which were selected for the event based on their availability.

Only provided with real_time_scheduling_time_chosen notifications.

Localization #

The scheduling page displayed when a user navigates to the Real Time Scheduling URL will detect the user’s browser locale and render accordingly.

Currently supported locales are:

  • ar Arabic
  • cs Czech
  • cy Welsh
  • de German
  • en US English (default)
  • es Spanish
  • fr French
  • fr-CA Canadian French
  • he Hebrew
  • it Italian
  • ja Japanese
  • nl Dutch
  • pl Polish
  • pt-BR Brazilian Portuguese
  • ru Russian
  • sv Swedish
  • tr Turkish
  • zh-CN Simplified Chinese

Use of one of the supported locales can be forced by adding a locale query string parameter to the Real Time Scheduling URL, for example:

https://app.cronofy.com/add_to_calendar/scheduling/p6Ht4P6_4svo1nrjpIY738bdfk?locale=de

Event creation example #

Scenario

You wish to provide a booking page for an interview:

  • The candidate is known by email but not synchronized in Cronofy. They’ll be sent the URL to select a time.
  • The recruitment panel contains three members, of which two are required to perform the interview.
  • Each interviewer has their own preference for conferencing.
Payload
POST /v1/real_time_scheduling HTTP/1.1
Host: {data_center_url}
Authorization: Bearer {API_KEY}
Content-Type: application/json; charset=utf-8

{
  "oauth": {
    "redirect_uri": "{REDIRECT_URI}"
  },
  "event_creation": "single",
  "event": {
    "event_id": "ri4vch-45fsd",
    "summary": "Interview panel stage",
    "tzid": "Europe/London",
    "attendees": {
      "invite": [
        {
          "email": "candidate@example.com",
          "display_name": "Jim Candidate"
        }
      ]
    }
  },
  "availability": {
    "participants": [
      {
        "members": [
          {
            "sub": "acc_5e591ae2815c14f86ea55caf"
          },
          {
            "sub": "acc_61092b71f5aa93c71280b010"
          },
          {
            "sub": "acc_61115004f5aa93bb48fc5dd3"
          }
        ],
        "required": 2
      }
    ],
    "required_duration": {
      "minutes": 60
    },
    "available_periods": [
      {
        "start": "2024-07-27T09:00:00Z",
        "end": "2024-07-27T18:00:00Z"
      }
    ]
  },
  "target_calendars": [
    {
      "sub": "acc_5e591ae2815c14f86ea55caf",
      "calendar_id": "cal_Xlka34FcFPhupVxZ_K@fbCQqIXfoVEHSVR06mpg",
      "event": {
        "conferencing": {
          "profile_id": "pro_YABpIfWqk4wjcW5t"
        }
      },
      "attendee": {
        "email": "marty@evenitron.com",
        "display_name": "Marty McFly"
      }
    },
    {
      "sub": "acc_61092b71f5aa93c71280b010",
      "calendar_id": "cal_YQkrbPWqk8cSgLAG_o@ZiqDLP1-zjzDl6zhXwFg",
      "event": {
        "conferencing": {
          "profile_id": "integrated"
        }
      },
      "attendee": {
        "email": "doc@evenitron.com",
        "display_name": "Doc Brown"
      }
    },
    {
      "sub": "acc_61115004f5aa93bb48fc5dd3",
      "calendar_id": "cal_YRFQA@Wqk7tI@F3J_3X4Nll-hxnkdz-wlOTkhIw",
      "event": {
        "conferencing": {
          "profile_id": "integrated"
        }
      },
      "attendee": {
        "email": "sarah@evenitron.com",
        "display_name": "Sarah Connor"
      }
    }
  ],
  "redirect_urls": {
    "completed_url": "https://www.example.com/success"
  }
}
Notes

Taking each section in turn:

  • "event_creation": "single" instructs Cronofy to create a single event in one calendar, and add others as attendees to that event.
  • In the event, the candidate is listed as an attendee. They will always be invited to the created event as a result.
  • availability defines the parameters of valid slot choices. The event will be one hour long. Two out of three possible interviewers are required, listed in the members array.
    • We will present slots where any two are available. One interviewer will be selected as the organizer of the event, and the other interviewer will be added as an attendee.
  • target_calendars lists the same interviewers as present in availability. It defines:
    • Which of their calendars the event will be placed in if they are selected as the event organizer (calendar_id)
    • Overrides to the event if they are selected as the event organizer - allowing each interviewer to specify their own conferencing solution (event.conferencing)
    • How the interviewer is added to the event as an attendee if they are included in, but not the organizer of, the created event. (attendee)

In This Section