Guide

Microsoft Graph calendarView Explained

Query the Microsoft Graph calendarView endpoint for events in a date range with recurrences expanded. Compare it to list events and read calendars from the CLI.

Written by Prem Keshari Senior SRE

VerifiedCLI 3.1.22 · Microsoft · last tested June 19, 2026

What is the Microsoft Graph calendarView endpoint?

The calendarView endpoint is a GET to /me/calendar/calendarView?startDateTime={s}&endDateTime={e} that returns the events occurring inside a date range. Its defining behavior is recurrence expansion: a weekly standup shows up as one event per week in the window, each a real event instance you can read or update individually.

Both startDateTime and endDateTime are required query parameters, expressed as ISO 8601 date-time strings. According to the official calendarView list reference, the endpoint "gets the occurrences, exceptions, and single instances of events in a calendar view defined by a time range." The default page size is 10 events. The endpoint is read-only, so it never moves or rewrites events on the calendar it reads.

The request below reads a one-week window and trims the payload to four fields with $select. Sending thePrefer: outlook.timezone header pins the returned start and end values to a named time zone instead of the mailbox default, which removes a whole class of off-by-an-hour bugs.

GET https://graph.microsoft.com/v1.0/me/calendar/calendarView?startDateTime=2026-06-22T00:00:00&endDateTime=2026-06-29T00:00:00&$select=subject,start,end,type&$top=50
Authorization: Bearer <access_token>
Prefer: outlook.timezone="America/Los_Angeles"

How does calendarView differ from GET /me/events?

The split is recurrence handling. GET /me/events returns the recurrence master, typed seriesMaster, plus any one-off exceptions, and never the generated occurrences. calendarView returns the expanded occurrences for the window, so a daily meeting over 7 days appears 7 times rather than once.

The event resource reference documents the four values of the type property: singleInstance, occurrence, exception, and seriesMaster. A plain event list returns seriesMaster for any recurring series, leaving you to expand the recurrence pattern yourself before you can answer "is there a meeting on Wednesday?". calendarView does that expansion server-side, returning occurrence and exception items already placed on their real dates. For a 30-day window with one daily recurrence, that's roughly 30 occurrence objects from calendarView versus a single master from the events list.

AspectGET /me/calendar/calendarViewGET /me/events
RecurrencesExpanded into occurrencesOne seriesMaster only
Required paramsstartDateTime, endDateTimeNone
type returnedoccurrence, exception, singleInstanceseriesMaster, singleInstance
Best for"What's scheduled in this range?"Reading or editing a series definition

What does a calendarView response look like?

A calendarView response is an OData collection: a value array of event objects plus an optional @odata.nextLink when more pages exist. Each occurrence carries its own id, seriesMasterId, type, and a start/end pair with a dateTime and timeZone.

Because each occurrence is a distinct object, you can act on a single instance without touching the series. The seriesMasterId links every occurrence back to its master, so a script can group instances by series in one pass. The payload below shows two days of a daily standup inside the requested window. Both items have type: occurrence and share one seriesMasterId, and the response is paged at the default 10 events until you raise $top.

{
  "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/calendar/calendarView?$skip=10&...",
  "value": [
    {
      "id": "AAMk_occurrence_1",
      "seriesMasterId": "AAMk_master",
      "type": "occurrence",
      "subject": "Daily standup",
      "start": { "dateTime": "2026-06-22T09:00:00.0000000", "timeZone": "America/Los_Angeles" },
      "end":   { "dateTime": "2026-06-22T09:15:00.0000000", "timeZone": "America/Los_Angeles" }
    },
    {
      "id": "AAMk_occurrence_2",
      "seriesMasterId": "AAMk_master",
      "type": "occurrence",
      "subject": "Daily standup",
      "start": { "dateTime": "2026-06-23T09:00:00.0000000", "timeZone": "America/Los_Angeles" },
      "end":   { "dateTime": "2026-06-23T09:15:00.0000000", "timeZone": "America/Los_Angeles" }
    }
  ]
}

How do you page and trim a calendarView query?

Two query options control payload size: $top sets the page size and $select limits the fields returned. When a window holds more events than one page, Graph returns @odata.nextLink, an opaque URL you follow verbatim until it stops appearing. The default page is 10 events.

Raising $top cuts round trips: a 50-event week needs five requests at the default 10 but one at $top=50. The calendarView reference lists $select, $top, $skip, and $orderby among the supported OData parameters. Don't hand-build the next URL from $skip yourself; follow @odata.nextLink exactly, because Graph encodes paging state inside it. The loop below walks every page of a one-week view and stops when no nextLink comes back.

url="https://graph.microsoft.com/v1.0/me/calendar/calendarView?startDateTime=2026-06-22T00:00:00&endDateTime=2026-06-29T00:00:00&\$top=50"

while [ -n "$url" ] && [ "$url" != "null" ]; do
  page=$(curl -s -H "Authorization: Bearer $TOKEN" \
    -H 'Prefer: outlook.timezone="America/Los_Angeles"' "$url")
  echo "$page" | jq '.value[] | {subject, type, start: .start.dateTime}'
  url=$(echo "$page" | jq -r '."@odata.nextLink" // "null"')
done

How do you read the same window from the CLI?

The nylas calendar events list command reads events in a forward window the way calendarView does, with recurrences already expanded into instances. You pass -d/--days for the window and -n/--limit for the count, and the tool handles OAuth, time zones, and paging instead of you assembling a query string and header.

This removes the plumbing a direct call owns: token refresh, the required startDateTime/endDateTime pair, the Prefer header, and @odata.nextLink following. The --days flag defaults to 7 and accepts 0 for no limit; --limit defaults to 10 and auto-paginates past 200. The command below reads the next 30 days, asks for up to 200 events, and emits JSON for a script.

nylas calendar events list \
  --days 30 \
  --limit 200 \
  --format json

How do you parse CLI events output with jq?

The --format json flag emits machine-readable output that pipes straight into jq, so a cron job or agent reads occurrences without screen scraping. The three accepted formats are table, json, and yaml; table is the default.

Piping to jq turns a one-line read into a building block for a pipeline. The example below pins the display zone with --timezone, asks for the next 14 days, and projects each event down to a title and start time. A 14-day read for a single calendar typically returns a few dozen events, small enough to inline into a prompt under a few hundred tokens.

nylas calendar events list \
  --days 14 \
  --limit 200 \
  --timezone America/Los_Angeles \
  --format json \
  | jq '.[] | {title, start}'

When should you call the Graph API directly instead?

Call Microsoft Graph directly when you need Microsoft-only controls: a specific calendar group, the $orderby/$filter OData surface, application permissions with Calendars.Read across a tenant, or a web app that already runs the MSAL OAuth flow. Reach for the terminal path for scripts, agent tools, and cron jobs that should also run against Google without a second integration.

The trade-off is ownership, not capability. A direct calendarView integration owns app registration in Azure AD, token refresh, the required date-range params, the Prefer: outlook.timezone header, and @odata.nextLink paging. The CLI owns command selection and output handling while the provider integration sits behind it. For a one-off range read or a cross-provider scheduler, the terminal keeps a short script from turning into a long-lived OAuth client maintained for one endpoint.

Next steps