Capacitor plugin to manage calendars and events on Android and iOS. Create, read, update and delete calendars and events, work with recurring events, present the system event dialogs, and listen for calendar changes.
The Capacitor Calendar plugin gives your app full access to the calendars and events on the device. Here are some of the key features:
- 📅 Calendars: Create, delete and retrieve the calendars on the device, including the default calendar for new events.
- 🗓️ Events: Create, read, update and delete events, and query all events in a time range with a single call.
- 🔁 Recurring Events: Create recurring events with a readable recurrence rule — and read that rule back, instead of only being able to write it.
- 🎯 Single Occurrences: Update or delete a single occurrence of a recurring event, or the occurrence and all future ones.
- 📱 System Dialogs: Let the user create or edit an event in the system dialog, prefilled with your event data.
- 🔔 Change Listener: Get notified when calendars or events change, including changes made by other apps.
- 🔒 Granular Permissions: Separate read and write permissions, including write-only calendar access on iOS 17 and newer.
⚠️ Error Codes: Every runtime failure rejects with a documented error code, so you can branch on it instead of parsing messages.- 🌍 All-Day & Time Zones: A documented all-day and time zone contract that behaves identically on both platforms — no off-by-one-day surprises.
- 🤝 Compatibility: Works hand in hand with the Contacts and Datetime Picker plugins.
- 📦 CocoaPods & SPM: Supports CocoaPods and Swift Package Manager for iOS.
- 🔁 Up-to-date: Always supports the latest Capacitor version.
- ⭐️ Support: Priority support from the Capawesome Team.
- ✨ Handcrafted: Built from the ground up with care and expertise, not forked or AI-generated.
Missing a feature? Just open an issue and we'll take a look!
The Calendar plugin is typically used whenever an app needs to read from or write to the calendars on the device, for example:
- Booking and appointment apps: Write a confirmed booking straight into the user's calendar, including an alert before the appointment, and update or remove it when the booking changes.
- Field service and scheduling: Show the agenda of the device next to your own schedule so that technicians and sales reps see conflicts before they accept a job.
- Fitness and course apps: Add recurring training sessions or course dates as a single recurring event, and let the user skip a single session without losing the series.
- Reminders before appointments: Attach alerts to an event so that the operating system reminds the user, even when your app is not running.
- Calendar integrations: Keep events in sync with your backend and react to changes that the user made in the calendar app.
| Plugin Version | Capacitor Version | Status |
|---|---|---|
| 0.x.x | >=8.x.x | Active support |
| Android | iOS |
|---|---|
This plugin is only available to Capawesome Insiders. First, make sure you have the Capawesome npm registry set up. You can do this by running the following commands:
npm config set @capawesome-team:registry https://npm.registry.capawesome.io
npm config set //npm.registry.capawesome.io/:_authToken <YOUR_LICENSE_KEY>
Attention: Replace <YOUR_LICENSE_KEY> with the license key you received from Polar. If you don't have a license key yet, you can get one by becoming a Capawesome Insider.
Next, you can use our AI-Assisted Setup to install the plugin. Add the Capawesome Skills to your AI tool using the following command:
npx skills add capawesome-team/skills --skill capacitor-pluginsThen use the following prompt:
Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome-team/capacitor-calendar` plugin in my project.
If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
npm install @capawesome-team/capacitor-calendar
npx cap syncThis API requires the following elements be added to your AndroidManifest.xml before or after the application tag:
<!-- Required if you want to read calendars and events, for example with `getCalendars()` or `getEvents(...)`. -->
<uses-permission android:name="android.permission.READ_CALENDAR" />
<!-- Required if you want to create, update or delete calendars and events, for example with `createEvent(...)`. -->
<uses-permission android:name="android.permission.WRITE_CALENDAR" />Only declare the permissions that your app actually needs. Keep in mind that createEvent(...), updateEventById(...) and deleteEventById(...) require the READ_CALENDAR permission in addition to the WRITE_CALENDAR permission, because they have to look up the calendar or event first. Only createCalendar(...) and deleteCalendarById(...) work with the WRITE_CALENDAR permission alone.
If you are using Proguard, you need to add the following rules to your proguard-rules.pro file:
-keep class io.capawesome.capacitorjs.plugins.** { *; }
Add the following keys to the ios/App/App/Info.plist file, which tell the user why your app needs access to the calendars:
<!-- Required on iOS 17 and newer if your app reads or modifies calendars or events. -->
<key>NSCalendarsFullAccessUsageDescription</key>
<string>The app needs access to your calendars to display and manage your events.</string>
<!-- Required on iOS 17 and newer if your app only requests the `writeCalendar` permission. -->
<key>NSCalendarsWriteOnlyAccessUsageDescription</key>
<string>The app needs access to your calendars to add events for your bookings.</string>
<!-- Required on iOS 16 and older. -->
<key>NSCalendarsUsageDescription</key>
<string>The app needs access to your calendars to display and manage your events.</string>Which keys you need depends on the access that your app requests:
NSCalendarsFullAccessUsageDescriptionis required on iOS 17 and newer whenever thereadCalendarpermission is requested and by every method that reads or modifies calendars or events. Modifying requires full access as well, because the plugin has to look up the calendar or event first.NSCalendarsWriteOnlyAccessUsageDescriptionis only required on iOS 17 and newer ifrequestPermissions(...)is called with only thewriteCalendarpermission. Write-only access lets your app add events without seeing the events of the user, but is not sufficient for the methods of this plugin.NSCalendarsUsageDescriptionis required on iOS 16 and older, which does not distinguish between read and write access.
If a required key is missing, requestPermissions(...) rejects with a clear error message.
No configuration required for this plugin.
The following examples show how to request permissions, work with calendars and events, create and modify recurring events, present the system event dialogs, and listen for calendar changes.
Request read and write access to the calendars of the device. Pass the permissions option to request only a subset. On iOS 17 and newer, requesting only the writeCalendar permission requests write-only access, which does not give your app access to the existing events of the user. Methods such as createEvent(...) request full access when they are called, because they have to look up the calendar or event first:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const requestPermissions = async () => {
const { readCalendar, writeCalendar } = await Calendar.requestPermissions();
return readCalendar === 'granted' && writeCalendar === 'granted';
};
const requestWriteOnlyPermission = async () => {
const { writeCalendar } = await Calendar.requestPermissions({
permissions: ['writeCalendar'],
});
return writeCalendar === 'granted';
};Retrieve all calendars on the device with getCalendars(), or only the calendar that the system uses for new events with getDefaultCalendar(). Use the writable property to filter out calendars that your app cannot write to, for example subscribed holiday calendars:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const getWritableCalendars = async () => {
const { calendars } = await Calendar.getCalendars();
return calendars.filter(calendar => calendar.writable);
};
const getDefaultCalendar = async () => {
const { calendar } = await Calendar.getDefaultCalendar();
return calendar;
};Create an event with createEvent(...). Only title and startDate are required. If no calendarId is provided, the event is created in the default calendar. The alerts are offsets in minutes before the start of the event:
import { Calendar, EventAvailability } from '@capawesome-team/capacitor-calendar';
const createEvent = async (calendarId: string) => {
const startDate = new Date('2026-09-01T10:00:00').getTime();
const { id } = await Calendar.createEvent({
event: {
calendarId,
title: 'Dentist appointment',
startDate,
endDate: startDate + 60 * 60 * 1000,
location: 'Main Street 1, Springfield',
description: 'Bring the insurance card.',
availability: EventAvailability.Busy,
alerts: [60, 15],
},
});
return id;
};Add a recurrence rule to create a recurring event. The following example creates an event that repeats every week on Mondays and Wednesdays for ten occurrences:
import {
Calendar,
RecurrenceFrequency,
Weekday,
} from '@capawesome-team/capacitor-calendar';
const createRecurringEvent = async () => {
const { id } = await Calendar.createEvent({
event: {
title: 'Team stand-up',
startDate: new Date('2026-09-01T09:00:00').getTime(),
recurrence: {
frequency: RecurrenceFrequency.Weekly,
interval: 1,
count: 10,
daysOfWeek: [Weekday.Monday, Weekday.Wednesday],
},
},
});
return id;
};Query all events that overlap a time range with getEvents(...). Recurring events are expanded, so each occurrence is returned as a separate entry with its own startDate. Pass a calendarId to restrict the query to a single calendar:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const getEventsOfNextWeek = async () => {
const from = Date.now();
const to = from + 7 * 24 * 60 * 60 * 1000;
const { events } = await Calendar.getEvents({ from, to });
return events;
};A single event can be retrieved by its identifier with getEventById(...), which resolves with null if the event does not exist:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const getEventById = async (id: string) => {
const { event } = await Calendar.getEventById({ id });
return event;
};Update an event with updateEventById(...). Only the properties that you pass are changed, all others keep their current values. Setting a property to null (or an array property to []) removes it from the event:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const rescheduleEvent = async (id: string, startDate: number) => {
await Calendar.updateEventById({
id,
event: {
startDate,
endDate: startDate + 30 * 60 * 1000,
},
});
};
const clearEventDetails = async (id: string) => {
await Calendar.updateEventById({
id,
event: {
location: null,
description: null,
alerts: [],
},
});
};Pass the instanceStartDate of an occurrence, as returned by getEvents(...), to apply an operation to a single occurrence of a recurring event instead of the whole series. The span option controls whether the operation affects only that occurrence or the occurrence and all future ones:
import { Calendar, EventSpan } from '@capawesome-team/capacitor-calendar';
const deleteOccurrence = async (id: string, instanceStartDate: number) => {
await Calendar.deleteEventById({
id,
instanceStartDate,
span: EventSpan.ThisEvent,
});
};
const deleteAllFutureOccurrences = async (
id: string,
instanceStartDate: number,
) => {
await Calendar.deleteEventById({
id,
instanceStartDate,
span: EventSpan.ThisAndFutureEvents,
});
};Without instanceStartDate, the entire recurring event is deleted.
Let the user create an event in the system dialog with displayCreateEvent(...), optionally prefilled with your event data. On iOS, the identifier of the created event is returned if the user saved the event:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const displayCreateEvent = async () => {
const { id } = await Calendar.displayCreateEvent({
event: {
title: 'Lunch with Jane',
startDate: new Date('2026-09-01T12:00:00').getTime(),
location: 'Main Street 1, Springfield',
},
});
return id;
};Use displayUpdateEventById(...) to let the user edit an existing event. On iOS, the action describes what the user did in the dialog:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const displayUpdateEventById = async (id: string) => {
const { action } = await Calendar.displayUpdateEventById({ id });
return action;
};The system dialogs on Android do not report a result back to the app, so id and action are only available on iOS. On Android, only the event properties that are supported by the system intent are prefilled, and the remaining properties are silently ignored.
Register a listener for the calendarChange event to reload your data whenever calendars or events change, including changes that were made in the calendar app or by other apps. The event carries no payload, because the operating systems do not report which entities changed:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const addCalendarChangeListener = async () => {
return Calendar.addListener('calendarChange', () => {
console.log('The calendars or events on the device have changed.');
});
};
const removeAllListeners = async () => {
await Calendar.removeAllListeners();
};Open the calendar app of the device at a specific date with openCalendar(...), for example after an event was created. Use openSettings() to send the user to the settings of your app so that a previously denied permission can be granted:
import { Calendar } from '@capawesome-team/capacitor-calendar';
const openCalendar = async (date: number) => {
await Calendar.openCalendar({ date });
};
const openSettings = async () => {
await Calendar.openSettings();
};checkPermissions()createCalendar(...)createEvent(...)deleteCalendarById(...)deleteEventById(...)displayCreateEvent(...)displayUpdateEventById(...)getCalendars()getDefaultCalendar()getEventById(...)getEvents(...)openCalendar(...)openSettings()requestPermissions(...)updateEventById(...)addListener('calendarChange', ...)removeAllListeners()- Interfaces
- Type Aliases
- Enums
checkPermissions() => Promise<PermissionStatus>Check permissions to access the device calendar.
Only available on Android and iOS.
Returns: Promise<PermissionStatus>
Since: 0.0.1
createCalendar(options: CreateCalendarOptions) => Promise<CreateCalendarResult>Create a new calendar on the device.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
CreateCalendarOptions |
Returns: Promise<CreateCalendarResult>
Since: 0.0.1
createEvent(options: CreateEventOptions) => Promise<CreateEventResult>Create a new event in a calendar.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
CreateEventOptions |
Returns: Promise<CreateEventResult>
Since: 0.0.1
deleteCalendarById(options: DeleteCalendarByIdOptions) => Promise<void>Delete a calendar from the device.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
DeleteCalendarByIdOptions |
Since: 0.0.1
deleteEventById(options: DeleteEventByIdOptions) => Promise<void>Delete an event from the device.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
DeleteEventByIdOptions |
Since: 0.0.1
displayCreateEvent(options?: DisplayCreateEventOptions | undefined) => Promise<DisplayCreateEventResult>Display the system user interface to create a new event.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
DisplayCreateEventOptions |
Returns: Promise<DisplayCreateEventResult>
Since: 0.0.1
displayUpdateEventById(options: DisplayUpdateEventByIdOptions) => Promise<DisplayUpdateEventByIdResult>Display the system user interface to update an existing event.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
DisplayUpdateEventByIdOptions |
Returns: Promise<DisplayUpdateEventByIdResult>
Since: 0.0.1
getCalendars() => Promise<GetCalendarsResult>Get all calendars on the device.
Only available on Android and iOS.
Returns: Promise<GetCalendarsResult>
Since: 0.0.1
getDefaultCalendar() => Promise<GetDefaultCalendarResult>Get the default calendar for new events.
Only available on Android and iOS.
Returns: Promise<GetDefaultCalendarResult>
Since: 0.0.1
getEventById(options: GetEventByIdOptions) => Promise<GetEventByIdResult>Get a single event by its identifier.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
GetEventByIdOptions |
Returns: Promise<GetEventByIdResult>
Since: 0.0.1
getEvents(options: GetEventsOptions) => Promise<GetEventsResult>Get the events in a given time range.
Returns all events that overlap the time range, including single occurrences of recurring events.
Rejects with the error code CALENDAR_NOT_FOUND if a calendarId is
provided but no calendar with that identifier exists.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
GetEventsOptions |
Returns: Promise<GetEventsResult>
Since: 0.0.1
openCalendar(options?: OpenCalendarOptions | undefined) => Promise<void>Open the calendar app of the device.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
OpenCalendarOptions |
Since: 0.0.1
openSettings() => Promise<void>Open the settings of the app so that the user can grant or revoke permissions.
Only available on Android and iOS.
Since: 0.0.1
requestPermissions(options?: RequestPermissionsOptions | undefined) => Promise<PermissionStatus>Request permissions to access the device calendar.
On iOS 17+, requesting only the writeCalendar permission requests
write-only access. Requesting the readCalendar permission requests
full access.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
RequestPermissionsOptions |
Returns: Promise<PermissionStatus>
Since: 0.0.1
updateEventById(options: UpdateEventByIdOptions) => Promise<void>Update an existing event.
Only available on Android and iOS.
| Param | Type |
|---|---|
options |
UpdateEventByIdOptions |
Since: 0.0.1
addListener(eventName: 'calendarChange', listenerFunc: () => void) => Promise<PluginListenerHandle>Called when calendars or events are created, updated or deleted, including by other apps.
Only available on Android and iOS.
| Param | Type |
|---|---|
eventName |
'calendarChange' |
listenerFunc |
() => void |
Returns: Promise<PluginListenerHandle>
Since: 0.0.1
removeAllListeners() => Promise<void>Remove all listeners for this plugin.
Since: 0.0.1
| Prop | Type | Description | Since |
|---|---|---|---|
readCalendar |
PermissionState |
The permission state for reading calendar data. On iOS, this is prompt as long as only write-only access has been granted. |
0.0.1 |
writeCalendar |
PermissionState |
The permission state for writing calendar data. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
id |
string |
The identifier of the created calendar. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
color |
string |
The color of the calendar as a hex string in the format #RRGGBB. |
0.0.1 |
title |
string |
The title of the calendar. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
id |
string |
The identifier of the created event. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
event |
EventInput |
The event to create. | 0.0.1 |
| Prop | Type | Description | Default | Since |
|---|---|---|---|---|
alerts |
number[] |
The alerts of the event as offsets in minutes before the start of the event. Negative values represent minutes after the start. | 0.0.1 | |
allDay |
boolean |
Whether the event is an all-day event. For all-day events, startDate and endDate are interpreted as midnight UTC of the respective calendar day. |
false |
0.0.1 |
availability |
EventAvailability |
The availability of the event. | 0.0.1 | |
calendarId |
string |
The identifier of the calendar in which the event is created. | The identifier of the default calendar. |
0.0.1 |
description |
string |
The description of the event. | 0.0.1 | |
endDate |
number |
The end date of the event as a timestamp in milliseconds. If not provided, the event ends one hour after startDate (all-day events: on the same day as startDate). For all-day events, the end date is exclusive (midnight UTC of the day after the last day of the event). |
0.0.1 | |
location |
string |
The location of the event. | 0.0.1 | |
recurrence |
RecurrenceRule |
The recurrence rule of the event. | 0.0.1 | |
startDate |
number |
The start date of the event as a timestamp in milliseconds. | 0.0.1 | |
timezone |
string |
The time zone of the event as an IANA time zone identifier. | The default time zone of the device. |
0.0.1 |
title |
string |
The title of the event. | 0.0.1 |
| Prop | Type | Description | Default | Since |
|---|---|---|---|---|
count |
number |
The number of occurrences after which the recurrence ends. Takes precedence over until. |
0.0.1 | |
daysOfWeek |
Weekday[] |
The days of the week on which the event recurs. | 0.0.1 | |
frequency |
RecurrenceFrequency |
The frequency of the recurrence. | 0.0.1 | |
interval |
number |
The interval between occurrences of the recurrence. For example, an interval of 2 with a Weekly frequency results in an event that recurs every two weeks. |
1 |
0.0.1 |
until |
number |
The date on which the recurrence ends as a timestamp in milliseconds. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
id |
string |
The identifier of the calendar to delete. | 0.0.1 |
| Prop | Type | Description | Default | Since |
|---|---|---|---|---|
id |
string |
The identifier of the event to delete. | 0.0.1 | |
instanceStartDate |
number |
The start date of a single occurrence of a recurring event as a timestamp in milliseconds, as returned by getEvents(...). If provided, only the given occurrence (or, depending on span, the given and all future occurrences) of the recurring event is deleted. If omitted, the entire recurring event is deleted. |
0.0.1 | |
span |
EventSpan |
The span of a recurring event to which the operation is applied. Only applied when instanceStartDate is provided. |
EventSpan.ThisEvent |
0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
id |
string |
The identifier of the created event. Only returned if the event was saved. Only available on iOS. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
event |
Partial<EventInput> |
The event data with which the dialog is prefilled. On Android, only the properties supported by the system intent are applied. Unsupported properties are silently ignored. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
action |
EventEditAction |
The action that the user performed in the dialog. Only available on iOS. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
id |
string |
The identifier of the event to update. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
calendars |
Calendar[] |
The calendars on the device. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
color |
string |
The color of the calendar as a hex string in the format #RRGGBB. |
0.0.1 |
id |
string |
The identifier of the calendar. | 0.0.1 |
title |
string |
The title of the calendar. | 0.0.1 |
writable |
boolean |
Whether events can be added, updated, or deleted in this calendar. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
calendar |
Calendar | null |
The default calendar for new events. If no default calendar is available, null is returned. |
0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
event |
CalendarEvent | null |
The event with the given identifier. If no event was found, null is returned. |
0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
alerts |
number[] |
The alerts of the event as offsets in minutes before the start of the event. Negative values represent minutes after the start. | 0.0.1 |
allDay |
boolean |
Whether the event is an all-day event. For all-day events, startDate and endDate are returned as midnight UTC of the respective calendar day. |
0.0.1 |
availability |
EventAvailability |
The availability of the event. | 0.0.1 |
calendarId |
string |
The identifier of the calendar that the event belongs to. | 0.0.1 |
description |
string |
The description of the event. | 0.0.1 |
endDate |
number |
The end date of the event as a timestamp in milliseconds. For all-day events, the end date is exclusive (midnight UTC of the day after the last day of the event). | 0.0.1 |
id |
string |
The identifier of the event. All occurrences of a recurring event share the same identifier. | 0.0.1 |
location |
string |
The location of the event. | 0.0.1 |
recurrence |
RecurrenceRule |
The recurrence rule of the event. | 0.0.1 |
startDate |
number |
The start date of the event as a timestamp in milliseconds. | 0.0.1 |
status |
EventStatus |
The confirmation status of the event. | 0.0.1 |
timezone |
string |
The time zone of the event as an IANA time zone identifier. | 0.0.1 |
title |
string |
The title of the event. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
id |
string |
The identifier of the event. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
events |
CalendarEvent[] |
The events in the given time range. | 0.0.1 |
| Prop | Type | Description | Since |
|---|---|---|---|
calendarId |
string |
The identifier of the calendar to get the events from. If not provided, the events of all calendars are returned. | 0.0.1 |
from |
number |
The start of the time range as a timestamp in milliseconds. | 0.0.1 |
to |
number |
The end of the time range as a timestamp in milliseconds. | 0.0.1 |
| Prop | Type | Description | Default | Since |
|---|---|---|---|---|
date |
number |
The date to which the calendar app is opened as a timestamp in milliseconds. | The current time. |
0.0.1 |
| Prop | Type | Description | Default | Since |
|---|---|---|---|---|
permissions |
CalendarPermissionType[] |
The permissions to request. | ['readCalendar', 'writeCalendar'] |
0.0.1 |
| Prop | Type | Description | Default | Since |
|---|---|---|---|---|
event |
Nullable<Partial<EventInput>> |
The updated event data. Missing properties are ignored and keep their existing values. Properties explicitly set to null (or empty arrays []) will be removed from the event. Properties that are required for the event structure (allDay, calendarId, endDate, startDate, timezone) must not be set to null. |
0.0.1 | |
id |
string |
The identifier of the event to update. | 0.0.1 | |
instanceStartDate |
number |
The start date of a single occurrence of a recurring event as a timestamp in milliseconds, as returned by getEvents(...). If provided, only the given occurrence (or, depending on span, the given and all future occurrences) of the recurring event is updated. If omitted, the entire recurring event is updated. |
0.0.1 | |
span |
EventSpan |
The span of a recurring event to which the operation is applied. Only applied when instanceStartDate is provided. |
EventSpan.ThisEvent |
0.0.1 |
| Prop | Type |
|---|---|
remove |
() => Promise<void> |
'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'
The action that the user performed in a system event dialog.
'canceled' | 'deleted' | 'saved'
The confirmation status of an event.
'canceled' | 'confirmed' | 'tentative'
The permissions to request when calling requestPermissions(...).
'readCalendar' | 'writeCalendar'
{ [K in keyof T]: T[K] | null }
| Members | Value | Description | Since |
|---|---|---|---|
Busy |
'BUSY' |
The time of the event is marked as busy. | 0.0.1 |
Free |
'FREE' |
The time of the event is marked as free. | 0.0.1 |
Tentative |
'TENTATIVE' |
The time of the event is marked as tentative. | 0.0.1 |
Unavailable |
'UNAVAILABLE' |
The time of the event is marked as unavailable. On Android, this value is mapped to Busy. |
0.0.1 |
| Members | Value | Description | Since |
|---|---|---|---|
Friday |
'FRIDAY' |
The event recurs on Fridays. | 0.0.1 |
Monday |
'MONDAY' |
The event recurs on Mondays. | 0.0.1 |
Saturday |
'SATURDAY' |
The event recurs on Saturdays. | 0.0.1 |
Sunday |
'SUNDAY' |
The event recurs on Sundays. | 0.0.1 |
Thursday |
'THURSDAY' |
The event recurs on Thursdays. | 0.0.1 |
Tuesday |
'TUESDAY' |
The event recurs on Tuesdays. | 0.0.1 |
Wednesday |
'WEDNESDAY' |
The event recurs on Wednesdays. | 0.0.1 |
| Members | Value | Description | Since |
|---|---|---|---|
Daily |
'DAILY' |
The event recurs daily. | 0.0.1 |
Monthly |
'MONTHLY' |
The event recurs monthly. | 0.0.1 |
Weekly |
'WEEKLY' |
The event recurs weekly. | 0.0.1 |
Yearly |
'YEARLY' |
The event recurs yearly. | 0.0.1 |
| Members | Value | Description | Since |
|---|---|---|---|
ThisAndFutureEvents |
'THIS_AND_FUTURE_EVENTS' |
The operation is applied to the given occurrence and all future occurrences of the recurring event. | 0.0.1 |
ThisEvent |
'THIS_EVENT' |
The operation is applied only to the given occurrence of the recurring event. | 0.0.1 |
Recurring events are stored as a single event with a recurrence rule, but they are displayed to the user as many occurrences. The plugin makes both views available and keeps them consistent across Android and iOS.
Occurrence expansion: getEvents(...) expands recurring events into their occurrences. Each occurrence is returned as a separate entry whose startDate and endDate describe that occurrence, while the id and the recurrence rule are the same for all occurrences of the same series. getEventById(...), in contrast, always returns the series itself with its original start date.
Targeting a single occurrence: updateEventById(...) and deleteEventById(...) operate on the whole series by default. Pass the startDate of an occurrence as instanceStartDate to target that occurrence instead, and use span to choose the scope:
EventSpan.ThisEvent(default) applies the change to the given occurrence only. The rest of the series remains untouched.EventSpan.ThisAndFutureEventsapplies the change to the given occurrence and all following ones, while past occurrences remain untouched.
Reading a rule back: the recurrence property of an event is both written and read. A rule that uses parts which are not supported by the plugin — for example a rule created in another app — is read back as the closest supported subset, so frequency and interval are always correct even if a more exotic part is dropped.
All-day events and time zones: an event with allDay: true has no time of day. Its startDate and endDate are therefore interpreted and returned as midnight UTC of the respective calendar day on both platforms, independent of the time zone of the device. The endDate is exclusive: it is midnight UTC of the day after the last day of the event, so a one-day all-day event on 2026-09-01 has startDate = Date.UTC(2026, 8, 1) and endDate = Date.UTC(2026, 8, 2). An endDate that is missing or not on a midnight boundary is normalized: it is floored to midnight UTC of its day and raised to at least one day after startDate, so the event always spans at least one full day. Build these timestamps in UTC, for example with Date.UTC(2026, 8, 1), and format them in UTC as well — using the local time zone instead is what makes an all-day event appear on the wrong day. For events that are not all-day, the timezone property defines the time zone in which the event takes place and defaults to the time zone of the device.
We focused on correctness instead of a long feature list. Every runtime failure rejects with a documented error code, so your app can react to a missing event or a read-only calendar programmatically. Recurrence rules can be read back, not just written, so a recurring event can round-trip through your app without losing information. Single occurrences of a recurring event can be updated and deleted, including all future occurrences. All-day events and time zones follow one documented contract on both platforms, and behavior that only one platform can provide is documented as such instead of being silently faked. On top of that, the plugin is covered by unit tests, is built from the ground up by the Capawesome Team, and comes with priority support.
Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.
- Contacts: Read and write device contacts, for example to invite them to an event.
- Datetime Picker: Let the user pick the date and time of an event natively.
Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our Capawesome Newsletter.
See CHANGELOG.md.
See BREAKING.md.
See LICENSE.