# Read events (https://www.cal-sdk.com/docs/guides/read-events)

## List a time window [#list-a-time-window]

A week view needs every event that touches the week, including the one that started Sunday night. `listEvents` returns the events that overlap `[timeMin, timeMax)`, meaning events that end after `timeMin` and start before `timeMax`:

```ts
import { listEvents } from '@cal-sdk/core';

const { events, nextPageToken } = await listEvents({
  calendar,
  // The week of 9 November, in New York.
  timeMin: '2026-11-09T00:00:00-05:00',
  timeMax: '2026-11-16T00:00:00-05:00',
});
```

Because the end is exclusive, an event ending exactly on a boundary never shows up in two back-to-back windows. `timeMin` and `timeMax` take a `Date` or an ISO 8601 string. Watch out for strings without a time: `'2026-11-01'` means midnight UTC, so pass an offset when you mean midnight in Berlin or Kolkata.

## Walk every page [#walk-every-page]

`listEvents` returns one page. You can pass `nextPageToken` back as `pageToken` to get the next one, but it's usually easier to let `iterateEvents` do it:

```ts
import { iterateEvents } from '@cal-sdk/core';

for await (const event of iterateEvents({ calendar, timeMin, timeMax })) {
  console.log(event.title);
}
```

It fetches pages as you loop, so you can `break` early without reading the rest. Since it yields events rather than results, there's nowhere to return warnings, and they go to the [warnings setting](/docs/concepts/warnings) instead. Set `pageSize` to change how many events each request asks for; providers may return fewer.

## Recurring events [#recurring-events]

By default each series is expanded into its instances, sorted by start. An instance that follows the series rule is an `occurrence`, and one that someone changed, like the Monday standup moved to 10:00, is an `exception`.

To show the rules themselves, such as "every Monday, Wednesday and Friday", pass `expandRecurring: false` to get one `series` event per recurring event, with its rule in `recurrence`:

```ts
const { events } = await listEvents({ calendar, timeMin, timeMax, expandRecurring: false });

const series = events.filter((event) => event.kind === 'series');
console.log(series[0]?.recurrence); // ['RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR']
```

Deleted instances are not events, so listings leave them out. [Recurring events](/docs/guides/recurring-events) covers the rest.

## Fetch one event [#fetch-one-event]

```ts
import { getEvent } from '@cal-sdk/core';

const { event } = await getEvent({ calendar, eventId });
```

`eventId` can be a single event, a series, an occurrence or an exception. A missing event throws `NotFoundError`.

## Search [#search]

```ts
const { events } = await listEvents({ calendar, timeMin, timeMax, query: 'design review' });
```

Search is the read most providers can't do. Only Google and the mock support `query`, and the others throw `UnsupportedFunctionalityError` rather than quietly ignoring it. If your app accepts any provider, check `calendar.capabilities.events.search` first.

## Another calendar [#another-calendar]

Every read defaults to `'primary'`. To read another calendar, pass the `id` you got from [`listCalendars`](/docs/guides/calendars):

```ts
const { events } = await listEvents({ calendar, calendarId: 'team@example.com', timeMin, timeMax });
```
