# The event model (https://www.cal-sdk.com/docs/concepts/events)

On the wire, a Google event and an Outlook event have little in common: different ids, different time formats, different names for the same status. calsdk turns both into one `CalendarEvent`, so the rest of your code only learns one shape. Here is one read from Outlook:

```ts
{
  id: 'AAMkAGI2TG93AAA=',
  calendarId: 'primary',
  kind: 'single',
  title: 'Design review',
  description: 'Walk through the new onboarding flow.',
  location: 'Room 4',
  start: { dateTime: '2026-11-03T10:00:00+05:30', timeZone: 'Asia/Kolkata' },
  end: { dateTime: '2026-11-03T11:00:00+05:30', timeZone: 'Asia/Kolkata' },
  status: 'confirmed',
  showAs: 'busy',
  organizer: { email: 'ana@example.com', name: 'Ana', self: true },
  attendees: [
    { email: 'raj@example.com', name: 'Raj', responseStatus: 'accepted' },
  ],
  conference: { provider: 'teams', joinUrl: 'https://teams.microsoft.com/l/meetup-join/...' },
  etag: 'W/"DwAAABYAAAA="',
  htmlLink: 'https://outlook.office365.com/owa/?itemid=...',
  createdAt: '2026-10-28T09:12:00Z',
  updatedAt: '2026-10-30T14:03:00Z',
  providerMetadata: { microsoft: { importance: 'normal', showAs: 'busy' } },
}
```

Read the same meeting from Google and you get the same shape, with the title, times and attendees in the same places. What belongs to Google still differs: the id, the etag, the links and the metadata.

## Identity [#identity]

Every event carries the provider's own `id` and the `calendarId` it was read from. Pass both back to `getEvent`, `updateEvent` and `deleteEvent`. Ids are strings with no fixed format, and each provider shapes them its own way, so store them as they are rather than parsing them.

`kind` tells you what you're looking at: a `single` event, a recurring `series`, one `occurrence` of a series, or an `exception`, an occurrence someone moved or edited. Occurrences and exceptions also carry `seriesId`, the series they belong to, and `originalStart`, where the series' rule placed them. [Recurring events](/docs/guides/recurring-events) covers how to work with them.

## When [#when]

`start` and `end` are either both timed, `{ dateTime, timeZone }`, or both all-day, `{ date }`. An all-day event's end date is exclusive, so a one-day event on 3 November ends on the 4th. [Time zones](/docs/concepts/time-zones) explains why timed events keep their zone.

A series keeps its rule in `recurrence`, as RFC 5545 lines such as `['RRULE:FREQ=WEEKLY;BYDAY=MO', 'EXDATE:20261110T100000Z']`.

## Status and availability [#status-and-availability]

`status` is `confirmed`, `tentative` or `cancelled`. You'll rarely see `cancelled`: it's for events that still have their details, such as an Outlook meeting the organizer cancelled. Deleted events aren't returned at all, and sync reports them as `delete` changes.

`showAs` is `busy` or `free`, and decides whether the event blocks time in free/busy. Providers with more states, such as Outlook's out of office, keep the original in `providerMetadata`. `visibility` is `default`, `public` or `private`.

## People [#people]

The `organizer` is a `{ email, name?, self? }`, where `self` is `true` when it's the signed-in user. `attendees` have the same fields plus `responseStatus` (`needsAction`, `accepted`, `declined` or `tentative`), `optional` and `organizer`.

Some providers leave attendees out of listings because reading them costs a request per event. Fetch the event with `getEvent` when you need them. The provider pages say which.

## Extras [#extras]

`conference` is the video link, `{ provider, joinUrl, id? }`, where `provider` is `google-meet`, `teams`, `zoom` or `other`. `reminders` is `{ useDefault, overrides? }`, and each override is a `{ method: 'popup' | 'email', minutesBefore }`. `color` is a hex color like `'#RRGGBB'`, and `htmlLink` opens the event in the provider's own app.

`etag` is a version tag: pass it back as `ifMatch` and an update only lands if nobody changed the event since you read it. Deletes take it too, though [Outlook can miss a change](/docs/providers/microsoft#writing-events) made just before the delete. `createdAt` and `updatedAt` are ISO 8601 timestamps. `providerMetadata` holds whatever only one provider has, keyed by provider id; [Provider options](/docs/guides/provider-options) covers it.

Every field except `id`, `calendarId`, `kind`, `start`, `end`, `status` and `showAs` is optional, because a provider leaves out what it doesn't have. A Cal.com booking has no color, and an ICS feed has no etag.

## Writing events [#writing-events]

You don't write a `CalendarEvent` back. `createEvent` takes an `EventInput`, a smaller shape with only the fields you can set: `title`, `description`, `location`, `start`, `end`, `recurrence`, `showAs`, `visibility`, `attendees`, `createConference`, `reminders` and `color`. `updateEvent` takes the same fields as a partial `EventPatch`, where `null` clears a field. See [Types](/docs/reference/types) for both.
