How to block time slots in Outlook and Google calendar with Nylas Calendar API

14 min read

Key Takeaways

  • Learn how to block time slots in Outlook and Google Calendar using the Nylas Calendar API.
  • Discover how to improve scheduling control by dynamically managing availability.
  • Get step-by-step guidance with real-world examples and API requests.
  • Simplify time management and enhance user experience with automated calendar workflows.

Managing calendar availability is essential for professionals, teams, and businesses to stay organized and productive. Whether you need to reserve focus time, avoid double bookings, or block personal commitments, controlling your calendar efficiently can save time and reduce frustration.

However, manually managing availability in Outlook or Google Calendar can be tedious and prone to errors, especially for users balancing multiple schedules. This is where Nylas comes in. By leveraging the Nylas API, you can automate and simplify the process of blocking time slots, ensuring that your availability is always up-to-date and accurate.

If you’re new to time slot management, check out our foundational article: How to Schedule Time Slots and Check Availability.

In this article, we’ll walk you through how to block time slots in Outlook and Google Calendar using Nylas, complete with actionable steps and code samples to help you get started.

Why block time slots in your calendar?

Blocking time slots in your calendar is a simple yet powerful way to take control of your schedule. By proactively reserving time, you ensure that your most important priorities are protected and that interruptions are minimized. Here are some common scenarios where blocking time is essential:

  • Focus time for deep work
    Reserve uninterrupted blocks to work on critical projects or tasks that require concentration, preventing last-minute meetings from filling your calendar.
  • Personal commitments
    Block time for appointments, breaks, or personal obligations without the risk of overlapping professional engagements.
  • Preventing overbooking
    Automatically mark specific times as “busy” to avoid double-booking, especially when managing multiple calendars or team availability.
  • Recurring events and routines
    Set aside regular time for team syncs, one-on-ones, or weekly planning, ensuring these important events are prioritized.

By blocking time slots, you create clear boundaries in your schedule, boost productivity, and reduce stress from an overloaded calendar. With Nylas, you can automate this process across both Outlook and Google Calendar, saving time and ensuring accuracy.

How Nylas works with Outlook and Google calendar

Nylas provides a powerful API that integrates seamlessly with Outlook and Google Calendar, allowing developers to manage calendars programmatically. Whether you need to block time slots, check availability, or automate scheduling workflows, Nylas offers a unified solution to simplify calendar management.

Here’s how it works:

  • Centralized API integration
    Nylas connects directly to both Google Calendar and Outlook through a single, unified API. Instead of managing two separate integrations, you can interact with both platforms using one consistent interface.
  • Flexible calendar management
    Using Nylas, you can:
    • Fetch calendar events and availability in real time.
    • Block time slots by marking specific windows as “busy.”
    • Sync changes across multiple calendars seamlessly.
  • Unified developer experience
    With Nylas, developers can save time by avoiding platform-specific complexities. The API handles authentication, data normalization, and calendar syncing, so you can focus on building your application.

For more detailed technical information and resources, visit Nylas API Documentation or explore additional solutions on Nylas.com.

The next section details step-by-step instructions for blocking time slots in Outlook and Google Calendar using Nylas, complete with practical code examples.

Step-by-Step guide to blocking time slots with Nylas

Blocking time slots in Outlook

Step 1: Connect Outlook calendar with the Nylas API

  • Log in to the Nylas Dashboard and navigate to the Connectors section.
  • Add the Microsoft connector and provide the necessary details:
  • Input your Azure Client ID and Azure Client Secret. These can be obtained by following the steps outlined in the Nylas documentation.
  • Select the required scopes to ensure the integration works seamlessly.
  • Once the connector is created, set up a grant to enable testing with your Outlook account.
  • Navigate to Grants → Add Test Grant → Enter your email and follow the setup instructions.

Step 2: Mark time slots as “Busy”

  • Create an event in the calendar and specify it as a busy event to block the time slot.
  • Refer to the Nylas Event Creation Documentation for detailed instructions on how to create
  • Use the Nylas SDKs to streamline event creation across different programming languages.

Node.js

Ruby

Python

Java

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)

const now = Math.floor(Date.now() / 1000)

async function createAnEvent() {
  try {
    const event = await nylas.events.create({
      identifier: process.env.NYLAS_GRANT_ID,
      requestBody: {
        title: 'I\'m busy',
        location: "Work",
        description: "I'm busy at work",
        busy: true,
        when: {
          startTime: now + 3600,
          endTime: now + 5400,
        },
        participants: [{email: "[email protected]"}]
      },
      queryParams: {
        calendarId: process.env.OUTLOOK_CALENDAR_ID,
      },
    })

    console.log('Event:', event);
  } catch (error) {
    console.error('Error creating event:', error)
  }
}

createAnEvent()
require 'nylas'
require 'dotenv/load'

nylas = Nylas::Client.new(
  api_key: ENV["NYLAS_API_KEY"],
  api_uri: ENV["NYLAS_API_URI"]
)

query_params = {
  calendar_id: ENV["OUTLOOK_CALENDAR_ID"]	
}

start_time = Time.now()
start_time = start_time + (1 * 3600)
end_time = start_time + (0.5 * 3600)

request_body = {
    busy: true,
	when: {
		start_time: start_time.to_i,
		end_time: end_time.to_i
	},
	title: "I'm busy",
	location: "Work",
	description: "I'm busy at work",
	participants: [{
		name: "Swag",
		email: "[email protected]", 
		status: "noreply"
	}]
}

event, _request_id = nylas.events.create(
		identifier: ENV["NYLAS_GRANT_ID"], 
		query_params: query_params,
		request_body: request_body)
puts JSON.pretty_generate(event)
from dotenv import load_dotenv
import pendulum
import os
from nylas import Client

load_dotenv()

nylas = Client(
    api_key = os.environ.get("NYLAS_API_KEY"),
    api_uri = os.environ.get("NYLAS_API_URI")
)

grant_id = os.environ.get("NYLAS_GRANT_ID")

start = pendulum.now()
start = start.add(hours=1)
end = start.add(hours=0.5)

events = nylas.events.create(
  grant_id,
  request_body={
    "title": "I\'m busy",
    "location": "Work",
    "busy": True,
    "description": "I'm busy at work",
    "when": {
      "start_time": start.int_timestamp,
      "end_time": end.int_timestamp
    },
	"participants": [{
		"name": "Swag",
		"email": "[email protected]", 
		"status": "noreply"
	}]    
  },
  query_params={
    "calendar_id": os.environ.get("OUTLOOK_CALENDAR_ID")
  }
)

print(events)
import com.nylas.NylasClient;
import com.nylas.models.*;
import io.github.cdimascio.dotenv.Dotenv;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.*;

public class Create_Event {
    public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
        Dotenv dotenv = Dotenv.load();
        NylasClient nylas = new NylasClient.Builder(dotenv.get("NYLAS_API_KEY"))
                                           .apiUri(dotenv.get("NYLAS_API_URI")).build();

