Using the Calendar API
💡 Looking for the Calendar API references? You can find them here!
The Nylas Calendar API gives your application a secure, reliable connection to your end users' calendars and the events they contain. It provides a REST interface that lets you...
- Access data for calendars and events (event titles, locations, descriptions, and so on).
- Schedule events and send notifications.
- RSVP to existing events.
Calendars and Events
Each end user who authenticates with your Nylas application might have zero, one, or multiple calendars. Their account can have many calendars, including the primary calendar, shared team calendars, and other custom calendars. They might also have Read access to their teammates' calendars.
In general, a Calendar object serves as a container for Event objects. A single end user usually has access to several calendars, but one is always considered their "primary" or default calendar. Calendars can be shared amongst end users, and users might have full Read/Write access to a calendar (owner or organizer), Read-only access (subscriber), or they might be able to see only the free/busy information.
By default, when an end user authenticates their account with your application, Nylas generates notifications for their primary calendar only. You can modify settings in the Nylas Dashboard to receive notifications for all of your end users' calendars.
Event objects are containers for information about scheduled events. This includes a list of the people involved, details about the time, meeting location (in-person address or virtual conferencing details), and a description. They can also include attachments and information about who has confirmed their attendance.
There are several types of calendars that you might encounter when working with the Nylas Calendar APIs:
Provider calendars
These are the most common type of calendar. There are several types of provider calendars: personal, group, and resource. You can view, add, modify, and delete events on calendars where read_only
is false
. Nylas makes changes directly on the provider.
Microsoft shared calendars
You can use the full set of Calendar APIs on Microsoft shared calendars only if they are correctly configured, and used with the correct permissions.
- Set the
Calendars.ReadWrite.Shared
API permission in the Azure application. - Make sure that the calendar owner specifically gives individual users access to the shared calendar. The owner can grant
Can view all details
orCan edit
permissions, depending on your use cases.
If the shared calendar owner grants "organizational access" to a shared calendar, meaning default-on access granted to the entire domain (sometimes called "tenant-based sharing"), then the owner must explicitly grant theCan edit
permission to users who need access using Nylas. TheCan view all details
permission does not allow Nylas access to the shared calendar.
Virtual calendars
Virtual calendars work like any other calendar, and they make it simple to embed customized scheduling features in your application. They're ideal for situations where you need to schedule events for people or objects that aren't associated with an existing calendar account (for example, a meeting room).
Limited calendar support for IMAP providers
IMAP is a protocol for receiving email messages only. "IMAP" service providers use the IMAP protocol to receive email messages, and the SMTP protocol to send them. Neither of these protocols includes calendar functionality.
Calendar availability
The Nylas APIs offer multiple ways to get information about end users' availability, so you can book meetings or run other time-based operations.
The Free/Busy endpoint
The simplest way to get availability information is using the Free/Busy endpoint. When you make a Free/Busy request, Nylas queries the provider, which returns simple information about blocks of time when the end user is booked and not available. For more information, see Check free/busy information.
If you're querying an end user within your organization, this information is usually public within the org. If you're querying for an end user outside of your organization, the calendar's owner must have published or made public the free/busy information.
The Availability endpoint
You can use the Availability endpoint to find space in an end user's calendar for a meeting with specific and detailed criteria. Use the endpoint to find a time that works, which you can then feed to the Events API to create an actual booking. For more information, see Check calendar availability.
Before you begin
To follow along with the samples on this page, you first need to sign up for a Nylas developer account, which gets you a free Nylas application and API key.
For a guided introduction, you can follow the Getting started guide to set up a Nylas account and Sandbox application. When you have those, you can connect an account from a calendar provider (such as Google, Microsoft, or iCloud) and use your API key with the sample API calls on this page to access that account's data.
Get available calendars
Most end users subscribe to multiple calendars. To view a list of all calendars they have access to, make a Get Calendars request.
💡 To follow along with this guide, copy the ID of a calendar that you're willing to make modifications to. You can always create a calendar for this purpose if you don't want to test features out on any of your existing calendars.
To make examples easier to read, this guide uses a query parameter to limit the number of results to five. See the pagination reference documentation to learn more about controlling the number of objects that Nylas returns.
The following example shows how to get an end user's available calendars, and the type of JSON response you can expect.
curl -X GET "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars?limit=5" \
-H "accept: application/json"\
-H "authorization: Bearer <NYLAS_API_KEY>"
{
"request_id" : "123-456-789",
"data" : [
{
"grant_id": "<NYLAS_GRANT_ID>"
"description": "Board game nights!",
"id": "zd08j9stfph95u449vti",
"is_primary": false,
"name": "Game nights",
"object": "calendar",
"read_only": true,
"timezone": "America/Toronto",
"hex_color": "#000000",
"is_owned_by_user": true
},
{
"grant_id": "<NYLAS_GRANT_ID>"
"description": null,
"id": "joujhadwh59pz9rvfjfw",
"is_primary": false,
"name": "jane.doe@example.com",
"object": "calendar",
"read_only": true,
"timezone": "America/Toronto",
"hex_color": "#000000",
"is_owned_by_user": true
}
]
}
The is_primary
field is included for Google and EWS calendars. If it's true
, it's the account's primary calendar. If false
, it's either a secondary or child calendar. For other providers, the primary calendar usually either uses the account's email address as the name, or it's called Calendar.
You can also use the Nylas SDKs to get a list of calendars associated with an account.
import 'dotenv/config'
import Nylas from 'nylas'
const NylasConfig = {
apiKey: process.env.NYLAS_API_KEY,
apiUri: process.env.NYLAS_API_URI,
}
const nylas = new Nylas(NylasConfig);
async function fetchFiveAvailableCalendars() {
try {
const calendars = await nylas.calendars.list({
identifier: process.env.NYLAS_GRANT_ID,
limit: 5
})
console.log('Available Calendars:', calendars);
} catch (error) {
console.error('Error fetching calendars:', error)
}
}
fetchFiveAvailableCalendars()
from dotenv import load_dotenv
load_dotenv()
import os
import sys
from nylas import Client
nylas = Client(
os.environ.get('NYLAS_API_KEY'),
os.environ.get('NYLAS_API_URI')
)
grant_id = os.environ.get("NYLAS_GRANT_ID")
calendars = nylas.calendars.list(grant_id)
print(calendars)
require 'nylas'
nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
calendars, _request_ids = nylas.calendars.list(identifier: "<NYLAS_GRANT_ID>", query_params: {limit: 5})
calendars.each {|calendar|
puts calendar
}
import com.nylas.NylasClient;
import com.nylas.models.*;
import java.util.List;
public class read_calendars {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
ListCalendersQueryParams listCalendersQueryParams = new ListCalendersQueryParams.
Builder().
limit(5).
build();
List<Calendar> calendars = nylas.calendars().list(dotenv.get("CALENDAR_ID"), listCalendersQueryParams).getData();
for (Calendar calendar : calendars) {
System.out.println(calendar);
}
}
}
import com.nylas.NylasClient
import com.nylas.models.*
import com.nylas.resources.Calendars
fun main(args: Array<String>) {
val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")
val calendarQueryParams: ListCalendersQueryParams = ListCalendersQueryParams(limit = 5)
val calendars: List<Calendar> = nylas.calendars().list("<CALENDAR_ID>", calendarQueryParams).data
for(calendar in calendars) {
println(calendar)
}
}
Get a calendar
You can return information about a single calendar by making a Get Calendar request that includes the appropriate calendar id
.
The following example shows a sample cURL request and the JSON response you can expect.
curl --request GET \
--url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID> \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--header 'Content-Type: application/json'
{
"request_id": "123-456-789",
"data": {
"grant_id": "<NYLAS_GRANT_ID>",
"description": "Board game nights!",
"id": "zd08j9stfph95u449vti",
"is_primary": false,
"name": "Game nights",
"object": "calendar",
"read_only": false,
"timezone": "UTC",
"hex_color": "#a47ae2",
"hex_foreground_color": "#000000",
"is_owned_by_user": true
}
}
You can also get information about a calendar using the Nylas SDKs.
import 'dotenv/config'
import Nylas from 'nylas'
const NylasConfig = {
apiKey: process.env.NYLAS_API_KEY,
apiUri: process.env.NYLAS_API_URI,
}
const nylas = new Nylas(NylasConfig);
async function fetchCalendar() {
try {
const calendar = await nylas.calendars.find({
identifier: process.env.NYLAS_GRANT_ID,
calendarId: process.env.CALENDAR_ID,
})
console.log('Calendar:', calendar)
} catch (error) {
console.error('Error fetching calendars:', error)
}
}
fetchCalendar()
from dotenv import load_dotenv
load_dotenv()
import os
import sys
from nylas import Client
nylas = Client(
os.environ.get('NYLAS_API_KEY'),
os.environ.get('NYLAS_API_URI')
)
grant_id = os.environ.get("NYLAS_GRANT_ID")
calendar = nylas.calendars.find(
grant_id,
os.environ.get("CALENDAR_ID")
)
print(calendar)
require 'nylas'
nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
calendar, _request_ids = nylas.calendars.find(
identifier: "<NYLAS_GRANT_ID>",
calendar_id: "<CALENDAR_ID>"
)
puts calendar
import com.nylas.NylasClient;
import com.nylas.models.*;
public class GetCalendar {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
Response<Calendar> calendar = nylas.calendars().find("<NYLAS_GRANT_ID>", "<CALENDAR_ID>");
System.out.println("Id: " + calendar.getData().getId() +
" | Name: " + calendar.getData().getName() +
" | Description: " + calendar.getData().getDescription());
}
}
import com.nylas.NylasClient
import com.nylas.models.*
fun main(args: Array<String>) {
val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")
val calendar: Response<Calendar> = nylas.calendars().find("<NYLAS_GRANT_ID>", "<CALENDAR_ID")
println("Id: " + calendar.data.id +
" | Name: " + calendar.data.name +
" | Description: " + calendar.data.description)
}
Create a calendar
Because a calendar is a container for Event objects, it doesn't have a lot of parameters or options available. In fact, when you create a calendar for a Microsoft account, you can specify the name as a string only. For other providers, you can also add a description, a location, an IANA-formatted timezone, and optional metadata.
The following example shows how to use a Create Calendar request and the type of JSON response you can expect.
curl --request POST \
--url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"name": "My New Calendar",
"description": "Description of my new calendar",
"location": "Location description",
"timezone": "America/Los_Angeles"
}'
{
"request_id": "1",
"data": {
"grant_id": "1",
"description": "<string>",
"id": "2",
"is_primary": false,
"location": "<string>",
"metadata": {
"your-key": "<string>"
},
"name": "<string>",
"object": "calendar",
"read_only": false,
"timezone": "UTC",
"is_owned_by_user": false
}
}
You can also use the Nylas SDKs to create calendars, as in the examples below.
import 'dotenv/config'
import Nylas from 'nylas'
const NylasConfig = {
apiKey: process.env.NYLAS_API_KEY,
apiUri: process.env.NYLAS_API_URI,
}
const nylas = new Nylas(NylasConfig)
async function createCalendar() {
try {
const calendar = await nylas.calendars.create({
identifier: process.env.NYLAS_GRANT_ID,
requestBody: {
name: 'Nylas DevRel',
description: 'Nylas Developer Relations',
}
})
console.log('Calendar:', calendar)
} catch (error) {
console.error('Error to create calendar:', error)
}
}
createCalendar()
from dotenv import load_dotenv
load_dotenv()
import os
import sys
from nylas import Client
nylas = Client(
os.environ.get('NYLAS_API_KEY'),
os.environ.get('NYLAS_API_URI')
)
grant_id = os.environ.get("NYLAS_GRANT_ID")
calendar = nylas.calendars.create(
grant_id,
request_body={
"name": 'Nylas DevRel',
"description": 'Nylas Developer Relations'
}
)
print(calendar)
require 'nylas'
nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
query_params = {
calendar_id: "<CALENDAR_ID>"
}
request_body = {
"name": "My New Calendar",
"description": "Description of my new calendar",
"location": "Location description",
"timezone": "America/Toronto",
"metadata": { "key1":"This is my metadata" }
}
calendar, _request_ids = nylas.calendars.create(
identifier: "<NYLAS_GRANT_ID>",
request_body: request_body)
puts calendar
import com.nylas.NylasClient;
import com.nylas.models.*;
import java.util.Map;
public class CreateCalendar {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
CreateCalendarRequest requestBody = new CreateCalendarRequest(
"My New Calendar",
"Description of my new calendar",
"Location description",
"America/Toronto",
Map.of("key1", "This is my metadata"));
Response<Calendar> calendar = nylas.calendars().
create("<NYLAS_GRANT_ID>", requestBody);
System.out.println(calendar.getData());
}
}
import com.nylas.NylasClient
import com.nylas.models.*
fun main(args: Array<String>) {
val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")
val requestBody = CreateCalendarRequest(
"My New Calendar",
"Description of my new calendar",
"Location description",
"America/Toronto",
mapOf("key1" to "This is my metadata")
)
val calendar: Response<Calendar> = nylas.calendars().
create("<NYLAS_GRANT_ID>", requestBody)
print(calendar.data)
}
Update a calendar
You can update a calendar to change any of the available fields, except if the end user's provider is Microsoft. For Microsoft calendars, you can update only the name string. To update any other information, you must delete the calendar and re-create it.
To update a calendar, make an Update Calendar request that includes the calendar's id
.
curl --request PUT \
--url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID> \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"name": "My New Calendar",
"description": "Description of my new calendar",
"location": "Location description",
"timezone": "America/Los_Angeles"
}'
{
"request_id": "1",
"data": {
"grant_id": "1",
"description": "<string>",
"id": "2",
"is_primary": false,
"location": "<string>",
"metadata": {
"your-key": "<string>"
},
"name": "<string>",
"object": "calendar",
"read_only": false,
"timezone": "UTC",
"is_owned_by_user": false
}
}
You can also update a calendar using the Nylas SDKs, as in the following examples.
import 'dotenv/config'
import Nylas from 'nylas'
const NylasConfig = {
apiKey: process.env.NYLAS_API_KEY,
apiUri: process.env.NYLAS_API_URI,
}
const nylas = new Nylas(NylasConfig)
async function updateCalendar() {
try {
const calendar = await nylas.calendars.update({
identifier: process.env.NYLAS_GRANT_ID,
calendarId: process.env.CALENDAR_ID,
requestBody: {
name: 'Nylas DevRel Calendar',
description: 'Nylas Developer Relations',
}
})
console.log('Updated Calendar:', calendar)
} catch (error) {
console.error('Error to update calendar:', error)
}
}
updateCalendar()
from dotenv import load_dotenv
load_dotenv()
import os
import sys
from nylas import Client
nylas = Client(
os.environ.get('NYLAS_API_KEY'),
os.environ.get('NYLAS_API_URI')
)
grant_id = os.environ.get("NYLAS_GRANT_ID")
calendar = nylas.calendars.update(
grant_id,
calendar_id=os.environ.get("CALENDAR_ID"),
request_body={
"name": 'Nylas DevRel Calendar',
"description": 'Nylas Developer Relations'
}
)
print(calendar)
require 'nylas'
nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
request_body = {
"name": "\"New Test Calendar (changed)\"",
"description": "\"this calendar has been updated!\"",
}
calendar, _request_ids = nylas.calendars.update(
identifier: "<NYLAS_GRANT_ID>",
calendar_id: "<CALENDAR_ID",
request_body: request_body)
puts calendar
import com.nylas.NylasClient;
import com.nylas.models.*;
public class UpdateCalendar {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
UpdateCalendarRequest requestBody = new UpdateCalendarRequest.Builder().
name("My New Calendar").
description("Description of my new calendar").
location("Location description").
timezone("America/Los_Angeles").
build();
Response<Calendar> calendar = nylas.calendars().update(
"<CALENDAR_ID>",
"<CALENDAR_ID>",
requestBody);
System.out.println(calendar.getData());
}
}
import com.nylas.NylasClient
import com.nylas.models.*
import com.nylas.resources.Calendars
fun main(args: Array<String>) {
val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")
val requestBody = UpdateCalendarRequest.Builder().
name("\"New Test Calendar (changed)\"").
description("\"this calendar has been updated!\"").
location("Location description").
timezone("America/Los_Angeles").
build()
val calendar: Response<Calendar> = nylas.calendars().update(
"<CALENDAR_ID>",
"<CALENDAR_ID>",
requestBody)
print(calendar.data)
}
Receive notifications for all calendars
⚠️ If you choose to receive webhook notifications for all of your end users' calendars, Nylas might generate a large number of webhooks. Prepare for this possibility by scaling your webhook processing before you change your subscriptions. For more information, see Best practices for webhooks.
By default, when an end user authenticates their account with your application, Nylas generates notifications for their primary calendar only. You can modify settings in the Nylas Dashboard to receive notifications for all of your end users' calendars:
- Log in to the v3 Nylas Dashboard.
- From the left navigation menu, select Notifications.
- Navigate to the Settings tab.
- Deselect the Subscribe to primary calendars only option and save your changes.
After you update this setting, you might need to wait a few minutes for your change to take effect.
🔍 Because iCloud doesn't support marking calendars as primary, Nylas sends calendar.updated
webhook notifications for changes to all calendars on an iCloud account. This happens even if you have "Subscribe to primary calendars only" enabled.
Calendar limitations
- When creating a calendar on Microsoft, you can define only its name.
- Similarly, you can update only the name of a Microsoft calendar.
More resources
The Nylas Samples Github repository includes working example applications in several languages that use the Nylas Calendar API. The following examples are interesting places to start exploring: