# Time Selection

> **ALPHA**

> **SECONDARY:** This is an ALPHA feature and needs to be enabled by Cronofy support. Please email [support@cronofy.com](mailto:support@cronofy.com) with the `client_id` of your Application to have it enabled.

#### Description
The Time Selection endpoints let an integrating application list the available
times for a [Scheduling Request](/developers/api/scheduling-requests/index.md)
and book one, entirely over the API.

This supports Scheduling Requests that can be completed with just a time.
Requests that need more input from the person booking (required data capture,
consent, or custom questions, or a multi-event / sequence that books a time per
step) cannot yet be completed this way and must continue to redirect the user to
a booking page as a fallback.

See [When a request qualifies](#when-a-request-qualifies) below.

There are two integration operations that facilitate this:

- [Available Slots](/developers/api/scheduling-requests/time-selection/available-slots/index.md) returns the request's
available times.

- [Select Slot](/developers/api/scheduling-requests/time-selection/select-slot/index.md) books a time.

#### Discovering the operations
You never build the operation URLs yourself. They are handed to you when they
are available via an `integration_operations` object, mirroring the
`recipient_operations` object aimed at the person the request is intended for.
`integration_operations` are the set of actions available to your application
at that point in the request's life.

The serialized Scheduling Request carries only the entry point, the URL to
list its available times:

```json
{
  "integration_operations": {
    "simple_available_slots_url": "{SIMPLE_AVAILABLE_SLOTS_URL}"
  }
}
```

`integration_operations` appears on the Scheduling Request everywhere it is
serialized, including the [Create](/developers/api/scheduling-requests/create/index.md)
and [Query](/developers/api/scheduling-requests/query/index.md) responses.

It does not carry a select URL: you cannot select a time before you have
listed the available times, so that URL is returned alongside the times by the
[Available Slots](/developers/api/scheduling-requests/time-selection/available-slots/index.md) endpoint instead, as
`simple_select_slot_url`. Following the URLs as they are returned means there is
nothing for your application to construct or store between steps.

When the request cannot be booked with just a time, `integration_operations` is
an empty object `{}` and the person should be sent to the booking page via
[`recipient_operations.view_url`](/developers/api/scheduling-requests/query/index.md).

#### Operation URLs are opaque
Treat every operation URL as **opaque**. Use it exactly as Cronofy provides it.
Do not parse it or store assumptions about its shape. As these operations are
enhanced and expanded, the URLs may change and so will an integration that
relies on a specific pattern.

Its host, path, and any identifier within it are not part of the contract and
may change. The only guarantee is that the string Cronofy hands you in
`integration_operations` will work for a suitable period for the related
workflow (ie. minutes or hours, rather than days or weeks).

Unlike examples elsewhere in our documentation, these URLs are shown as
placeholders such as `{SIMPLE_AVAILABLE_SLOTS_URL}`, precisely because their
structure is not part of the contract.

#### The response envelope
The successes and the business-state failures of both endpoints share one
response shape: a typed `integration_operation_result` object beside the full
`scheduling_request`. Returning the request on every such response lets you
inspect and render the current state, and see what is possible.

```json
{
  "integration_operation_result": {
    "type": "available_slots",
    "result": "success",
    "integration_operations": { ... },
    ...
  },
  "scheduling_request": { ... }
}
```

`integration_operation_result` always carries:

- `type`: the operation invoked, for example `available_slots` or `select_slot`.

- `result`: the outcome, from the [result vocabulary](#result-vocabulary) below.

- `integration_operations`: the same "what's next" map the request carries,
so new actions can appear without changing the shape.

Any context-specific data sits alongside these: the `available_slots` and
`suggested_slots` for a listing, the `selected_slot` for a selection.

#### Result vocabulary
<table>
	<thead>
			<tr>
					<th>HTTP</th>
					<th>`result`</th>
					<th>Meaning</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>`200`</td>
					<td>`success`</td>
					<td>The operation completed; the response holds what was asked for.</td>
			</tr>
			<tr>
					<td>`202`</td>
					<td>`accepted`</td>
					<td>The operation was accepted; it will be processed asynchronously.</td>
			</tr>
			<tr>
					<td>`409`</td>
					<td>`conflict`</td>
					<td>Transient state meant the operation could not be actioned; retry the same payload shortly.</td>
			</tr>
			<tr>
					<td>`409`</td>
					<td>`not_possible`</td>
					<td>The request's current state means this cannot be done; see `result_detail`.</td>
			</tr>
			<tr>
					<td>`422`</td>
					<td>`invalid`</td>
					<td>The input was wrong, such as a missing or malformed value; see the top-level `errors`.</td>
			</tr>
	</tbody>
</table>
[Available Slots](/developers/api/scheduling-requests/time-selection/available-slots/index.md) returns `success` or
`not_possible`. [Select Slot](/developers/api/scheduling-requests/time-selection/select-slot/index.md) returns `accepted`,
`conflict`, `not_possible`, or `invalid`.

#### result_detail
The `result` guides the general handling of all operation results, the
`result_detail` allows you to specialize based on more operation-specific
variations of a `not_possible` `result`.

##### slot_unavailable
The chosen time has gone, but the request is still open. Pick another time; the
response includes a fresh `available_slots` / `suggested_slots` list and
`simple_select_slot_url`, so no second call is needed. Only returned by Select Slot.

##### superseded
The token was replaced, or the request is paused and will re-open under a new
token. Re-read the accompanying `scheduling_request` and follow whatever it now
advertises.

##### no_longer_possible
The request is booked, cancelled, expired, or otherwise terminal. Stop; fall back
to `recipient_operations.view_url` if a person can still act.

##### requires_more_input
The request needs more than a time: data capture, consent, custom questions, or a
multi-event / sequence that books a time per step. Send the person to the booking
page (`recipient_operations.view_url`).

##### configuration_error
Some configuration of the request or its participants prevents it from being
completed. The underlying configuration will need to be resolved for this
request to be scheduled.

#### When a request qualifies
A Scheduling Request advertises `simple_available_slots_url` only when it can be
completed with just a time. That means it is awaiting slot selection, places a
single event, and needs no further input from the person booking.

- **Requests that need more than a time are excluded.** Required data capture,
consent questions, and custom questions all require the person to complete the
booking page. Multi-event and sequence requests place an event per step, so a
single time can never complete them.

An excluded request has an empty `integration_operations` object. If one of its
endpoints is called by URL regardless, the response is `not_possible` with a
`result_detail` of `requires_more_input`.

> **INFO:** We are actively working on this area of the platform. If there are operations
you want to be made available via the API, please email
[support@cronofy.com](mailto:support@cronofy.com) with your use case.

#### Error responses
Failures fall into two shapes.

**Failures with useful request state** (the successes, the business-state
`409`s, and the validation `422`) use the [response envelope](#the-response-envelope)
so the `scheduling_request` travels alongside. A `not_possible` adds a
[`result_detail`](#result_detail); an `invalid` adds a top-level `errors` map, a
sibling of `integration_operation_result`, in the public API's
`{ &quot;<field>&quot;: [ { &quot;key&quot;, &quot;description&quot; } ] }` form:

```json
{
  "integration_operation_result": {
    "type": "select_slot",
    "result": "invalid",
    "integration_operations": {}
  },
  "errors": {
    "start": [
      { "key": "errors.required", "description": "required" }
    ]
  },
  "scheduling_request": { ... }
}
```

**Failures that are only about the caller or their credentials** carry no useful
request state, so they mirror the public API's
[errors shape](/developers/api/error-codes/index.md) with no
envelope:

```json
{
  "errors": {
    "authentication": [
      { "key": "errors.unauthorized", "description": "unauthorized" }
    ]
  }
}
```

This shape covers:

- `401` / `403`: authentication and authorization failures, which also
carry a `WWW-Authenticate` header;

- `404`: an unknown or deleted token, or the feature not being enabled for
the client;

- `429`: rate limited, returned with an empty body.

The `description` in an errors body is a human-readable fallback; treat the `key`
as the stable identifier. The specific errors each endpoint can return are listed
on the [Available Slots](/developers/api/scheduling-requests/time-selection/available-slots/index.md) and
[Select Slot](/developers/api/scheduling-requests/time-selection/select-slot/index.md) pages.

#### Authentication
The token in the URL identifies the request; the caller additionally
authenticates so the calls can be audited and rate limited. Two credentials are
accepted, the same two the [Scheduling Requests](/developers/api/scheduling-requests/index.md)
endpoints accept:

- an access token for the Organizational Unit, created by authorizing an
application for an [Organizational Unit scope](/developers/authorization/organization-connect/index.md);

- the `client_secret` of an [Internal Application](/developers/application-management/internal-applications/index.md)
linked to the Organizational Unit.

The resolved application or Organizational Unit must own the request. Both are
passed as a `Bearer` credential in the `Authorization` header.

**Scopes.** Access-token callers need the `organizational_unit_scheduler` scope
for both operations. An access token missing it receives a `403` with a
`WWW-Authenticate` header naming the scope needed. `client_secret` callers are
granted the scheduler scope implicitly.

**Rate limiting.** These endpoints draw from the same rate-limit buckets as the
rest of the public API, so they grant no additional allowance. A breach returns
`429`; see the [rate limits FAQ](/developers/faqs/application-management/rate-limits/index.md).

#### Times
Every time in a request or response is in UTC, formatted with a trailing `Z`
(for example `2026-09-17T09:00:00Z`). A slot is a `start` and `end` only.


---
[Read in HTML](/developers/api/scheduling-requests/time-selection/)

## In this section

- [Available Slots](/developers/api/scheduling-requests/time-selection/available-slots/index.md) — Lists the available times for a Scheduling Request so an integrating application can present or choose one.
- [Select Slot](/developers/api/scheduling-requests/time-selection/select-slot/index.md) — Books one of a Scheduling Request's available times directly over the API by posting the chosen start.