        LocalDateTime now = LocalDateTime.now();
        Instant instantTime = now.toInstant(ZoneOffset.UTC);
        Instant sixPmUtc = instantTime.plus(6, ChronoUnit.HOURS);
        Instant sixPmUtcPlus = instantTime.plus(390, ChronoUnit.MINUTES);

        long startTime = sixPmUtc.getEpochSecond();
        long endTime = sixPmUtcPlus.getEpochSecond();

        String title = "I'm busy";
        String location = "Work";
        String description = "I'm busy at work";

        CreateEventRequest.When.Timespan timespan = new CreateEventRequest.
                When.Timespan.
                Builder(Math.toIntExact(startTime), Math.toIntExact(endTime)).
                build();

        List<CreateEventRequest.Participant> participants_list = new ArrayList<>();

        participants_list.add(new CreateEventRequest.
                Participant("[email protected]", ParticipantStatus.NOREPLY,
                "Swag", "", ""));

        CreateEventRequest createEventRequest = new CreateEventRequest.Builder(timespan)
                .participants(participants_list)
                .busy(Boolean.TRUE)
                .title(title)
                .location(location)
                .description(description)
                .build();

        CreateEventQueryParams createEventQueryParams = new CreateEventQueryParams.Builder(dotenv.get("OUTLOOK_CALENDAR_ID")).build();

        Event event = nylas.events().create(
                dotenv.get("NYLAS_GRANT_ID"),
                createEventRequest,
                createEventQueryParams).getData();
    }
}

Step 3: Programmatic use of availability and busy settings

  • Leverage Nylas to check availability by determining whether two or more accounts have overlapping events. This is useful for scheduling meetings.
  • Use the Free/Busy endpoint to fetch a list of all booked events, which can help identify when a user is busy and their remaining availability. For detailed guidance on these features, refer to the Availability and Free/Busy Documentation.

Node.js

Ruby

Python

Java

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)

const participant = process.env.OUTLOOK_CALENDAR_ID
const guest = process.env.GUEST_CALENDAR_ID

const date = Date()
const new_date = new Date(date)
var start_time = new Date(new_date.getFullYear(), 
                          new_date.getMonth(), new_date.getUTCDate(), 9, 0, 0, 0);	
var end_time = new Date(new_date.getFullYear(), 
                          new_date.getMonth(), new_date.getUTCDate(), 17, 0, 0, 0);

async function getCalendarAvailability() {
  try {
    const calendar = await nylas.calendars.getAvailability({
      requestBody: {
        startTime: start_time.getTime() / 1000,
        endTime: end_time.getTime() / 1000,
        duration_minutes: 60,
        participants: [{email: participant}, {email: guest}]
      }
    })

    calendar['data']['timeSlots'].forEach((timeslot) => {
		var auxStartTime = new Date(timeslot['startTime'] * 1000);
		var auxEndTime = new Date(timeslot['endTime'] * 1000);
		console.log(`From: ${auxStartTime.toLocaleTimeString()} To: ${auxEndTime.toLocaleTimeString()}`);
    });
    
  } catch (error) {
    console.error('Error fetching availability', error)
  }
}

getCalendarAvailability()
require 'nylas'
require 'date'
require 'dotenv/load'

nylas = Nylas::Client.new(
  api_key: ENV["NYLAS_API_KEY"],
  api_uri: ENV["NYLAS_API_URI"]
)

today = Date.today

start_time = Time.local(today.year, today.month, today.day, 8, 0,0).strftime("%s").to_i
end_time = Time.local(today.year, today.month, today.day, 17, 0,0).strftime("%s").to_i

request_body = {
	"participants": [
	{
		"email": ENV["NYLAS_GRANT_ID"],
		"calendar_ids": [
			ENV["OUTLOOK_CALENDAR_ID"]
		],
	},
	{
		"email": ENV["GUEST_GRANT_ID"],
		"calendar_ids": [
			ENV["GUEST_CALENDAR_ID"]
		],
	}	
	],
	"start_time": start_time,
	"end_time": end_time,
	"duration_minutes": 60,
}

available, _request_ids = nylas.calendars.get_availability(request_body: request_body)

available[:time_slots].each {|slots|
	puts "From: #{Time.at(slots[:start_time]).to_datetime.strftime("%H:%M:%S")}" \
	     " To: #{Time.at(slots[:end_time]).to_datetime.strftime("%H:%M:%S")}"
}
from dotenv import load_dotenv
import os
import sys
import pendulum
from nylas import Client
from nylas.models.availability import GetAvailabilityRequest

load_dotenv()

nylas = Client(
    os.environ.get("NYLAS_API_KEY"),
    os.environ.get("NYLAS_API_URI")
)

now = pendulum.now()

start_time = pendulum.datetime(now.year, now.month, now.day, 13, 0, 0)
end_time = pendulum.datetime(now.year, now.month, now.day, 22, 0, 0)

request_body = GetAvailabilityRequest(
    participants = [
    {
        "email": os.environ.get("NYLAS_GRANT_ID"),
        "calendar_ids": [
            os.environ.get("OUTLOOK_CALENDAR_ID")
        ],
    },
    {
        "email": os.environ.get("GUEST_GRANT_ID"),
        "calendar_ids": [
            os.environ.get("GUEST_CALENDAR_ID")
        ],
    },            
    ],
        duration_minutes = 60,
)

request_body["start_time"] = start_time.int_timestamp
request_body["end_time"] = end_time.int_timestamp
availability, _request_ids = nylas.calendars.get_availability(request_body)
for slot in availability.time_slots:
    ts = pendulum.from_timestamp(slot.start_time, now.timezone.name).strftime("%H:%M:%S")
    te = pendulum.from_timestamp(slot.end_time, now.timezone.name).strftime("%H:%M:%S")
    print(f"From: {ts} To: {te}")
import com.nylas.NylasClient;
import com.nylas.models.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.text.SimpleDateFormat;
import io.github.cdimascio.dotenv.Dotenv;

public class GetAvailability {
    public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
        Dotenv dotenv = Dotenv.load();
        NylasClient nylas = new NylasClient.Builder(dotenv.get("NYLAS_API_KEY"))
                .apiUri(dotenv.get("NYLAS_API_URI")).build();

        LocalDate today = LocalDate.now();
        Instant sixPmUtc = today.atTime(13, 0).toInstant(ZoneOffset.UTC);
        long startTime = sixPmUtc.getEpochSecond();
        Instant sixPmUtcPlus = sixPmUtc.plus(9, ChronoUnit.HOURS);
        long endTime = sixPmUtcPlus.getEpochSecond();

