Guide

Manage Outlook Calendar from the CLI

Create, list, update, and delete Microsoft 365 calendar events from your terminal. No Azure AD app registration, no Graph API boilerplate. The Nylas CLI handles OAuth2 and calendar CRUD with single-line commands. Works with Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP.

Written by Caleb Geene Director, Site Reliability Engineering

Reviewed by Hazik

VerifiedCLI 3.1.1 · Outlook Calendar · last tested April 11, 2026

Most Fortune 500 companies run on Microsoft 365

According to Microsoft's Ignite 2024 announcement, nearly 70% of the Fortune 500 use Microsoft 365 Copilot alone — meaning overall Microsoft 365 adoption is even higher. That means most enterprise calendar workflows hit the Graph API sooner or later. And the Graph API isn't casual. You register an Azure AD application, configure delegated permissions like Calendars.ReadWrite, handle OAuth2 token exchange with PKCE, then call GET /me/events with a Bearer token. That's four steps before your first query.

Application permissions (the daemon/service auth flow) require a different grant type entirely, and according to Microsoft's Graph API calendar documentation, most calendar operations need delegated permissions unless you're building a background service with admin consent. The Nylas CLI collapses all of this into nylas init.

Graph API vs. Nylas CLI

TaskMicrosoft Graph APINylas CLI
Initial setupRegister Azure AD app, configure permissions, get tenant IDbrew install nylas/nylas-cli/nylas && nylas init
AuthenticationImplement OAuth2 PKCE flow, handle token refreshnylas auth login (browser-based OAuth2)
List eventsGET /me/events with Bearer token and query paramsnylas calendar events list
Create eventPOST /me/events with JSON bodynylas calendar events create --title "..."
Book a roomPOST /me/findRooms + add room as attendee--participant room@company.com
Check availabilityPOST /me/calendar/getSchedule with JSON bodynylas calendar availability check
Provider lock-inMicrosoft onlyWorks with Google, Yahoo, iCloud, Exchange, IMAP too
Time to first API call15-30 minutesUnder 2 minutes

1. Install and connect your Microsoft 365 account

Install via Homebrew (other methods here) and run the init wizard:

brew install nylas/nylas-cli/nylas
nylas init

The wizard creates a Nylas account and walks you through connecting Microsoft 365 via OAuth2. Unlike Graph API setup, there's no Azure AD app registration, no tenant configuration, no .env files.

2. Core Outlook calendar commands

Most Microsoft 365 automations still come down to four operations: list the right calendar, create an event in the right mailbox, update the exact occurrence you care about, and delete only when the mailbox policy allows it. The Outlook-specific wrinkle is that you often need to target a delegated calendar or shared identity rather than your own default calendar.

# List upcoming events on your default calendar
nylas calendar events list --days 14

# Create an event on a delegated executive calendar
nylas calendar events create \
  --calendar-id cal_exec_assistant \
  --title "Board Prep" \
  --start "2026-04-10 09:00" \
  --end "2026-04-10 10:00" \
  --participant chief-of-staff@company.com

# Reschedule a Microsoft 365 event
nylas calendar events update event_abc123 \
  --start "2026-04-10 11:00" \
  --end "2026-04-10 12:00"

# Delete an event by ID
nylas calendar events delete event_abc123

If the mailbox owner delegated access through Outlook but you still cannot write to the calendar, verify the exact calendar_id and mailbox policy before blaming the command. That is a Microsoft 365 permissions problem, not a CLI syntax problem.

3. Shared calendars and delegation

Microsoft 365 organizations rely heavily on shared calendars for teams, projects, and departments. According to Microsoft's Azure AD permission model documentation, accessing another user's calendar requires either delegated permissions with the user's consent or application-level permissions granted by an admin. The CLI abstracts this once your grant has the right scopes.

# See all calendars (personal + shared + delegated)
nylas calendar list

# List events on a shared team calendar
nylas calendar events list --calendar-id cal_shared_marketing

# Create an event on a delegated calendar
nylas calendar events create \
  --calendar-id cal_exec_assistant \
  --title "Board Prep" \
  --start "2026-04-10 09:00" \
  --end "2026-04-10 10:00"

4. Executive assistant and delegated-calendar workflows

Outlook calendar automation is often less about room resources and more about one person acting on behalf of another. Executive assistants, chiefs of staff, recruiting coordinators, and operations leads commonly create or move meetings on delegated calendars all day. That pattern is much more Outlook-specific than the iCloud or Yahoo versions of this guide.

# Pull the exact delegated calendar IDs you can access
nylas calendar list --json | \
  jq -r '.[] | "\(.name) | read_only=\(.read_only) | id=\(.id)"'

# Create a meeting on an executive's delegated calendar
nylas calendar events create \
  --calendar-id cal_exec_assistant \
  --title "Board Prep" \
  --start "2026-04-10 09:00" \
  --end "2026-04-10 10:00" \
  --participant chief-of-staff@company.com

