Guide

Set and Respect Calendar Working Hours

A 7am booking from an automation looks like a bug, not a meeting. This guide keeps bookings inside working hours: events create validates each booking against them and rejects out-of-hours times, while you bound availability find's search window to your workday so results stay in hours, and --ignore-working-hours overrides when an after-hours slot is intentional.

Written by Caleb Geene Director, Site Reliability Engineering

Reviewed by Qasim Muhammad

VerifiedCLI 3.1.17 · Google, Outlook · last tested June 9, 2026

What are calendar working hours and where do they live?

Calendar working hours are the recurring daily windows when you accept meetings, stored on the provider account, not in the CLI. Google keeps them in your Calendar settings; Microsoft 365 stores them on the mailbox as a workingHours object with days, start, end, and timezone. The tool reads that source of truth.

The default 9-to-5 window is 40 hours a week, which means roughly 76% of a 168-hour week is off-limits to a scheduler. A booking placed at 7am or 9pm is almost always a timezone bug or an automation that ignored the boundary. Google exposes the same data through the freebusy API, and Microsoft Graph returns it on the mailboxSettings resource, so the CLI honors whichever provider backs the grant instead of asking you to redefine the hours locally.

How do I find slots that stay inside working hours?

Run nylas calendar availability find with --participants: it returns the windows when every attendee is free within the --start/--end range you pass. Set that range to your workday so the results stay in hours. A 9am-to-5pm search across two people drops to the hours they actually share, often fewer than 10 slots a day.

# 30-minute in-hours slots both people share, next 5 business days
nylas calendar availability find \
  --participants you@company.com,teammate@company.com \
  --duration 30 --interval 30 \
  --start "monday 9am" --end "friday 5pm" \
  --json

The --interval flag snaps results to clean boundaries, so 30 returns slots on the hour and half-hour rather than odd 12-minute gaps. Because you bounded the search to 9am–5pm, the results already sit inside the workday; widen --start/--end only when you mean to look outside it. The real enforcement happens at booking time, covered next.

Why does events create reject some bookings?

The nylas calendar events create command validates the requested start and end against the organizer's working hours before it writes anything. A 7am start fails validation and the event is never created, which stops a buggy timezone offset from booking a meeting nobody can attend. This check runs in well under one second.

# Inside working hours — succeeds
nylas calendar events create \
  --title "Sprint planning" \
  --start "2026-06-15 10:00" --end "2026-06-15 10:30" \
  --participant teammate@company.com

# 7am start — rejected by working-hours validation, no event written
nylas calendar events create \
  --title "Too early" \
  --start "2026-06-15 07:00" --end "2026-06-15 07:30" \
  --participant teammate@company.com

Pairing the two commands closes the loop: take the first slot from availability find and pass it straight to events create. The find step never hands you an out-of-hours time, and the create step rejects one if a script computes the start independently, so two layers guard the same boundary.

How do I book outside working hours on purpose?

Pass --ignore-working-hours to events create to skip the validation for one booking. A 6am call with a team eight timezones away is a legitimate exception, and the flag lets that single event through without changing the account's 40-hour working-hours window for every other booking.

# Intentional early call across timezones — override the guardrail
nylas calendar events create \
  --title "APAC sync (6am)" \
  --start "2026-06-16 06:00" --end "2026-06-16 06:30" \
  --participant apac-team@company.com \
  --ignore-working-hours

Use the override per command rather than as a default. If a script always passes --ignore-working-hours, the guardrail is effectively off and a timezone bug can book at 3am again. Keep the flag for the one or two genuine exceptions a week, not the 200 routine bookings around them.

How do I keep an automation inside working hours?

Chain availability find into events create and, with the search window bounded to your workday, the automation books only in-hours slots. The script below finds the first 30-minute window both people share, books it, and exits cleanly when zero shared in-hours slots exist that day — a real case when two calendars are full.

#!/usr/bin/env bash
set -euo pipefail
PARTICIPANTS="you@company.com,teammate@company.com"

SLOTS=$(nylas calendar availability find \
  --participants "$PARTICIPANTS" \
  --duration 30 --interval 30 \
  --start "monday 9am" --end "monday 5pm" --json)

[ "$(echo "$SLOTS" | jq 'length')" -eq 0 ] && { echo "no in-hours slot today"; exit 0; }

START=$(echo "$SLOTS" | jq -r '.[0].start_time')
END=$(echo "$SLOTS" | jq -r '.[0].end_time')

# No --ignore-working-hours: create still validates the slot is in-hours
nylas calendar events create --title "Auto-booked sync" \
  --start "$START" --end "$END" \
  --participant teammate@company.com

Leaving --ignore-working-hours off the create call is deliberate: even though you bounded the find window to the workday, the create-time check is a second line of defense if a future edit computes the start a different way. Two independent guards catch the same 6am mistake.

Next steps