        List<String> participant_calendars = new ArrayList<>();
        List<String> guest_calendars = new ArrayList<>();
        participant_calendars.add(dotenv.get("OUTLOOK_CALENDAR_ID"));
        guest_calendars.add(dotenv.get("GUEST_CALENDAR_ID"));
        AvailabilityParticipant participant = new AvailabilityParticipant(dotenv.get("NYLAS_GRANT_ID"),
                participant_calendars, null);
        AvailabilityParticipant guest = new AvailabilityParticipant(dotenv.get("GUEST_GRANT_ID"),
                guest_calendars, null);
        List<AvailabilityParticipant> participants = new ArrayList<>();
        participants.add(participant);
        participants.add(guest);

        GetAvailabilityRequest availability = new GetAvailabilityRequest(
                Math.toIntExact(startTime),
                Math.toIntExact(endTime), participants, 60, null,
                null, null, null);

        Response<GetAvailabilityResponse> available =
                nylas.calendars().getAvailability(availability);

        assert available.getData().getTimeSlots() != null;

        for(TimeSlot times : available.getData().getTimeSlots()){
            String initDate = new SimpleDateFormat("HH:mm:ss").
                    format(new java.util.Date((times.getStartTime() * 1000L)));
            String endDate = new SimpleDateFormat("HH:mm:ss").
                    format(new java.util.Date((times.getEndTime() * 1000L)));

            System.out.println("From " + initDate + " To: " + endDate);
        }
    }
}
  • We can also use the Free/Busy endpoint, which returns a list of all booked events, allowing us to see when the user is busy. This also helps us determine their availability:

Node.js

Ruby

Python

Java

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)

const date = Date()
const new_date = new Date(date)
var start_time = new Date(new_date.getFullYear(), 
                          new_date.getMonth(), new_date.getUTCDate(), 9, 0, 0, 0);	
var end_time = new Date(new_date.getFullYear(), 
                          new_date.getMonth(), new_date.getUTCDate(), 17, 0, 0, 0);

async function getFreeBusyCalendarInfo() {
  try {
    const calendar = await nylas.calendars.getFreeBusy({
      identifier: process.env.NYLAS_GRANT_ID,
      requestBody: {
        startTime: start_time.getTime() / 1000,
        endTime: end_time.getTime() / 1000,
        emails: [process.env.OUTLOOK_CALENDAR_ID]
      }
    })

    calendar['data'][0]['timeSlots'].forEach((timeslot) => {
		var auxStartTime = new Date(timeslot['startTime'] * 1000);
		var auxEndTime = new Date(timeslot['endTime'] * 1000);
		console.log(`Busy from: ${auxStartTime.toLocaleTimeString()} To: ${auxEndTime.toLocaleTimeString()}`);
	});
	
  } catch (error) {
    console.error('Error to create calendar:', error)
  }
}

getFreeBusyCalendarInfo()
require 'nylas'
require 'date'
require 'dotenv/load'

nylas = Nylas::Client.new(
  api_key: ENV["NYLAS_API_KEY"],
  api_uri: ENV["NYLAS_API_URI"]
)

today = Date.today

start_time = Time.local(today.year, today.month, 
                        today.day, 9, 0,0).strftime("%s").to_i
end_time = Time.local(today.year, today.month, 
                        today.day, 17, 0,0).strftime("%s").to_i

request_body = {
		"emails": [
		  ENV["OUTLOOK_CALENDAR_ID"]
	],
	"start_time": start_time,
	"end_time": end_time
}

available, _request_ids = 
nylas.calendars.get_free_busy(identifier: ENV["NYLAS_GRANT_ID"], 
request_body: request_body)

available.each {|time_slots|
	time_slots[:time_slots].each {|slots|
		puts "Busy from: #{Time.at(slots[:start_time]).to_datetime.strftime("%H:%M:%S")}" \
             " To: #{Time.at(slots[:end_time]).to_datetime.strftime("%H:%M:%S")}"
	}
}

from dotenv import load_dotenv
import os
import sys
from nylas import Client
import pendulum

load_dotenv()

nylas = Client(
    os.environ.get('NYLAS_API_KEY'),
    os.environ.get('NYLAS_API_URI')
)

now = pendulum.now()

start_time = pendulum.datetime(now.year, now.month, now.day, 13, 0, 0)
end_time = pendulum.datetime(now.year, now.month, now.day, 22, 0, 0)

grant_id = os.environ.get("NYLAS_GRANT_ID")

free_busy = nylas.calendars.get_free_busy(
  grant_id,
  request_body={
    "start_time": start_time.int_timestamp,
    "end_time": end_time.int_timestamp,
    "emails": [os.environ.get("OUTLOOK_CALENDAR_ID")]
  }
)

for slot in free_busy[0][0].time_slots:
    ts = pendulum.from_timestamp(slot.start_time, now.timezone.name).strftime("%H:%M:%S")
    te = pendulum.from_timestamp(slot.end_time, now.timezone.name).strftime("%H:%M:%S")
    print(f"Busy from: {ts} To: {te}")
import com.nylas.NylasClient;
import com.nylas.models.*;
import io.github.cdimascio.dotenv.Dotenv;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

public class FreeBusy {
    public static void main(String[] args) throws Exception {
        Dotenv dotenv = Dotenv.load();
        NylasClient nylas = new NylasClient.Builder(dotenv.get("NYLAS_API_KEY")).build();

        LocalDate today = LocalDate.now();
        Instant sixPmUtc = today.atTime(12, 0).toInstant(ZoneOffset.UTC);
        int startTime = (int) sixPmUtc.getEpochSecond();
        Instant sixPmUtcPlus = sixPmUtc.plus(10, ChronoUnit.HOURS);
        int endTime = (int) sixPmUtcPlus.getEpochSecond();

        List<String> emails = new ArrayList<>();
        emails.add(dotenv.get("OUTLOOK_CALENDAR_ID"));

        GetFreeBusyRequest request = new GetFreeBusyRequest(startTime, endTime, emails);

        Response<List<GetFreeBusyResponse>> response = nylas.calendars().
                getFreeBusy(dotenv.get("NYLAS_GRANT_ID"), request);

        for(GetFreeBusyResponse freeBusy : response.getData()) {
            if (freeBusy.getObject() == FreeBusyType.FREE_BUSY) {
                GetFreeBusyResponse.FreeBusy freeBusyData = (GetFreeBusyResponse.FreeBusy) freeBusy;
                List<FreeBusyTimeSlot> times = freeBusyData.getTimeSlots();

                for(FreeBusyTimeSlot time : times){
                    String startDate = new SimpleDateFormat("HH:mm:ss").
                            format(new java.util.Date((time.getStartTime() * 1000L)));

                    String endDate = new SimpleDateFormat("HH:mm:ss").
                            format(new java.util.Date((time.getEndTime() * 1000L)));

                    System.out.println("Busy from: " + startDate + " to: " + endDate);
                }
            } else if (freeBusy.getObject() == FreeBusyType.ERROR) {
                GetFreeBusyResponse.FreeBusyError freeBusyError = (GetFreeBusyResponse.FreeBusyError) freeBusy;
            } else {
                throw new Exception("Unknown free busy type");
            }
        }
    }
}

