Time Selection ALPHA
Read as Markdown Required plan: SchedulerDescription #
The Time Selection endpoints let an integrating application list the available times for a Scheduling Request 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 below.
There are two integration operations that facilitate this:
- Available Slots returns the request’s available times.
- Select Slot 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:
{
"integration_operations": {
"simple_available_slots_url": "{SIMPLE_AVAILABLE_SLOTS_URL}"
}
}integration_operations appears on the Scheduling Request everywhere it is
serialized, including the Create
and Query 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 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.
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.
{
"integration_operation_result": {
"type": "available_slots",
"result": "success",
"integration_operations": { ... },
...
},
"scheduling_request": { ... }
}integration_operation_result always carries:
type: the operation invoked, for exampleavailable_slotsorselect_slot.result: the outcome, from the 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 #
| HTTP | result | Meaning |
|---|---|---|
200 | success | The operation completed; the response holds what was asked for. |
202 | accepted | The operation was accepted; it will be processed asynchronously. |
409 | conflict | Transient state meant the operation could not be actioned; retry the same payload shortly. |
409 | not_possible | The request’s current state means this cannot be done; see result_detail. |
422 | invalid | The input was wrong, such as a missing or malformed value; see the top-level errors. |
Available Slots returns success or
not_possible. Select Slot 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.
Error responses #
Failures fall into two shapes.
Failures with useful request state (the successes, the business-state
409s, and the validation 422) use the response envelope
so the scheduling_request travels alongside. A not_possible adds a
result_detail; an invalid adds a top-level errors map, a
sibling of integration_operation_result, in the public API’s
{ "<field>": [ { "key", "description" } ] } form:
{
"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 with no envelope:
{
"errors": {
"authentication": [
{ "key": "errors.unauthorized", "description": "unauthorized" }
]
}
}This shape covers:
401/403: authentication and authorization failures, which also carry aWWW-Authenticateheader;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 and
Select Slot 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 endpoints accept:
- an access token for the Organizational Unit, created by authorizing an application for an Organizational Unit scope;
- the
client_secretof an Internal Application 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.
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.