Availability Query

Required plan: Emerging

Description #

Inspects calendars to determine the common availability for people within the specified periods of time.

URL format #

{data_center_url}/v1/availability

Example Request #

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

{
  "participants": [
    {
      "members": [
        {
          "sub": "acc_5ba21743f408617d1269ea1e",
          "managed_availability": true
         },
        {
          "sub": "acc_64b17d868090ea21640c914c",
          "managed_availability": true
        }
      ],
      "required": "all"
    },
    {
      "members": [
        { "sub": "res_5ba21743f408617d12693521" },
        { "sub": "res_5ba21743f4000563a26934ea" },
        { "sub": "res_64b17d868090ea21640ad6e0" }
      ],
      "required": 1
    }
  ],
  "required_duration": { "minutes": 60 },
  "query_periods": [
    {
      "start": "2024-10-14T09:00:00Z",
      "end": "2024-10-14T18:00:00Z"
    },
    {
      "start": "2024-10-15T09:00:00Z",
      "end": "2024-10-15T18:00:00Z"
    }
  ],
  "buffer": {
    "before": { "minutes": 30 },
    "after": { "minutes": 15 }
  },
  "response_format": "slots"
}

Example Response #

Slots #

When a response_format of slots or overlapping_slots is specified, the response looks like this.

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

{
  "available_slots": [
    {
      "start": "2024-10-14T09:00:00Z",
      "end": "2024-10-14T10:00:00Z",
      "participants": [
        { "sub": "acc_5ba21743f408617d1269ea1e" },
        { "sub": "acc_64b17d868090ea21640c914c" },
        { "sub": "res_5ba21743f408617d12693521" },
        { "sub": "res_5ba21743f4000563a26934ea" }
      ]
    },
    {
      "start": "2024-10-15T10:00:00Z",
      "end": "2024-10-15T11:00:00Z",
      "participants": [
        { "sub": "acc_5ba21743f408617d1269ea1e" },
        { "sub": "acc_64b17d868090ea21640c914c" },
        { "sub": "res_64b17d868090ea21640ad6e0" }
      ]
    },
    {
      "start": "2024-10-15T11:00:00Z",
      "end": "2024-10-15T12:00:00Z",
      "participants": [
        { "sub": "acc_5ba21743f408617d1269ea1e" },
        { "sub": "acc_64b17d868090ea21640c914c" },
        { "sub": "res_64b17d868090ea21640ad6e0" }
      ]
    }
  ]
}

Periods #

The default response_format of periods looks like this.

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

{
  "available_periods": [
    {
      "start": "2024-10-14T09:00:00Z",
      "end": "2024-10-14T11:00:00Z",
      "participants": [
        { "sub": "acc_5ba21743f408617d1269ea1e" },
        { "sub": "acc_64b17d868090ea21640c914c" },
        { "sub": "res_5ba21743f4000563a26934ea" }
      ]
    },
    {
      "start": "2024-10-15T11:00:00Z",
      "end": "2024-10-15T17:00:00Z",
      "participants": [
        { "sub": "acc_5ba21743f408617d1269ea1e" },
        { "sub": "acc_64b17d868090ea21640c914c" },
        { "sub": "res_64b17d868090ea21640ad6e0" }
      ]
    }
  ]
}

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.

response_format optional  #

This can be one of the following values:

  • periods
  • slots
  • overlapping_slots

When not specified, and providing query_periods, the default response format is periods. In this case, response_format works in conjunction with start_interval to control the distribution of the periods/slots.

periods will generate contiguous available periods that are a minimum length of the required_duration.

slots will generate non-overlapping slots with length equal to the required_duration.

overlapping_slots will generate slots starting every start_interval irrespective of whether they overlap with length equal to the required_duration.

When using query_slots instead of query_periods, we’ll always consider all provided slots, effectively behaving like overlapping_slots. periods is an invalid value in this case.

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

{
  ...
  "response_format": "overlapping_slots",
  "required_duration": { "minutes": 60 },
  "query_periods": [
    {
      "start": "2024-10-14T09:00:00Z",
      "end": "2024-10-14T18:00:00Z"
    }
  ],
  "start_interval": { "minutes": 30 }
}

This query will consider 1-hour slot times starting every 30 minutes, with the first slot being at 9AM UTC, then 9:30AM UTC, and so on - with the last slot being at 5PM UTC. Any of those slots would be returned, if available.

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

{
  ...
  "required_duration": { "minutes": 60 },
  "query_slots": [
    { "start": "2024-10-14T09:00:00Z" },
    { "start": "2024-10-14T10:00:00Z" },
    { "start": "2024-10-14T13:30:00Z" },
    { "start": "2024-10-14T14:30:00Z" }
  ]
}

This will return, at most, four 1-hour slots starting at the specified times, avoiding the need to use a complex combination of query_periods and start_interval, or post-processing of the response, to achieve the same result. No other slot times would be considered or returned.

participants required  #

