Before you book a meeting, you need to know who’s already busy. A Free/Busy lookup answers exactly that: for each person you ask about, it returns the time blocks that fill their calendar, without exposing event titles or attendees. It’s the raw data layer every scheduling feature sits on top of, and the Calendar API returns it in one request.
This recipe shows how to query Free/Busy for one or more people, read the busy blocks the API returns, and decide when to reach for the availability endpoint instead.
Check Free/Busy for one or more people
Section titled “Check Free/Busy for one or more people”Send a POST request to /v3/grants/{grant_id}/calendars/free-busy with a JSON body containing start_time, end_time, and an emails array. Times are Unix timestamps in seconds, in Coordinated Universal Time (UTC). You can include up to 50 email addresses for Google and up to 20 for Microsoft in a single request.
The start_time and end_time define the window the API scans for busy blocks. The emails array lists every person you want to check, and they all have to use the same provider. The example below checks one mailbox over a 23 hour window.
curl --compressed --request POST \ --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars/free-busy' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "start_time": 1682467200, "end_time": 1682550000, "emails": ["[email protected]"] }'import Nylas from "nylas";
const nylas = new Nylas({ apiKey: "<NYLAS_API_KEY>", apiUri: "<NYLAS_API_URI>",});
const email = "<EMAIL>";
async function getFreeBusyCalendarInfo() { try { const calendar = await nylas.calendars.getFreeBusy({ identifier: "<NYLAS_GRANT_ID>", requestBody: { startTime: 1630435200, endTime: 1630521600, emails: [email], }, });
console.log("Calendar:", calendar); } catch (error) { console.error("Error to create calendar:", error); }}
getFreeBusyCalendarInfo();from nylas import Client
nylas = Client( "<NYLAS_API_KEY>", "<NYLAS_API_URI>")
grant_id = "<NYLAS_GRANT_ID>"email = "<EMAIL>"
free_busy = nylas.calendars.get_free_busy( grant_id, request_body={ "start_time":1630435200, "end_time":1630521600, "emails":[email] })
print(free_busy)The grant you authenticate with needs permission to view each address’s Free/Busy data, which the calendar provider controls. You can widen the window up to 3 months from start_time for Google and EWS, or 62 days for Microsoft Graph.
Read the busy time blocks
Section titled “Read the busy time blocks”The response is a data array with one entry per email you asked about. A successful entry has object: "free_busy" and a time_slots array, where each slot carries start_time, end_time (both Unix seconds), and a status of busy. A failed entry has object: "error" and an error string. The endpoint always returns 200 OK, so check each entry yourself.
Here’s a response checking 2 mailboxes. The first one resolved and returned 2 busy blocks. The second one failed because the provider couldn’t match the address, so it carries an error instead of time_slots:
{ "request_id": "dd3ec9a2-8f15-403d-b269-32b1f1beb9f5", "data": [ { "time_slots": [ { "start_time": 1690898400, "end_time": 1690902000, "status": "busy", "object": "time_slot" }, { "start_time": 1691064000, "end_time": 1691067600, "status": "busy", "object": "time_slot" } ], "object": "free_busy" }, { "object": "error" } ]}To find open time, invert the result: any gap inside your requested window that no time_slots entry covers is free for that person. When you check several people at once, a moment is bookable only if it’s free across every successful entry. Treat any entry with object: "error" as unknown rather than free, so you don’t book over a calendar you couldn’t read.
Check free/busy from the terminal
Section titled “Check free/busy from the terminal”Free/busy is the raw busy-block data behind any scheduling feature, and the Nylas CLI reads it with nylas calendar availability check. The command returns when the people on --emails are busy across a range, without exposing event titles or attendees.
nylas calendar availability check \ --start "2026-06-23 09:00" \ --end "2026-06-27 17:00"The same command underpins slot-finding: once you have the busy blocks, nylas calendar find-time turns them into ranked openings across the next 7 days. See the calendar availability check command reference for every flag.
Free/Busy vs availability
Section titled “Free/Busy vs availability”Free/Busy and availability solve related but different problems. Free/Busy returns raw busy intervals and leaves the slot math to you. The availability endpoint does that math for you: you pass a meeting duration and constraints, and it returns ready-to-book open slots across every attendee. Pick Free/Busy for custom logic, availability for a quick meeting picker.
The two endpoints take similar inputs but return opposite shapes. The table below sums up when each one fits, with the key difference being who computes the open slots.
| Free/Busy | Availability | |
|---|---|---|
| Endpoint | POST /calendars/free-busy | POST /calendars/availability |
| Returns | Raw busy time blocks per email | Bookable open slots across all attendees |
| Duration input | No | Yes, you set meeting length |
| Slot math | You compute open time | API computes it for you |
| Best for | Custom scheduling logic | Drop-in meeting picker |
If you only need to render someone’s busy ranges in a UI, Free/Busy is the lighter call. The moment you’re matching a 30 minute meeting against 4 calendars at once, switch to availability so you don’t rebuild overlap math across every attendee. See Find open meeting times for that flow.
Things to know about Free/Busy
Section titled “Things to know about Free/Busy”Free/Busy depends on connected grants and provider rules, so a few behaviors are worth knowing before you ship. The lookup only works for accounts connected through a grant, all addresses in one request must share a provider, and iCloud isn’t supported at all. Below are the details that trip people up most often.
Provider behavior and private events
Section titled “Provider behavior and private events”How much detail you get back depends on the provider and the target calendar’s sharing settings. On Google, the calling grant has to be able to see the other person’s Free/Busy, which Calendar sharing controls. On Microsoft Graph, the same applies through mailbox permissions, and Microsoft caps its calculation at 1,000 entries per time slot for each address. Private events still report as busy, but their titles and details never appear in the response, so you can query a colleague’s calendar without leaking what they’re doing. Neither provider includes all-day room resource bookings in the result.
Time ranges, time zones, and limits
Section titled “Time ranges, time zones, and limits”Every timestamp in both the request and the response is Unix seconds in UTC, so convert to the user’s local zone in your own code before display. The window you can scan depends on the provider: up to 3 months past start_time for Google and EWS, and up to 62 days for Microsoft Graph. Per request, you can include up to 50 email addresses for Google and 20 for Microsoft. Keep the window tight and the list short, since a 3 month scan across dozens of busy calendars returns far more slots than a single day.
Per-email error handling
Section titled “Per-email error handling”Because the endpoint returns 200 OK even when individual entries fail, error handling lives inside the data array, not the HTTP status. Loop over every entry and branch on object: process time_slots when it’s free_busy, and surface or retry the error string when it’s error. One bad address, like a misspelled name or a calendar your grant can’t read, won’t fail the whole batch, so the other 19 results still come back. The exact error text comes straight from the provider, as in the earlier Active Directory resolution message. The Microsoft Graph get schedule reference documents the underlying permissions if you’re debugging a Microsoft mailbox.
What’s next
Section titled “What’s next”- Find open meeting times to turn busy blocks into ready-to-book slots with the availability endpoint
- Hosted scheduling pages to embed a booking flow without building the slot picker yourself
- Calendar API overview for events, calendars, and recurring meetings
- Get Free/Busy schedule reference for the full request and response schema
- API reference for every endpoint and parameter