Guide
Microsoft Graph Calendar API Quickstart
Reading an Outlook calendar from code means Microsoft Graph, and Graph means an Azure app registration before your first request. This quickstart covers the whole path: register the app, request the Calendars scopes, list events from /me/events, create one with a POST, handle pagination — and the one-login shortcut for when the Azure setup is more than you need.
Written by Nick Barraclough Product Manager
Command references used in this guide: nylas auth login, nylas calendar events list, and nylas calendar events create.
How do you get started with the Graph calendar API?
You start by registering an application in Azure Active Directory, because Graph won't issue a token to an unregistered app. In the Azure portal you create an app, note its client ID and tenant ID, add a redirect URI, and create a client secret. With those you run an OAuth flow to obtain an access token, then call Graph with a Bearer header. The app registration guide covers each field.
Once you have a token, the calendar lives under /me. A GET https://graph.microsoft.com/v1.0/me/events returns the signed-in user's events as JSON, per the list events reference. That first successful call usually takes 15–30 minutes from a cold Azure tenant, almost all of it spent in the portal rather than in code.
What scopes and permissions does it need?
Calendar access needs the Calendars permissions. Calendars.Read grants read-only access to events; Calendars.ReadWrite adds create, update, and delete. You request these as delegated permissions when acting on behalf of a signed-in user, or as application permissions for unattended daemon access — and application permissions reach every mailbox in the tenant unless you scope them with Exchange RBAC for Applications.
Choosing the narrowest scope that works is the security default: a read-only sync should request Calendars.Read, not ReadWrite. Application permissions also require tenant-admin consent, documented in the Graph permissions reference, so unattended calendar access is a deliberate admin decision, not a self-service grant.
How do you list and create events with Graph?
Listing is a GET against /me/events; creating is a POST with a JSON body describing subject, start, end, and attendees. Times take a dateTime plus a timeZone, and Graph stores them in the calendar's zone. The example below lists the next events and creates a 30-minute meeting — the two operations that cover most calendar integrations.
# List events
curl -H "Authorization: Bearer $TOKEN" \
"https://graph.microsoft.com/v1.0/me/events?\$top=10&\$select=subject,start,end"
# Create a 30-minute event
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
https://graph.microsoft.com/v1.0/me/events \
-d '{
"subject": "Sync",
"start": { "dateTime": "2026-06-10T15:00:00", "timeZone": "Pacific Standard Time" },
"end": { "dateTime": "2026-06-10T15:30:00", "timeZone": "Pacific Standard Time" },
"attendees": [{ "emailAddress": { "address": "teammate@contoso.com" }, "type": "required" }]
}'What are the Graph calendar pagination gotchas?
Two gotchas trip up almost everyone. First, /me/events returns stored event objects — a recurring meeting appears once, as its series master, not as individual occurrences. To get expanded instances in a date range, use /me/calendarView?startDateTime=...&endDateTime=..., which materializes each occurrence. Picking the wrong endpoint silently drops every recurring instance from your results.
Second, Graph pages results: a response includes at most $top items (default and maximum vary by endpoint) plus an @odata.nextLink URL when more exist. You must follow that link until it's absent to read the full set — assuming the first page is complete is a common bug. Throttling also applies, returning 429 with a Retry-After header you should honor with backoff.
What is the CLI shortcut?
The CLI collapses the Azure setup into one login. nylas auth login --provider microsoft runs the OAuth flow for you — no app registration, no client secret, no scope request — and stores the grant. Then nylas calendar events list reads events and nylas calendar events create adds them, with recurring instances already expanded and pagination handled underneath. Output is JSON for scripting.
For a developer who needs to read or write one calendar from a script, that's minutes instead of a portal session. The full Graph API remains the right choice when you need tenant-wide administration or Graph-specific resources; for everyday calendar access, the login removes the registration wall. See the Graph email quickstart for the mail counterpart and manage the Outlook calendar for more commands.
# One login replaces the Azure app registration
nylas auth login --provider microsoft
# List events (recurring instances expanded, pages handled)
nylas calendar events list --days 14 --json
# Create an event
nylas calendar events create \
--title "Sync" --start "2026-06-10 15:00" --end "2026-06-10 15:30" \
--participant teammate@contoso.comNext steps
- Microsoft Graph email quickstart — the mail-side counterpart
- Manage the Outlook calendar — events, availability, and invites
- Outlook calendar change notifications — react to event changes
- Outlook CLI — mail and calendar from the terminal
- Full command reference — every flag and subcommand documented