Skip to content

Availability

The availability engine finds open time slots by examining events across one or more calendars. It supports single-agent, single-calendar, and cross-agent queries.

| Endpoint | Scope | Use case | |----------|-------|----------| | GET /v1/agents/:id/availability | All calendars for one agent | “When is this agent free?” | | GET /v1/calendars/:id/availability | Single calendar | “When is this calendar free?” | | GET /v1/availability | Multiple 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&slot_duration=30m" \
-H "Authorization: Bearer chr_sk_your_key_here"

Response:

{
"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" }
]
}

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | start | datetime | Yes | Start of the time range (ISO 8601) | | end | datetime | Yes | End of the time range (must be after start) | | slot_duration | string | No | 15m, 30m (default), 45m, 1h, or 2h | | include_busy | boolean | No | Include busy slots in response (default false) |

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&slot_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&slot_duration=30m" \
-H "Authorization: Bearer chr_sk_your_key_here"

Additional parameters for cross-agent queries

Section titled “Additional parameters for cross-agent queries”

| Parameter | Type | Description | |-----------|------|-------------| | agents | string | Required. Comma-separated agent IDs | | calendars | string | Optional. Comma-separated calendar IDs to narrow scope |

Cross-agent availability has plan-based limits:

| Plan | Max agents per query | Max date range | |------|---------------------|----------------| | Free | 5 | 30 days | | Pro | 20 | 90 days | | Custom | Custom | Custom |

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. Events imported via iCal subscriptions are also included
  5. The time range is divided into slots of the requested duration
  6. Slots that overlap with any blocking event are excluded (or marked busy if include_busy=true)

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&slot_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-slot_duration chunks. slot_duration is a minimum-gap filter — gaps shorter than slot_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.