These steps will enable you to efficiently block time slots in Outlook using Nylas, ensuring your calendar is always up-to-date and free from overbookings. Next, we’ll explore the steps for Google Calendar users.

Create time slots in Google Calendar

Step 1: Integrate Google calendar with the Nylas API

  • Log in to the Nylas Dashboard and navigate to the Connectors section.
  • Add the Google connector and provide the necessary details:
  • Input your Google OAuth Client ID and Google OAuth Client Secret. These can be obtained by following the steps outlined in the Nylas documentation.
  • Select the required scopes to ensure proper access to Google Calendar.
  • Once the connector is successfully created, set up a grant to enable testing with your Google Calendar:
    • Navigate to Grants → Add Test Grant → Enter your email and follow the prompts to authorize access.

Step: 2 Customize time slots and block specific hours

  • Use the Nylas API to programmatically create calendar events and mark specific time slots as “busy.
  • This allows you to block off time dynamically, preventing conflicts with other meetings or tasks.
  • Let’s explore the examples of creating and managing events with Nylas SDKs.

Node.js

Ruby

Python

Java

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)

const now = Math.floor(Date.now() / 1000)

async function createAnEvent() {
  try {
    const event = await nylas.events.create({
      identifier: process.env.NYLAS_GRANT_ID,
      requestBody: {
        title: 'I\'m busy',
        location: "Work",
        description: "I'm busy at work",
        busy: true,
        when: {
          startTime: now + 3600,
          endTime: now + 5400,
        },
        participants: [{email: "[email protected]"}]
      },
      queryParams: {
        calendarId: process.env.GOOGLE_CALENDAR_ID,
      },
    })

    console.log('Event:', event);
  } catch (error) {
    console.error('Error creating event:', error)
  }
}

createAnEvent()
require 'nylas'
require 'dotenv/load'

nylas = Nylas::Client.new(
  api_key: ENV["NYLAS_API_KEY"],
  api_uri: ENV["NYLAS_API_URI"]
)

query_params = {
  calendar_id: ENV["GOOGLE_CALENDAR_ID"]	
}

start_time = Time.now()
start_time = start_time + (1 * 3600)
end_time = start_time + (0.5 * 3600)

request_body = {
    busy: true,
	when: {
		start_time: start_time.to_i,
		end_time: end_time.to_i
	},
	title: "I'm busy",
	location: "Work",
	description: "I'm busy at work",
	participants: [{
		name: "Swag",
		email: "[email protected]", 
		status: "noreply"
	}]
}

event, _request_id = nylas.events.create(
		identifier: ENV["NYLAS_GRANT_ID"], 
		query_params: query_params,
		request_body: request_body)
puts JSON.pretty_generate(event)
from dotenv import load_dotenv
import pendulum
import os
from nylas import Client

load_dotenv()

nylas = Client(
    api_key = os.environ.get("NYLAS_API_KEY"),
    api_uri = os.environ.get("NYLAS_API_URI")
)

grant_id = os.environ.get("NYLAS_GRANT_ID")

start = pendulum.now()
start = start.add(hours=1)
end = start.add(hours=0.5)

events = nylas.events.create(
  grant_id,
  request_body={
    "title": "I\'m busy",
    "location": "Work",
    "busy": True,
    "description": "I'm busy at work",
    "when": {
      "start_time": start.int_timestamp,
      "end_time": end.int_timestamp
    },
	"participants": [{
		"name": "Swag",
		"email": "[email protected]", 
		"status": "noreply"
	}]    
  },
  query_params={
    "calendar_id": os.environ.get("GOOGLE_CALENDAR_ID")
  }
)

print(events)
import com.nylas.NylasClient;
import com.nylas.models.*;
import io.github.cdimascio.dotenv.Dotenv;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.*;

public class Create_Event {
    public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
        Dotenv dotenv = Dotenv.load();
        NylasClient nylas = new NylasClient.Builder(dotenv.get("NYLAS_API_KEY"))
                                           .apiUri(dotenv.get("NYLAS_API_URI")).build();

        LocalDateTime now = LocalDateTime.now();
        Instant instantTime = now.toInstant(ZoneOffset.UTC);
        Instant sixPmUtc = instantTime.plus(6, ChronoUnit.HOURS);
        Instant sixPmUtcPlus = instantTime.plus(390, ChronoUnit.MINUTES);

        long startTime = sixPmUtc.getEpochSecond();
        long endTime = sixPmUtcPlus.getEpochSecond();

        String title = "I'm busy";
        String location = "Work";
        String description = "I'm busy at work";

        CreateEventRequest.When.Timespan timespan = new CreateEventRequest.
                When.Timespan.
                Builder(Math.toIntExact(startTime), Math.toIntExact(endTime)).
                build();

        List<CreateEventRequest.Participant> participants_list = new ArrayList<>();

        participants_list.add(new CreateEventRequest.
                Participant("[email protected]", ParticipantStatus.NOREPLY,
                "Swag", "", ""));

        CreateEventRequest createEventRequest = new CreateEventRequest.Builder(timespan)
                .participants(participants_list)
                .busy(Boolean.TRUE)
                .title(title)
                .location(location)
                .description(description)
                .build();

        CreateEventQueryParams createEventQueryParams = new CreateEventQueryParams.Builder(dotenv.get("GOOGLE_CALENDAR_ID")).build();

        Event event = nylas.events().create(
                dotenv.get("NYLAS_GRANT_ID"),
                createEventRequest,
                createEventQueryParams).getData();
    }
}

Step 3: Dynamically block time slots

  • Leverage Nylas’ Availability and Create Event endpoints to programmatically block time slots based on your schedule. These endpoints allow you to fetch free time slots, display availability, and dynamically create events to reserve specific windows.

Check for Free/Busy slots in Google Calendar with Nylas Calendar API

Node.js

Ruby

Python

Java

import 'dotenv/config'
import Nylas from 'nylas'
import * as readline from 'readline';

const NylasConfig = {
 apiKey: process.env.NYLAS_API_KEY,
 apiUri: process.env.NYLAS_API_URI,
}

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

const askQuestion = (question) => {
  return new Promise((resolve) => {
    rl.question(question, (answer) => {
      resolve(answer);
    });
  });
};

const nylas = new Nylas(NylasConfig)
var free_slots = [];
var counter = 1;