An array of the groups of participants whose availability should be taken into account.

At least one group must be specified, a maximum of 10 accounts may be specified over a combination of groups.

participants.members required  #

An array of participants that should have their availability taken into account as part of this group.

At least one participant must be specified and you must have been granted the read_free_busy scope for each participant involved in the availability request.

Note that the read_events scope implicitly includes this scope as it allows access to a higher level of information than free-busy so you do not have to have both.

participants.members.sub required  #

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

This can be retrieved by calling the UserInfo endpoint with a valid access_token

participants.members.available_periods optional  #

An array of 1 to 50 available periods within which the member is available. If omitted it is assumed the member is available whenever they do not have a “busy” event in their calendar.

participants.members.available_periods.start  #

Thestart of an available period as a Time.

It must represent a future point in time.

participants.members.available_periods.end  #

Theend of an available period as a Time.

Must be at least 1 minute after the corresponding start and within 35 days of the earliest start.

participants.members.calendar_ids optional  #

Restricts the events contributing towards the members availability to those within the set of specified calendar_ids.

Calendars are chosen for each member in this order of precedence:

  • if this property is present, then only the calendars specified are used. If an empty array is specified then no calendars are chosen and all events in the participants calendars are ignored.
  • else, if managed_availability is true for the member, the calendars from the relevant Availability Rule(s) are used
  • else, all calendars for the member are considered
participants.members.buffer optional  #

Buffer values specific to this member. If specified are used instead of any top-level buffer when considering the member’s availability.

participants.members.buffer.before optional  #

A Duration specifying the minimum number of minutes that must be free for this member before an available period starts.

participants.members.buffer.after optional  #

A Duration specifying the minimum number of minutes that must be free for this member after the available period ends.

participants.members.availability_constraints optional  #

An Array of constraints that must be satisfied for each slot or period.

participants.members.availability_constraints.period required  #

A String value specifying the time period over which the constraint is to be applied.

You can specify one of the following values:

  • day will apply the constraint each day. You must also pass the tzid parameter to indicate which timezone you want to use to determine when a day starts and ends.
  • week will apply the constraint over the period of a week. A week is considered to be Monday to Sunday in the UTC time zone, following the ISO standard.
participants.members.availability_constraints.tzid optional  #

A String value specifying the time zone to use when the period is set to day. Must be a known time zone identifier from the IANA Time Zone Database. See the time zones page for more information.

Currently specifying a time zone is only supported with the day constraint period.

participants.members.availability_constraints.limit required  #

An Integer value specifying the maximum number of events allowable per period. If tags are provided then limit will only consider events with all of the given tags.

participants.members.availability_constraints.tags optional  #

An Object describing zero or more contextual Tag values to search for against each event when searching for availability. If more than one tag is provided the events must have all of the specified tags to be considered.

Tags may be treated as an empty set by omitting the tags field, setting it to null, the empty object {}, or leaving the context as an empty array { "private": [] }.

The context of “private”, as seen in the example below, is the only context currently supported.

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

{
  "participants":[{
      "members":[
        {
          "sub": "acc_5ba21743f408617d1269ea1e",
          "availability_constraints":[{
            "tags": {
              "private": [
                { "value": "Interview" }
              ]
            },
            "limit": 3,
            "period": "week"
          }]
        },
      ],
      "required": 1
  }],
  "required_duration": { "minutes": 30 },
  "query_periods": [
    {
      "start": "2024-10-14T09:00:00Z",
      "end": "2024-10-14T18:00:00Z"
    },
    {
      "start": "2024-10-15T09:00:00Z",
      "end": "2024-10-15T18:00:00Z"
    }
  ]
}

Tags on events are managed via the create or update event endpoint.

participants.members.managed_availability optional  #

A Boolean specifying whether managed availability should be taken into account for this member.

participants.members.only_managed_events optional  #

A Boolean specifying whether to to only consider events that you are managing when determining busy times for this member. Defaults to false.

participants.members.ignore_tentative optional  #

A Boolean specifying whether events where the user is marked as tentatively attending will be considered as free periods or not. By default these events are considered as busy periods.

participants.members.availability_rule_ids optional  #

An Array of availability_rule_id values referencing Availability Rules stored against the Account.

If not specified or set to null, all availability rules stored against the Account will be used.

If an empty Array is specified, ie [] then all availability rules stored against the Account will be ignored.

participants.required required  #

Either a String of all to specify that all members of the group need to be available for a period to be viable, or an Integer to specify the minimum number of the group that must be available.

required_duration required  #

A Duration describing the minimum period that the participant groups must be satisfied for a period to be deemed as available.

Must be greater than zero minutes in length.

query_periods optional  #

An array of 1 to 50 query periods, across up to 35 days of the period of synchronized events, within which suitable matches may be found.

query_periods.start required  #

The start of a query period as a Time.

It must represent a future point in time.

query_periods.end required  #

The end of a query period as a Time.

Must be at least 1 minute after the corresponding start and within 35 days of the earliest start.

