Events

Events have the same format on every calendar. You read, write and search them the same way on Google, Outlook and Pyas calendars. When a provider doesn't support a feature, the API returns an error or lists the feature in the response, instead of silently skipping it.

Choose a calendar

Every event request must include an account (accountId) and can include a calendar (calendarRef). If you don't specify a calendar, the API uses the account's primary calendar. A calendarRef is either primary or a calendar id returned by this request:

GET /v2/calendars

Times and time zones

FieldDescription
startsAt, endsAtThe time in UTC (2026-10-21T15:00:00Z)
startsAtLocal, endsAtLocalThe same time in the event's time zone, with that zone's offset (2026-10-21T11:00:00-04:00)
timezoneThe IANA name of the event's time zone (America/New_York)
isAllDayWhether the event is an all-day event. If it is, its times are midnight in timezone (startsAtLocal is 2026-10-21T00:00:00-04:00).

When you create or update an event, include a time zone offset with each time (Z or +02:00), or use plain dates (2026-10-21) for an all-day event. The API rejects a time without an offset, because the time is ambiguous without one. For the same reason, the from and to parameters for reading events also require an offset.

Create, update and delete events

const event = await pyas.events.create({
  accountId,
  title: 'Weekly review',
  startsAt: '2026-10-21T15:00:00Z',
  endsAt: '2026-10-21T15:30:00Z',
  attendees: [{ email: 'sam.patel@example.org', name: 'Sam Patel' }],
  recurrence: 'FREQ=WEEKLY;COUNT=6',
  metadata: { dealId: 'deal_1007' },
})

await pyas.events.update({ accountId, eventId: event.id, title: 'Weekly review (moved)' })
await pyas.events.delete({ accountId, eventId: event.id, notifyAttendees: true })

In an update request, include only the fields you want to update. To clear a field that can be empty, set it to null.

When you create, update or delete an event that has attendees, they get an email about it. To stop the email, set notifyAttendees to false. Outlook always emails attendees, and Microsoft doesn't offer a way to stop it. On an Outlook calendar, the change is still made, and the response includes meta.notifyAttendees to tell you that attendees were emailed:

"meta": {
  "notifyAttendees": {
    "applied": false,
    "reason": "Outlook emails attendees about changes to events that have them, and Microsoft Graph has no setting to stop it."
  }
}

Recurring events

recurrence is an RFC 5545 rule (FREQ=WEEKLY;BYDAY=MO,WE;COUNT=10). A list request returns each series once. To get every occurrence in the time window instead, pass expand=true.

To list the occurrences of a single series, call:

GET /v2/events/{eventId}/instances

Each occurrence includes a series field that identifies its series. When you update an occurrence, only that occurrence is updated.

To add a meeting link to an event, set conferencing.provider. You can use meet on a Google calendar, teams on an Outlook calendar, or zoom on any calendar. For Zoom, you also set conferencing.accountId to a connected Zoom account. The response includes conferencing.joinUrl, the meeting id, the passcode and the dial-in numbers.

To configure the meeting, such as who can join without waiting, recording and muting participants on entry, use conferencing.options. The options are the same for all three services. If a service doesn't support a setting, the API rejects the request instead of ignoring the setting. If a service doesn't keep a setting, the response lists it in meta.conferencing.notApplied, along with the reason.

Your own data on events

Use metadata to store your own fields on any event. Values can be text, numbers, true and false, or lists of those:

"metadata": { "dealId": "deal_1007", "seats": 4, "tags": ["Food", "Hiking"] }

Metadata works with every provider, and you can search for events by these fields across your whole app. A search for a list's item finds every event whose list holds it:

curl "https://api.pyas.io/v2/events?metadata.dealId=deal_1007" -H "x-api-key: $PYAS_API_KEY"
curl "https://api.pyas.io/v2/events?metadata.tags=Hiking" -H "x-api-key: $PYAS_API_KEY"

When you update an event, the keys you send are changed and the others are kept. A list you send replaces the list that was there. To remove a key, send it as null.

If you stored data as extended properties in v1, see Migrating from v1.

Read several calendars in one request

To read events from several calendars in one request, pass accountIds with from and to. To include every connected account of one of your users, pass a subjectId instead of accountIds. The API returns the events as a single timeline sorted by start time, and each event's account is in providerRefs.accountId.

When the same meeting appears on two calendars, the API either flags it as a duplicate (duplicates=flag, the default) or returns it only once (duplicates=collapse).

Prevent conflicting updates

Every event has a version, which the API also returns in the ETag header. When you update or delete the event, send that value in the If-Match header, exactly as you received it, including the quotes. If someone else updated the event after you read it, the API rejects the request with RESOURCE_CONFLICT (409 Conflict). In that case, read the event again, decide what to do, and retry the request.

curl -X PATCH "https://api.pyas.io/v2/events/$EVENT_ID?accountId=$ACCOUNT_ID" \
  -H "x-api-key: $PYAS_API_KEY" \
  -H "If-Match: $VERSION" \
  -H "content-type: application/json" \
  -d '{ "title": "Renamed" }'

Keeping a copy in sync

To keep a copy of a calendar in your own database, start a sync for a time window by passing sync=true. The API returns every event, page by page, and the last page includes meta.syncToken. Later, send only syncToken to get the changes since that sync. Deleted events are listed in meta.deletedIds. Use the event.* webhooks to find out when to sync again.

What else events can do

The Events reference covers everything else you can do with events. This includes attachments (links and files), responding to invitations (with a proposed new time on Outlook), moving an event to another calendar, forwarding an event, reminders, creating an event from a sentence (quick add), and importing events.