const main = async () => {
  const meeting_length = await askQuestion('How many minutes for each time slot? (Multiple of 5): ');
  const date = Date()
  const new_date = new Date(date)
  var start_time = new Date(new_date.getFullYear(), 
                            new_date.getMonth(), new_date.getUTCDate(), 9, 0, 0, 0);	
  var end_time = new Date(new_date.getFullYear(), 
                          new_date.getMonth(), new_date.getUTCDate(), 17, 0, 0, 0);
  try {
    const calendar = await nylas.calendars.getAvailability({
      requestBody: {
        startTime: start_time.getTime() / 1000,
        endTime: end_time.getTime() / 1000,
        duration_minutes: parseInt(meeting_length),
        participants: [{email: process.env.NYLAS_GRANT_ID}]
      }
    })
    
    calendar['data']['timeSlots'].forEach((timeslot) => {
		free_slots.push(timeslot);
    });
    
    free_slots.forEach((slot) => {
	    var auxStartTime = new Date(slot['startTime'] * 1000);
		var auxEndTime = new Date(slot['endTime'] * 1000);
		console.log(`${counter}) From: ${auxStartTime.toLocaleTimeString()} To: ${auxEndTime.toLocaleTimeString()}`);
		counter++;		
	});
        
    const chosen_slot = await askQuestion('Which slot would you like?: ');
    const guest_email = await askQuestion('With whom are you meeting? Enter a valid email address: ');
    const title = await askQuestion('What\'s the meeting title?: ');
    var times = 0;
    
    times = free_slots[parseInt(chosen_slot) - 1];
 
    const event = await nylas.events.create({
      identifier: process.env.NYLAS_GRANT_ID,
      requestBody: {
        title: title,
        busy: true,
        when: {
          startTime: times['startTime'],
          endTime: times['endTime'],
        },
        participants: [{email: guest_email}]
      },
      queryParams: {
        calendarId: process.env.NYLAS_CALENDAR_ID,
      },
    })

    console.log('Event:', event);
  
    } catch (error) {
    console.error('Error fetching availability:', error)
    }
  rl.close();
};

main();	
require 'nylas'
require 'date'
require 'dotenv/load'

nylas = Nylas::Client.new(
  api_key: ENV["NYLAS_API_KEY"],
  api_uri: ENV["NYLAS_API_URI"]
)

query_params = {
  calendar_id: ENV["NYLAS_CALENDAR_ID"]	
}

puts "How many minutes for each time slot? (Multiple of 5): "
meeting_length = gets
free_slots = Array.new
counter = 1

today = Date.today
start_time = Time.local(today.year, today.month, today.day, 8, 0,0).strftime("%s").to_i
end_time = Time.local(today.year, today.month, today.day, 17, 0,0).strftime("%s").to_i

request_body = {
	"participants": [
	{
		"email": ENV["NYLAS_GRANT_ID"],
		"calendar_ids": [
			ENV["NYLAS_CALENDAR_ID"]
		],
	}	
	],
	"start_time": start_time,
	"end_time": end_time,
	"duration_minutes": meeting_length.to_i,
}

available, _request_ids = nylas.calendars.get_availability(request_body: request_body)
available[:time_slots].each {|slots|
  free_slots.push(slots)
}

free_slots.each {|slot|
	puts "#{counter}) From: #{Time.at(slot[:start_time]).to_datetime.strftime("%H:%M:%S")}" \
	     " To: #{Time.at(slot[:end_time]).to_datetime.strftime("%H:%M:%S")}"
	counter = counter + 1
}

puts "Which slot would you like?: "
chosen_slot = gets
puts "With whom are you meeting? Enter a valid email address: "
guest_email = gets.chomp
puts "What's the meeting title?: "
title = gets

times = free_slots[chosen_slot.to_i - 1]

request_body = {
    busy: true,
	when: {
		start_time: times[:start_time].to_i,
		end_time: times[:end_time].to_i
	},
	title: title,
	participants: [{
		email: guest_email,
		status: "noreply"
	}]
}

puts ""

event, _request_id = nylas.events.create(
		identifier: ENV["NYLAS_GRANT_ID"], 
		query_params: query_params,
		request_body: request_body)
puts JSON.pretty_generate(event)
from dotenv import load_dotenv
import os
import sys
import pendulum
from nylas import Client
from nylas.models.availability import GetAvailabilityRequest

load_dotenv()

nylas = Client(
    os.environ.get("NYLAS_API_KEY"),
    os.environ.get("NYLAS_API_URI")
)

meeting_length = input("How many minutes for each time slot? (Multiple of 5): ")
free_slots = []
counter = 1

now = pendulum.now()

start_time = pendulum.datetime(now.year, now.month, now.day, 13, 0, 0)
end_time = pendulum.datetime(now.year, now.month, now.day, 22, 0, 0)

request_body = GetAvailabilityRequest(
    participants = [
    {
        "email": os.environ.get("NYLAS_GRANT_ID"),
        "calendar_ids": [
            os.environ.get("NYLAS_CALENDAR_ID")
        ],
    }
    ],
        duration_minutes = int(meeting_length),
        start_time = start_time.int_timestamp,
        end_time = end_time.int_timestamp
)

availability, _request_ids = nylas.calendars.get_availability(request_body)
for slots in availability.time_slots:
	free_slots.append(slots)
	
for slot in free_slots:
    ts = pendulum.from_timestamp(slot.start_time, now.timezone.name).strftime("%H:%M:%S")
    te = pendulum.from_timestamp(slot.end_time, now.timezone.name).strftime("%H:%M:%S")
    print(f"{counter}) From: {ts} To: {te}")
    counter += 1

chosen_slot = input("Which slot would you like?: ")
guest_email = input("With whom are you meeting? Enter a valid email address: ")
title = input("What's the meeting title?: ")

times = free_slots[int(chosen_slot) - 1]

events = nylas.events.create(
  os.environ.get("NYLAS_GRANT_ID"),
  request_body={
    "title": title,
    "busy": True,
    "when": {
      "start_time": times.start_time,
      "end_time": times.end_time
    },
	"participants": [{
		"email": guest_email, 
		"status": "noreply"
	}]    
  },
  query_params={
    "calendar_id": os.environ.get("NYLAS_CALENDAR_ID")
  }
)

print("\n")
print(events)
import com.nylas.NylasClient;
import com.nylas.models.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.io.Console;
import java.util.ArrayList;
import java.util.List;
import java.text.SimpleDateFormat;
import io.github.cdimascio.dotenv.Dotenv;

public class DynamicScheduling {
    public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
        Dotenv dotenv = Dotenv.load();
        NylasClient nylas = new NylasClient.Builder(dotenv.get("NYLAS_API_KEY"))
                .apiUri(dotenv.get("NYLAS_API_URI")).build();

        Console console = System.console();
        System.out.print("How many minutes for each time slot? (Multiple of 5): ");
        String meeting_length = console.readLine();
        int counter = 1;

        LocalDate today = LocalDate.now();
        Instant sixPmUtc = today.atTime(13, 0).toInstant(ZoneOffset.UTC);
        long startTime = sixPmUtc.getEpochSecond();
        Instant sixPmUtcPlus = sixPmUtc.plus(9, ChronoUnit.HOURS);
        long endTime = sixPmUtcPlus.getEpochSecond();