If the mailbox owner delegated access through Outlook but you still cannot write to the event, the issue is usually permission scope or mailbox policy, not the CLI command.

5. Teams meeting links

When you create an event with participants on a Microsoft 365 account, Teams meeting links can be auto-generated. The conferencing details appear in the event response. Extract them with --json and jq:

nylas calendar events create \
  --title "Weekly Standup" \
  --start "2026-04-07 09:00" \
  --end "2026-04-07 09:30" \
  --participant dev-team@company.com \
  --json | jq '.conferencing'

This replaces the manual Graph API flow of creating an onlineMeeting resource and attaching it to the event.

6. Outlook categories and recurring events

Outlook calendars support color-coded categories (Blue, Red, Green, or custom labels like "Client Meetings"). These categories sync across Outlook desktop, web, and mobile. When you fetch events as JSON, each event's metadata includes its category assignments:

# View event details including categories
nylas calendar events list --json | jq '.[] | {title: .title, categories: .metadata}'

Recurring events

Outlook represents recurring events using RRULE (RFC 5545). A weekly standup, for instance, is a single master event with an RRULE like FREQ=WEEKLY;BYDAY=MO;COUNT=52. When you list events, the CLI returns individual occurrences, not the raw RRULE. Updating a single occurrence changes only that instance; updating the master event changes the series.

# Update a single occurrence
nylas calendar events update event_abc123_20260407 \
  --title "Standup (Cancelled)" \
  --start "2026-04-07 09:00" \
  --end "2026-04-07 09:00"

# Delete an entire recurring series by its master ID
nylas calendar events delete event_abc123

When to use the Exchange guide instead

If your main problem is room mailboxes, on-prem Exchange, hybrid coexistence, or EWS migration pressure, you are really in Exchange territory rather than pure Outlook/M365 tenant workflows. Use the Exchange calendar guide for that estate-management path.

7. Check availability and find time

Free/busy checks work across calendars without parsing iCal feeds or calling the Graph API's getSchedule endpoint:

# Your availability for the next 7 days
nylas calendar availability check

# Find a 30-minute slot with two coworkers
nylas calendar availability find \
  --participants alice@company.com,bob@company.com \
  --duration 30

Example output

$ nylas calendar availability find --participants alice@company.com,bob@company.com --duration 30

Available slots:

1. Tue, Apr 1, 2026, 11:00 AM - 11:30 AM
   All participants free

2. Tue, Apr 1, 2026, 3:00 PM - 3:30 PM
   All participants free

Found 2 slot(s)

8. JSON output for scripting

Outlook teams usually use JSON output for morning briefings, room audits, executive assistant workflows, and escalation tooling. The payload matters more than the rendered table when you are feeding Microsoft 365 state into another system:

# Count today's meetings
nylas calendar events list --days 1 --json | jq length

# Morning briefing script
#!/bin/bash
count=$(nylas calendar events list --days 1 --json | jq length)
echo "You have $count meetings today."
if [ "$count" -gt 6 ]; then
  echo "Heavy meeting day. Block focus time."
fi

9. Delegated calendars vs shared mailboxes

Microsoft 365 teams often conflate delegated calendars, shared mailboxes, resource calendars, and M365 group calendars. They are not the same thing operationally. Delegation is person-to-person access. Shared mailboxes behave like a separate identity. M365 groups are collaboration objects with their own calendar surface. That distinction barely exists in the Google or iCloud versions of this guide, but it changes how Outlook automations fail in practice.

# Check which calendars your current Outlook grant can actually see
nylas calendar list --json | \
  jq -r '.[] | "\(.name) | read_only=\(.read_only) | id=\(.id)"'

If a script can list a calendar but cannot create an event, the issue is usually delegated permission scope or mailbox policy, not the command itself.

10. Conditional Access and tenant controls

Outlook and Microsoft 365 also sit behind Entra ID tenant policy. Conditional Access, MFA requirements, disabled legacy auth, tenant consent, and mailbox-level policies can all block otherwise valid calendar workflows. This is why the Outlook article cannot just be a copy of the Yahoo or iCloud one. The protocol story is Microsoft Graph, but the operational story is tenant policy.

When an Outlook automation works for one user and fails for another, the root cause is often not event data. It is the tenant deciding which grant is allowed to act, whether shared mailbox access is enabled, or whether conferencing details can be provisioned.

11. M365 groups and channel scheduling

Another Outlook-specific workflow is scheduling around M365 groups, Teams channels, and room lists. Those don't map cleanly to the simpler "one account, one calendar" model used by most personal providers. If you support enterprise users, make sure your automation can distinguish between a person's mailbox calendar and a shared collaboration calendar.

# Pull calendar IDs first, then target the exact group or delegated calendar
nylas calendar list --json | \
  jq '.[] | {name: .name, id: .id}'

Next steps