query_slots optional  #

An array of 1 to 50 slot times, across up to 35 days of the period of synchronized events, within which suitable matches may be found.

This is an alternative to specifying query_periods, giving you more control over the exact slot times considered.

query_slots.start required  #

The start of a query slot as a Time.

It must represent a future point in time. The end is unspecified, as it is implicit based on the value of the required_duration parameter.

available_periods alias  #

This is an alias for query_periods to maintain backwards compatibility. available_periods is the original name for query_periods and both represent the same concept, but query_periods makes the intent clearer.

We will not remove support for using available_periods but it is recommended to use query_periods.

buffer.before optional  #

A Duration specifying the minimum number of minutes that must be free before the available period starts.

buffer.after optional  #

A Duration specifying the minimum number of minutes that must be free after the available period ends.

start_interval optional  #

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

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

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

This value is only relevant when using query_periods, and is ignored when query_slots are passed instead.

max_results optional  #

An Integer describing the maximum number of available periods or slots to return from the query.

Must be between 1 and 512 inclusive. If not provided up to 20 results will be returned.

include_member_statuses optional  #

A Boolean specifying if you want members’ synchronization status to be returned in the response.

Sync statuses are returned in an additional member_statuses top level key on the response and include all of the members participating in the Availability Query.

This is useful to ensure the returned availability is based on the most up-to-date calendar data for the member.

See the description of the possible values below.

excluded_events optional  #

An array of objects describing events that should not be considered during the Availability calculation.

{
  ...
  "excluded_events": [
    { "event_id": "interview_123" },
    { "event_uid": "evt_external_64f758b2707e9e455c32e9e" },
  ]
}

Each item must specify either event_id for a Managed Event or the event_uid of an External Event (you can learn more about the difference between these here).

If the specified events appear in any of the calendars queried, they will not block time from being considered as Available.

This is useful for operations such as querying to reschedule a meeting, where omitting the current event representing the meeting may make some additional slots available. It can also be used to customize your query based on context, such as allowing a query for an important customer meeting to ignore several reschedulable internal meetings.

Response parameters #

available_periods  #

An array of available periods that match the criteria specified in the request.

Up to 20, or the value specified for max_results, periods will be returned with preference being towards the soonest matches.

available_periods.start  #

Thestart of an available period as a Time.

available_periods.end  #

Theend of an available period as a Time.

available_periods.participants  #

An array of participants that are available for the given period.

available_periods.participants.sub  #

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

member_statuses  #

An array of each of the participants in the query, and their synchronization status. Only returned when passing true in the include_member_statuses request parameter.

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

{
  ...
  "member_statuses": [
    {
      "sub": "acc_64b17d868090ea21640c914c",
      "sync_status": "active"
    },
    {
      "sub": "acc_61815038636bd5c5ce4edd14",
      "sync_status": "pending"
    },
    {
      "sub": "acc_64b186438090ea21640c9160",
      "sync_status": "disconnected"
    }
  ]
}
member_statuses.sync_status  #

The current synchronization status as a String.

If a member has multiple calendar profiles authorized on their account and are participating in the query, this value represents the worst (least connected) profile.

The possible values are:

  • active - their calendar is syncing and the query has used an up-to-date view of their availability.
  • pending - the initial sync of their calendar has not completed yet, so the query cannot consider a their full availability yet. The query has run based on the data available.
  • disconnected - their calendar profile is disconnected (usually due to expired credentials, awaiting relinking), so the query has run on the most recent data held and cannot guarantee a complete picture of their availability.
  • hibernated - your authorization to their Account is currently in a hibernated state. Including this Account in the query will trigger all Profiles for this Account to be fully synced. You can then reattempt the Availability query to get up to date calendar information.

Error responses #

401 Unauthorized #

The request was refused as the provided authentication credentials were not recognized.

Note that whilst many accounts can be part of the availability request that authentication is performed via theaccess_token for only one of them.

When an OAuthrefresh_token is available then it should be used to request a replacement auth_token before the request is retried.

402 Payment Required #

The request was refused as your plan does not include the required feature.

422 Unprocessable #

The request was unable to be processed due to it containing invalid parameters.

The response will contain a JSON object containing one or more errors relating to the invalid parameters.

For example, if you omitted the required required_duration parameter, you would receive a response like:

{
  "errors": {
    "required_duration": [
      {
        "key": "errors.required",
        "description": "required"
      }
    ]
  }
}

The key field is intended for programmatic use and the description field is a human-readable equivalent.

Common validation errors

  • invalid_time_format - not a recognized time format. available_periods.start and available_periods.end must be ISO 8601 compliant Time strings.
  • invalid_time_pair - end must be after start.
  • max_date_exceeded - date is too far in the future. available_periods must be less than or equal to 201 days in the future.
  • min_date_exceeded - date is too far in the past. available_periods must be in the future.
  • max_period_exceeded - available_periods.end and query_periods.end must be within 35 days of the earliest start.