        List<String> participant_calendars = new ArrayList<>();
        participant_calendars.add(dotenv.get("NYLAS_CALENDAR_ID"));
        AvailabilityParticipant participant = new AvailabilityParticipant(dotenv.get("NYLAS_GRANT_ID"),
                participant_calendars, null);
        List<AvailabilityParticipant> participants = new ArrayList<>();
        participants.add(participant);

        GetAvailabilityRequest availability = new GetAvailabilityRequest(
                Math.toIntExact(startTime),
                Math.toIntExact(endTime), participants, Integer.parseInt(meeting_length), null,
                null, null, null);

        Response<GetAvailabilityResponse> available =
                nylas.calendars().getAvailability(availability);

        assert available.getData().getTimeSlots() != null;
        List<TimeSlot> free_slots = new ArrayList<TimeSlot>(available.getData().getTimeSlots());

        for(TimeSlot slot : free_slots){
            String initDate = new SimpleDateFormat("HH:mm:ss").
                    format(new java.util.Date((slot.getStartTime() * 1000L)));
            String endDate = new SimpleDateFormat("HH:mm:ss").
                    format(new java.util.Date((slot.getEndTime() * 1000L)));
            System.out.println(counter + ") From " + initDate + " To: " + endDate);
            counter++;
        }

        System.out.print("Which slot would you like?: ");
        String chosen_slot = console.readLine();
        System.out.print("With whom are you meeting? Enter a valid email address: ");
        String guest_email = console.readLine();
        System.out.print("What's the meeting title?: ");
        String title = console.readLine();

        TimeSlot times = free_slots.get(Integer.parseInt(chosen_slot) - 1);

        CreateEventRequest.When.Timespan timespan = new CreateEventRequest.
                When.Timespan.
                Builder(Math.toIntExact(times.getStartTime()), Math.toIntExact(times.getEndTime())).
                build();

        List<CreateEventRequest.Participant> participants_list = new ArrayList<>();
        participants_list.add(new CreateEventRequest.
                Participant(guest_email, ParticipantStatus.NOREPLY,
                "", "", ""));

        CreateEventRequest createEventRequest = new CreateEventRequest.Builder(timespan)
                .participants(participants_list)
                .busy(Boolean.TRUE)
                .title(title)
                .build();

        CreateEventQueryParams createEventQueryParams =
                new CreateEventQueryParams.Builder(dotenv.get("NYLAS_CALENDAR_ID")).build();

        Event event = nylas.events().create(
                dotenv.get("NYLAS_GRANT_ID"),
                createEventRequest,
                createEventQueryParams).getData();

        System.out.println(event);
    }
}

Additional Customization Options

Using Nylas Scheduler for advanced time blocking

Nylas offers robust endpoints for event creation and management, but they require manual setup and ongoing maintenance. For a simpler, ready-made solution, the Nylas Scheduler provides an easy-to-implement interface with powerful features for advanced time blocking.

Here’s how to get started with the Scheduler:

  • Register a Callback URI:
  1. Go to the Nylas Dashboard.
  2. Navigate to Hosted Authentication → Callback URIs.
  3. Add your application’s callback URI with the following settings:
  • As the earlier code samples demonstrated, Nylas offers powerful endpoints for managing event creation and manipulation. However, these require manual effort and significant maintenance. Fortunately, Nylas also provides the Scheduler—a flexible, ready-made solution that’s easy to implement and includes numerous advanced features to simplify event management.
  • Let’s implement our Scheduler by creating a Scheduler Editor and a Scheduler Page.
  • First, it’s important to register a callback URI. To do this, go to the Nylas Dashboard and follow these steps::
    • Click Hosted Authentication in the left navigation, and click Callback URIs.
    • Click Add a callback URI, and enter your application’s callback URI.
    • Select the JavaScript platform.
    • For URL, enter http://localhost:<PORT>/scheduler-editor.
    • For Origin, enter http://localhost:<PORT>.
    • Click Add callback URI.
  • Once registered, you can create a “scheduler-editor.html” with this code:
<!-- scheduler-editor.html -->

<!DOCTYPE html>
<html class="h-full bg-white" lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Nylas Scheduler Editor Component</title>

  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
  <link
    href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap"
    rel="stylesheet"
  />

  <script src="https://cdn.tailwindcss.com"></script>

  <style type="text/css">
    body {
      font-family: "Inter", sans-serif;
    }
  </style>
</head>

