Skip to content

Availability

The availability engine finds open time slots across Chronary calendars and any Google Calendar or Microsoft Outlook sources a human has authorized for the queried agents. It supports single-agent, single-calendar, and cross-agent queries.

EndpointScopeUse case
GET /v1/agents/:id/availabilityAll calendars for one agent”When is this agent free?”
GET /v1/calendars/:id/availabilitySingle calendar”When is this calendar free?”
GET /v1/availabilityMultiple agents”When are all these agents free?”

Returns available time slots across all of an agent’s calendars:

Terminal window
curl "https://api.chronary.ai/v1/agents/agt_a1b2c3d4/availability?start=2026-04-07T09:00:00Z&end=2026-04-07T17:00:00Z&duration=30m" \
-H "Authorization: Bearer chr_sk_your_key_here"

Response:

{
"agents": ["agt_a1b2c3d4"],
"slots": [
{ "start": "2026-04-07T09:00:00Z", "end": "2026-04-07T09:30:00Z" },
{ "start": "2026-04-07T09:30:00Z", "end": "2026-04-07T10:00:00Z" },
{ "start": "2026-04-07T10:00:00Z", "end": "2026-04-07T10:30:00Z" },
{ "start": "2026-04-07T15:00:00Z", "end": "2026-04-07T15:30:00Z" }
],
"availability_state": "complete",
"sources": {
"chronary": "current",
"external": "current",
"last_synced_at": "2026-04-07T08:58:00Z"
},
"warnings": []
}
ParameterTypeRequiredDescription
startdatetimeYesStart of the time range (ISO 8601)
enddatetimeYesEnd of the time range (must be after start)
durationstringNo15m, 30m (default), 45m, 1h, or 2h
slot_durationstringNoDeprecated alias for duration. Still accepted; sending both with different values returns 400 Bad Request
include_busybooleanNoInclude busy slots in response (default false)
allow_stalebooleanNoReturn slots from a usable stale human-calendar cache. Defaults to false (fail closed); use only for non-committing exploration

Same parameters, scoped to one calendar:

Terminal window
curl "https://api.chronary.ai/v1/calendars/cal_x1y2z3/availability?start=2026-04-07T09:00:00Z&end=2026-04-07T17:00:00Z&duration=1h" \
-H "Authorization: Bearer chr_sk_your_key_here"

Find time slots where multiple agents are all free:

Terminal window
curl "https://api.chronary.ai/v1/availability?agents=agt_a1b2c3d4,agt_e5f6g7h8&start=2026-04-07T09:00:00Z&end=2026-04-07T17:00:00Z&duration=30m" \
-H "Authorization: Bearer chr_sk_your_key_here"

Additional parameters for cross-agent queries

Section titled “Additional parameters for cross-agent queries”
ParameterTypeDescription
agentsstringRequired. Comma-separated agent IDs
calendarsstringOptional. Comma-separated calendar IDs to narrow scope

Cross-agent availability has plan-based limits:

PlanMax agents per queryMax date range
Free530 days
Pro2090 days
CustomCustomCustom

Exceeding these limits returns 400 Bad Request.

  1. The engine collects all events from the relevant calendars in the requested time range
  2. Events with status confirmed or tentative block time slots
  3. Events with status cancelled do not block time
  4. Opaque busy intervals from human calendars granted to each queried agent are included
  5. Events imported via iCal subscriptions are also included
  6. Recurring series are expanded into their occurrences within the range — each occurrence blocks slots like a regular event (individually cancelled occurrences do not)
  7. The time range is divided into slots of the requested duration
  8. Slots that overlap with any blocking event are excluded (or marked busy if include_busy=true)

Availability completeness and source health

Section titled “Availability completeness and source health”

Every response includes availability_state, sources, and warnings. Treat slots as safe to schedule only when availability_state is complete.

StateMeaning
completeChronary and all required authorized human sources are current
staleA usable human-calendar cache exists but is older than the freshness target
partialOne or more required sources cannot cover the full requested window
unavailableRequired source data is unavailable

By default, stale, partial, or unavailable human data produces no slots and an availability_incomplete warning. Pass allow_stale=true only when showing exploratory suggestions that will be rechecked before committing. MCP stays fail-closed and intentionally has no override.

See Human Calendar Connections for setup, agent mappings, privacy, and publishing.

Every calendar can have optional availability rules that shape the busy blocks fed into the engine. Rules live under PUT /v1/calendars/:id/availability-rules — see the availability rules reference for the full schema.

Two things you can configure:

  • Buffersbuffer_before_minutes and buffer_after_minutes (0–120) expand every event on the calendar. A 30-minute event with a 15-minute before/after buffer occupies 60 minutes of busy time in free/busy calculations.
  • Working hours — per-day local start/end times in an IANA timezone. Any time outside working hours is treated as busy. Days you omit are entirely non-working.

Let’s walk through it.

Set 15-minute buffers and 9am–5pm Mon–Fri working hours in America/New_York:

Terminal window
curl -X PUT https://api.chronary.ai/v1/calendars/cal_01H9X4M2P5R8T6V0/availability-rules \
-H "Authorization: Bearer chr_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"buffer_before_minutes": 15,
"buffer_after_minutes": 15,
"working_hours": {
"mon": { "start": "09:00", "end": "17:00" },
"tue": { "start": "09:00", "end": "17:00" },
"wed": { "start": "09:00", "end": "17:00" },
"thu": { "start": "09:00", "end": "17:00" },
"fri": { "start": "09:00", "end": "17:00" }
},
"timezone": "America/New_York"
}'

Saturday and Sunday are omitted, so they will be treated as fully non-working.

Assume there’s one confirmed event on Wednesday, 2026-04-08, from 14:00–14:30 Eastern Time (18:00–18:30 UTC).

Step 3 — Query availability for that day

Section titled “Step 3 — Query availability for that day”

Query the full local day (midnight-to-midnight Eastern, which in UTC is 2026-04-08T04:00:00Z through 2026-04-09T04:00:00Z) with include_busy=true so you can see what was blocked:

Terminal window
curl "https://api.chronary.ai/v1/calendars/cal_01H9X4M2P5R8T6V0/availability?start=2026-04-08T04:00:00Z&end=2026-04-09T04:00:00Z&duration=30m&include_busy=true" \
-H "Authorization: Bearer chr_sk_your_key_here"
{
"calendar_id": "cal_01H9X4M2P5R8T6V0",
"slots": [
{ "start": "2026-04-08T13:00:00.000Z", "end": "2026-04-08T17:45:00.000Z" },
{ "start": "2026-04-08T18:45:00.000Z", "end": "2026-04-08T21:00:00.000Z" }
],
"busy": [
{ "start": "2026-04-08T18:00:00.000Z", "end": "2026-04-08T18:30:00.000Z" }
]
}

A few things to notice:

  • slots are contiguous free-gap intervals, not per-duration chunks. duration is a minimum-gap filter — gaps shorter than duration are dropped from the response — not a chunk size. An agent that wants 30-minute sub-slots walks each gap itself, stepping by its preferred stride.
  • Free time only shows up between 13:00Z (9:00 AM ET) and 21:00Z (5:00 PM ET) — the working-hours window. Before 9 AM and after 5 PM local, nothing is bookable.
  • The raw event at 18:00Z–18:30Z expands to a 17:45Z–18:45Z busy block in the engine because of the 15-minute buffers, which is why the first gap ends at 17:45Z and the second starts at 18:45Z.
  • busy only reports the raw event — buffers and working-hours blocks are an implementation detail of the engine, not part of the busy array.