You’re building a booking page and need to show open time slots without scraping every attendee’s calendar by hand. Pulling each calendar, normalizing time zones, and intersecting the free blocks is the kind of work that breaks the moment one provider returns busy data in a different shape. The availability endpoint does that intersection for you and hands back the open slots in one response.
This recipe focuses on configuring the request: working hours, time zones, buffers, and the availability method for multi-host meetings. For a shorter cross-provider intersection walkthrough, start with find open meeting times.
Get available time slots
Section titled “Get available time slots”Send a POST /v3/calendars/availability request with a list of participants, a start_time/end_time window, and duration_minutes. The endpoint reads each participant’s calendar, intersects their busy times, and returns only slots when everyone is free. Unlike most calendar calls, this one takes no grant in the path.
You pass participant email addresses and calendar_ids directly in the body, and every address must map to a valid Nylas grant. The duration_minutes field sets the meeting length and must be a multiple of 5 minutes. The interval_minutes field controls how often a candidate slot starts. The request below finds 30-minute slots for two participants.
curl --compressed --request POST \ --url 'https://api.us.nylas.com/v3/calendars/availability' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "participants": [ { "email": "[email protected]", "calendar_ids": ["[email protected]"], "open_hours": [{ "days": [0,1,2], "timezone": "America/Toronto", "start": "9:00", "end": "17:00", "exdates": [] }] }, { "email": "[email protected]", } ], "start_time": 1600890600, "end_time": 1600999200, "interval_minutes": 30, "duration_minutes": 30, "round_to": 15, "availability_rules": { "availability_method": "collective", "buffer": { "before": 15, "after": 15 }, "default_open_hours": [ { "days": [0,1,2], "timezone": "America/Toronto", "start": "9:00", "end": "17:00", "exdates": [] }, { "days": [3,4,5], "timezone": "America/Toronto", "start": "10:00", "end": "18:00", "exdates": [] } ] } }'import Nylas from "nylas";
const nylas = new Nylas({ apiKey: "<NYLAS_API_KEY>", apiUri: "<NYLAS_API_URI>",});
const email = "<EMAIL>";
async function getCalendarAvailability() { try { const calendar = await nylas.calendars.getAvailability({ requestBody: { startTime: 1630435200, endTime: 1630521600, durationMinutes: 15, participants: [{ email }], }, });
console.log("Calendar:", calendar); } catch (error) { console.error("Error to create calendar:", error); }}
getCalendarAvailability();from nylas import Client
nylas = Client( "<NYLAS_API_KEY>", "<NYLAS_API_URI>")
grant_id = "<NYLAS_GRANT_ID>"email = "<EMAIL>"
availability = nylas.calendars.get_availability( request_body={ "start_time": 1630435200, "end_time": 1630521600, "duration_minutes": 15, "participants": [{"email": email}] })
print(availability)The response returns a time_slots array, each entry carrying start_time, end_time, and the emails that are free for that block. See the availability API reference for every field.
Set working hours and time zones
Section titled “Set working hours and time zones”Working hours restrict the search to when a participant takes meetings. Set them with open_hours on each participant or default_open_hours under availability_rules to apply one schedule to everyone. Each entry holds 5 fields, and a participant in Toronto and one in Berlin each get slots in their own local time.
In the days array, Sunday is 0 and Saturday is 6, so [1,2,3,4,5] covers a standard Monday-to-Friday week. The start and end use 24-hour format with no leading zero, like "9:00" and "17:00", and the minimum start is 0:00 with a maximum of 23:49. The timezone is an Internet Assigned Numbers Authority (IANA) string such as America/Toronto. Add an exdates array of YYYY-MM-DD dates to drop specific days, like a holiday, from the window.
curl --request POST \ --url 'https://api.us.nylas.com/v3/calendars/availability' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "start_time": 1600890600, "end_time": 1600999200, "duration_minutes": 30, "interval_minutes": 30, "participants": [ { "email": "[email protected]", "calendar_ids": ["primary"], "open_hours": [{ "days": [1, 2, 3, 4, 5], "timezone": "America/Toronto", "start": "9:00", "end": "17:00", "exdates": ["2025-12-25"] }] } ] }'A per-participant open_hours block overrides default_open_hours for that person, so you can set one company-wide schedule and adjust it for individuals who keep different hours.
Choose an availability method
Section titled “Choose an availability method”The availability_method field under availability_rules decides how the endpoint treats multiple hosts. The default is max-availability. For a meeting where every host must attend, use collective; for round-robin scheduling that spreads meetings across a pool of hosts, use one of the two fairness-oriented methods. The 3 supported values are below.
| Method | What it does |
|---|---|
collective | Returns slots when every participant is free at the same time. Use this for a group meeting where all hosts must attend. |
max-fairness | Round-robin method that favors the host with the fewest assigned meetings, so bookings spread evenly across the pool. |
max-availability | Round-robin method (the default) that favors the host with the most open time, maximizing how many slots a person sees when booking. |
Two more fields shape the slots. A buffer of { "before": 15, "after": 15 } treats 15 minutes around each existing meeting as busy, so a 10:00-11:00 event blocks 9:45-11:15 and back-to-back bookings don’t get suggested. The round_to value snaps slot start times to a clean boundary; with round_to set to 15, a slot that would start at 9:05 rounds to 9:15.
Things to know about availability
Section titled “Things to know about availability”Availability and Free/Busy solve different problems. Availability generates bookable slots after intersecting calendars and applying working hours, buffers, and rounding. Free/Busy is the lighter call that returns raw busy blocks for a single user when you want to build your own slot logic. Reach for availability when you want finished slots, and Free/Busy when you want the busy data.
A few constraints are worth planning for. All times use Unix seconds, and start_time, end_time, duration_minutes, interval_minutes, and round_to must each be multiples of 5 minutes. Every participant’s email must map to a connected grant, so a participant whose grant has expired skews results toward busy or drops them from the calculation. The availability_rules shape the output: round_to snaps start times to a clean boundary and buffer pads existing events, which together trim the slot list. Performance scales with the participant count and the window length, so a 90-day window across 20 participants generates far more candidate slots than a 1-week window for 2 people. Keep windows tight and let interval_minutes thin the grid. Time zones follow the IANA time zone database, so always pass a region string like America/Toronto rather than a raw numeric offset.
What’s next
Section titled “What’s next”- Free/Busy to read raw busy blocks for one user
- Find meeting times for the cross-provider intersection walkthrough
- Calendar API overview for events, calendars, and scheduling concepts
- Availability API reference for every request and response field