<body class="h-full">
  <div class="grid h-full place-items-center">
    <!-- Add the Nylas Scheduler Editor component -->
    <nylas-scheduler-editor />
  </div>

  <!-- Configure the Nylas Scheduler Editor component -->
  <script type="module">

    import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduler-editor/nylas-scheduler-editor.es.js";

    defineCustomElement(); 
    
    const schedulerEditor = document.querySelector("nylas-scheduler-editor");
    schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`;
    schedulerEditor.nylasSessionsConfig = {
      clientId: "NYLAS_CLIENT_ID", // Replace with your Nylas client ID from the previous section
      redirectUri: `${window.location.origin}/scheduler-editor`,
      domain: "https://api.us.nylas.com/v3", // or 'https://api.eu.nylas.com/v3' for EU data center
      hosted: true,
      accessType: "offline",
    };
    schedulerEditor.defaultSchedulerConfigState = {
      selectedConfiguration: {
        requires_session_auth: false, // Creates a public configuration which doesn't require a session
        scheduler: { // The callback URLs to be set in email notifications
          rescheduling_url: `${window.location.origin}/reschedule/:booking_ref`, // The URL of the email notification includes the booking reference
          cancellation_url: `${window.location.origin}/cancel/:booking_ref`
        }
      }
    };
  </script>
</body>
</html>      

  • Next, create another file named `index.html` and add the following source code::
<!-- index.html -->

<!DOCTYPE html>
<html class="h-full bg-white" lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Nylas Scheduling Component</title>

  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
  <link
    href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap"
    rel="stylesheet"
  />

  <script src="https://cdn.tailwindcss.com"></script>

  <style type="text/css">
    body {
      font-family: "Inter", sans-serif;
    }
  </style>
</head>

<body>
  <div class="grid gap-0 h-full place-items-center">
    <div class="grid gap-4">
      <!-- A button to view the Scheduler Editor -->
      <a
        href="scheduler-editor.html"
        class="w-fit border border-blue-500 hover:bg-blue-100 text-blue-500 font-bold py-2 px-4 rounded"
      >
        View Scheduler Editor
      </a>

      <!-- Add the Nylas Scheduling Component -->
      <nylas-scheduling></nylas-scheduling>
    </div>
  </div>

  <!-- Configure the Nylas Scheduling Component with a scheduler configuration ID -->
  <script type="module">

    import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduling/nylas-scheduling.es.js";

    defineCustomElement();

    const nylasScheduling = document.querySelector("nylas-scheduling");

    // Set the scheduler api url based on the data center
    nylasScheduling.schedulerApiUrl = "https://api.us.nylas.com"; // or 'https://api.eu.nylas.com' for EU data center

    // Get the scheduler configuration ID from the URL ?config_id=NYLAS_SCHEDULER_CONFIGURATION_ID
    const urlParams = new URLSearchParams(window.location.search);

    // If not config_id exists, throw a console.error
    if (!urlParams.has("config_id")) {
      console.error(
        "No scheduler configuration ID found in the URL. Please provide a scheduler configuration ID."
      );
    }

    // Set the scheduler configuration ID
    nylasScheduling.configurationId = urlParams.get("config_id");
  </script>
</body>
</html>   

  • To run the scheduler, open a terminal window and execute the appropriate command.
npx serve --listen 4567
  • Once the scheduler is running, open your preferred browser and navigate to the specified URL.
http://localhost:4567/
  • Next, configure the scheduler by clicking the View Scheduler Editor button.
  • Log in to the scheduler and grant it permission to access your calendar.
  • After logging in, create your first scheduling page by following the on-screen prompts.
  • Let’s create it.
  • Once the scheduling page is created, it can be shared with others to allow them to book meetings directly.

For detailed instructions and further customization options, refer to the Nylas Scheduler Documentation.

Automating recurring time slots (e.g., weekly team syncs or daily breaks)

Nylas makes it easy to create recurring events using the RRULE parameter. You can specify recurrence patterns such as daily, weekly, or monthly, saving time when blocking repetitive time slots.

Examples of recurring time slots include:

  • Weekly team syncs (e.g., every Monday at 10 AM).
  • Daily breaks (e.g., lunch break from 12 PM to 1 PM).

Node.js

Ruby

Python

Java

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)

const date = Date()
const new_date = new Date(date)
var start_time = new Date(new_date.getFullYear(), 
                          new_date.getMonth(), new_date.getUTCDate(), 13, 0, 0, 0);	
var end_time = new Date(new_date.getFullYear(), 
                          new_date.getMonth(), new_date.getUTCDate(), 14, 0, 0, 0);

async function createAnEvent() {
  try {
    const event = await nylas.events.create({
      identifier: process.env.NYLAS_GRANT_ID,
      requestBody: {
        title: 'Lunch time',
        description: "I'm having lunch",
        busy: true,
        when: {
          startTime: start_time.getTime() / 1000,
          endTime: end_time.getTime() / 1000,
        },
	    recurrence: [
          'RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR'
        ],
        participants: [{email: "[email protected]"}]
      },
      queryParams: {
        calendarId: process.env.NYLAS_CALENDAR_ID,
      },
    })

    console.log('Event:', event);
  } catch (error) {
    console.error('Error creating event:', error)
  }
}

createAnEvent()
require 'nylas'
require 'dotenv/load'

nylas = Nylas::Client.new(
  api_key: ENV["NYLAS_API_KEY"],
  api_uri: ENV["NYLAS_API_URI"]
)

query_params = {
  calendar_id: ENV["NYLAS_CALENDAR_ID"]	
}

today = Date.today

start_time = Time.local(today.year, today.month, today.day, 13, 0,0).strftime("%s").to_i
end_time = Time.local(today.year, today.month, today.day, 14, 0,0).strftime("%s").to_i

request_body = {
    busy: true,
	when: {
		start_time: start_time.to_i,
		end_time: end_time.to_i
	},
	title: "Lunch time",
	description: "I'm having lunch",
	participants: [{
		name: "Swag",
		email: "[email protected]", 
		status: "noreply"
	}],
	"recurrence": [
      "RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR"
    ]
}

event, _request_id = nylas.events.create(
		identifier: ENV["NYLAS_GRANT_ID"], 
		query_params: query_params,
		request_body: request_body)
puts JSON.pretty_generate(event)
from dotenv import load_dotenv
import pendulum
import os
from nylas import Client

load_dotenv()

nylas = Client(
    api_key = os.environ.get("NYLAS_API_KEY"),
    api_uri = os.environ.get("NYLAS_API_URI")
)

grant_id = os.environ.get("NYLAS_GRANT_ID")

now = pendulum.now()

start_time = pendulum.datetime(now.year, now.month, now.day, 13, 0, 0)
end_time = pendulum.datetime(now.year, now.month, now.day, 14, 0, 0)

events = nylas.events.create(
  grant_id,
  request_body={
    "title": "Lunch time",
    "location": "I'm having lunch",
    "busy": True,
    "when": {
      "start_time": start_time.int_timestamp,
      "end_time": end_time.int_timestamp
    },
	"participants": [{
		"name": "Swag",
		"email": "[email protected]", 
		"status": "noreply"
	}],
	"recurrence": [
    "RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR"
    ]
  },
  query_params={
    "calendar_id": os.environ.get("NYLAS_CALENDAR_ID")
  }
)

print(events)
import com.nylas.NylasClient;
import com.nylas.models.*;
import io.github.cdimascio.dotenv.Dotenv;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.time.LocalDate;

public class RecurringEvent {
    public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
        Dotenv dotenv = Dotenv.load();
        NylasClient nylas = new NylasClient.Builder(dotenv.get("NYLAS_API_KEY"))
                                           .apiUri(dotenv.get("NYLAS_API_URI")).build();

        LocalDate today = LocalDate.now();
        Instant sixPmUtc = today.atTime(1, 0).toInstant(ZoneOffset.UTC);
        long startTime = sixPmUtc.getEpochSecond();
        Instant sixPmUtcPlus = sixPmUtc.plus(1, ChronoUnit.HOURS);
        long endTime = sixPmUtcPlus.getEpochSecond();

        String title = "Lunch time";
        String description = "I'm having lunch";

        CreateEventRequest.When.Timespan timespan = new CreateEventRequest.
                When.Timespan.
                Builder(Math.toIntExact(startTime), Math.toIntExact(endTime)).
                build();

        List<CreateEventRequest.Participant> participants_list = new ArrayList<>();
        List<String> recurrence = new ArrayList<>();
        recurrence.add("RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR");

        participants_list.add(new CreateEventRequest.
                Participant("[email protected]", ParticipantStatus.NOREPLY,
                "Swag", "", ""));

        CreateEventRequest createEventRequest = new CreateEventRequest.Builder(timespan)
                .participants(participants_list)
                .busy(Boolean.TRUE)
                .title(title)
                .description(description)
                .recurrence(recurrence)
                .build();

        CreateEventQueryParams createEventQueryParams = new
                CreateEventQueryParams.Builder(dotenv.get("NYLAS_CALENDAR_ID")).build();

        Event event = nylas.events().create(
                dotenv.get("NYLAS_GRANT_ID"),
                createEventRequest,
                createEventQueryParams).getData();

        System.out.println(event);
    }
}


By leveraging RRULE, you can ensure consistent time blocking without manual intervention. 

Setting permissions to control the visibility of blocked times (e.g., private or public)

Nylas allows you to control the visibility of events programmatically by setting the visibility field in the event request body.

visibility: Public|Private

Options include:

  • Private: Event details remain hidden; others only see the time as “busy.”
  • Public: Event details, such as the title and description, are visible to others.

If the visibility parameter is not specified, Nylas will default to the provider’s visibility settings (Google Calendar or Outlook).

This feature is particularly useful for balancing transparency with privacy, ensuring that sensitive events remain private while maintaining an accurate calendar view.

By combining these customization options, you can maximize the flexibility and efficiency of your time-blocking strategy with Nylas.

Unique features of Nylas for time slot management

1. Cross-Calendar Consistency: Manage Outlook and Google Calendar from a Single Interface

Nylas allows seamless management of both Outlook and Google Calendar through a unified interface. If you’ve set up connectors for both platforms, you can:

  • Use their respective emails to access calendar data from each provider.
  • Label events to indicate the specific calendar they belong to, making it easier to organize and differentiate schedules.
  • When creating new events, specify the desired calendar provider (Google or Outlook) or choose to create the event on multiple calendars simultaneously.

This ensures consistency and eliminates the need to switch between separate systems when managing availability across different platforms.

2. Real-Time Updates Using Nylas Webhooks

Nylas webhooks provide real-time notifications whenever calendar events are created, updated, or deleted, enabling dynamic time slot management.

Setting Up Webhooks:

  • Navigate to the Notifications section on the Nylas Dashboard.
  • Click on Create Webhook and select the events you want to monitor.
  • A hosted webhook URL is required to receive and process the notifications.
  • Webhooks can also be configured programmatically, allowing you to automate real-time updates for event changes.

Node.js

Ruby

Python

Java

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)

const createWebhook = async () => {
  try {
    const webhook = await nylas.webhooks.create({
      requestBody: {
        triggerTypes: [WebhookTriggers.EventCreated],
        webhookUrl: process.env.WEBHOOK_URL,
        description: "My first webhook",
        notificationEmailAddress: process.env.EMAIL,
      }
    })

    console.log("Webhook created:", webhook)
  } catch (error) {
    console.error("Error creating webhook:", error)
  }
}

createWebhook()
require 'nylas'

nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")

request_body = {
  trigger_types: [Nylas::WebhookTrigger::EVENT_CREATED],
  webhook_url: "<WEBHOOK_URL>",
  description: 'My first webhook',
  notification_email_address: ["EMAIL_ADDRESS"]
}

begin
  webhooks, = nylas.webhooks.create(request_body: request_body)
  
  puts "Webhook created: #{webhooks}"
rescue StandardError => ex
  puts "Error creating webhook: #{ex}"
end

from dotenv import load_dotenv
import os
import sys
from nylas import Client
from nylas.models.webhooks import WebhookTriggers

load_dotenv()

nylas = Client(
  os.environ.get('NYLAS_API_KEY'),
  os.environ.get('NYLAS_API_URI')
)

grant_id = os.environ.get("NYLAS_GRANT_ID")
webhook_url = os.environ.get("WEBHOOK_URL")

email = os.environ.get("EMAIL")

webhook = nylas.webhooks.create(
  request_body={
    "trigger_types": [WebhookTriggers.EVENT_CREATED],
    "webhook_url": webhook_url,
    "description": "My first webhook",
    "notification_email_address": email,
  }
)

print(webhook)
import com.nylas.NylasClient;
import com.nylas.models.*;
import com.nylas.resources.Webhooks;
import com.nylas.models.WebhookTriggers;
import java.util.*;

public class webhooks {
  public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
    NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

    List<WebhookTriggers> triggers = new ArrayList<>();
    triggers.add(WebhookTriggers.EVENT_CREATED);

    CreateWebhookRequest webhookRequest = new CreateWebhookRequest(triggers, "<WEBHOOK_URL>",
        "My first webhook", "<EMAIL_ADDRESS>");

    try {
      Response<WebhookWithSecret> webhook = new Webhooks(nylas).create(webhookRequest);

      System.out.println(webhook.getData());
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
}

Syncing blocked slots across multiple accounts for users with several calendars

For users managing multiple calendars across different providers, Nylas enables efficient synchronization of blocked time slots. By leveraging the Availability API, you can:

  • Access calendars from Google, Outlook, or both providers to retrieve a consolidated list of available time slots.
  • Read event information across multiple accounts and merge the data to create a unified view of blocked and available times.

This functionality is particularly useful for professionals balancing multiple commitments, as it allows seamless cross-calendar time management while preventing double-booking.

Practical Use Cases

Entrepreneurs Managing Overlapping Commitments

Entrepreneurs often juggle multiple priorities and calendars. Nylas helps them streamline scheduling by:

  • Dynamic Scheduling for On-Demand Services
    For businesses offering on-demand appointments, Nylas provides real-time updates to calendars, ensuring accurate and reliable bookings.
  • Coordinating Across Multiple Calendars
    Consolidate availability from work and personal calendars to prevent double-booking and manage time effectively.
  • Avoiding Overbooking for High-Traffic Calendars
    Use the Free/Busy endpoint to dynamically block slots during peak times, ensuring smooth operations without overloading schedules.

Teams Ensuring Meeting-Free Focus Times

In collaborative environments, uninterrupted time for deep work is essential. Nylas enables teams to:

  • Blocking Focus Time for Deep Work
    Automate the creation of focus periods to allow individuals or teams to work without distractions.
  • Automating Meeting-Free Zones
    Set rules to block recurring meeting-free times, such as lunch breaks or specific hours of the day, promoting better work-life balance.
  • Scheduling Recurring Team Events
    Use the recurring event feature to automate weekly syncs, standups, or other repetitive meetings, ensuring consistency and saving time.

Professionals Balancing Personal and Work-Life Commitments

Professionals managing work and personal responsibilities can maintain balance with features like:

  • Managing Shared Resources
    Block time for shared resources such as conference rooms or team equipment, preventing scheduling conflicts and ensuring availability.
  • Supporting Customer-Facing Scheduling Apps
    Developers creating booking tools can integrate Nylas Scheduler to allow clients and colleagues to book meetings seamlessly, saving time and improving user experience.
  • Customizing Personal and Professional Schedules
    Block time for personal commitments, ensuring personal appointments don’t conflict with professional obligations.

These practical use cases demonstrate how Nylas can empower individuals and teams to optimize their calendars, reduce scheduling conflicts, and maintain productivity.

Related resources

How to Solve Webhook Integration Challenges with PubSub Notification Channel

Key Takeaways This article addresses the challenges of webhook integration and introduces the PubSub Notification…

How to Send Emails Using an API

Key Takeaways This post will provide a complete walkthrough for integrating an email API focused…

How to build a CRM in 3 sprints with Nylas

What is a CRM? CRM stands for Customer Relationship Management, and it’s basically a way…