Articles · App ExamplesUpdated September 2026

How to add calendar sync to an app, and why most apps only need half of it.

To add calendar sync to an app you first decide which of two jobs you are doing. Writing an event into the calendar already on the phone is one permission string and one call. Keeping your app in step with somebody's Google or Outlook account is a server that keeps running when nobody has your app open. Most teams ask for the second and need the first, which is what appointment calendar apps tend to work out in week two.

Below: the permission key each platform wants and the alert the person actually reads, the handoff that skips the prompt on both platforms, why the second run creates duplicates, and how to price the version you need.

See which kind of sync you need

The short version

Writing to the phone's calendar is not syncing with an account.

This belongs at the top because it decides the budget. When you add an event to the phone calendar, it goes into one calendar on one device. If that calendar belongs to a Google or iCloud account, that account's own sync carries the event to their laptop. If it is a local calendar on the phone, the event stays on that phone. You choose which by id, and choosing badly is how an appointment fails to appear anywhere else.

The second thing to accept early is that nothing tells you afterwards. The calendar does not call your app when somebody drags the event, deletes it or declines it. If your app has to know the current state of a person's day, you are either reading the calendar back on a schedule or talking to Google and Microsoft from a server. Those are separate projects with separate bills.

Five things people mean by calendar sync

Calendar integration in a mobile app is not one feature. It is five, and they share a name. Reminding somebody inside your own app. Handing them a prefilled event sheet that their calendar app saves. Writing events into the device calendar yourself. Publishing a feed they subscribe to. And holding a live two-way link with their Google or Microsoft account. The cost runs from an afternoon to a permanent piece of infrastructure.

Work out what the feature is for before you pick one. If the point is that the person turns up, the calendar is one delivery route and often the dearer one. A reminder through push notifications fires from your own app, needs nothing from the calendar, and you can see whether it was delivered. If the point is that your appointment sits next to the dentist and the school run, only a real calendar entry does that.

The honest test is whether anything outside your app has to see the appointment. If the answer is no, do not touch the calendar at all. If the answer is yes, the cheapest version that works is usually the handoff two sections down, not the full account sync somebody asked for.

Try it

Which calendar sync are you actually buying

Five different features share one word. Pick the one you meant and see what it costs and what breaks.

A day or two

A usage string on iOS, WRITE_CALENDAR on Android

A refusal. You still need a screen that works without it.

The permission string, and the alert the person reads

iOS will not let an app touch calendar data without a reason string in Info.plist, and the person reads that exact sentence inside the system alert. Since iOS 17 there are two keys rather than one. NSCalendarsFullAccessUsageDescription covers reading and writing. NSCalendarsWriteOnlyAccessUsageDescription covers apps that only create events, and Apple describes it as a message that tells people why the app is requesting access to create calendar events.

Ask for write only when writing is all you do. The person gets a smaller request, your app never sees the rest of their week, and there is less to explain at review. Both keys arrived in iOS 17, so a build that still supports iOS 16 keeps the older NSCalendarsUsageDescription alongside them. Expo's config plugin writes all of this for you and has a writeOnlyAccess switch that picks which key it emits.

Write the sentence yourself. The default a library ships reads like allow this app to access your calendar, which tells the person nothing and invites a question from App Review. Say what you will put there and when. Adds appointments you book to your own calendar is a sentence somebody can agree to.

Then test it on a real phone. Expo lists its calendar library as device only on both Android and iOS and says it is not supported in Expo Go, so you need a development build. Newly runs your app on a cloud simulator while it builds, which is enough to see the screens, but a simulator's calendar is empty and belongs to nobody. The alert, a refusal, and an event landing in the wrong account all show up on the phone in your pocket and nowhere earlier.

Apple, NSCalendarsWriteOnlyAccessUsageDescription

Android's two permissions, and the handoff that skips them

Android splits the job in two. The Calendar Provider documentation states that to read calendar data an application must include the READ_CALENDAR permission in its manifest file, and that it must include WRITE_CALENDAR to delete, insert or update calendar data. The manifest entry is only the start, because the person is still asked at runtime and can still say no.

Then there is the escape hatch, and most apps should take it. The same documentation says that using the INSERT intent lets your application hand off the event insertion task to the Calendar itself, and that with this approach your application does not even need to have the WRITE_CALENDAR permission in its manifest file. The person lands in their own calendar app with the fields already filled in, and saves it or does not.

iOS has the same shape. Apple's note on the write only key says that if your app runs on iOS 17 or later and presents an EKEventEditViewController so people can create calendar events, you do not need to request calendar access. One sheet, no alert, and no refusal to design around.

The trade is identical on both platforms: you learn nothing. Expo documents that the dialog result carries an event id on iOS when permission was granted and the person confirmed, and that on Android the id is always null and the reported action is always done, because the platform does not say whether the event was saved, cancelled or deleted. That is fine for a one-off. It stops being fine the moment a booking can move.

Android, Calendar provider overview

Why the second run creates duplicates

Nearly every calendar feature fails the same way. You write an event, the job runs again, and now there are two. The fix is not clever matching on title and start time. To sync appointments to a calendar and keep them in step, the write has to hand back an identifier, you store that identifier against your own booking, and every later touch is an update or a delete on it rather than a fresh insert.

Keep that id in your own data rather than trusting the calendar to hold your state. The calendar belongs to the person and they can delete anything in it. So your booking row carries the event id, the calendar it went to, and when you last wrote. When the id no longer resolves, you decide what that means: put it back, or take the hint and stop.

Three details break integrations after launch. Time zones, because Android's provider requires an event time zone on a direct insert and a meeting stored in the wrong one lands an hour out for somebody. Recurrence, because a repeating booking is one record with a rule and a pile of exceptions, not a list of dates. And cancellation, because a booking killed in your app has to reach a calendar that never asks you anything. This is the point where a booking tool quietly becomes an appointment reminder app with a calendar feature attached.

Full two-way sync with Google Calendar or Microsoft 365 is a different animal again. It means OAuth, refresh tokens you have to keep alive, change notifications, and a reconciliation pass for the hours your listener was down. Price it as a backend project with a mobile front end, not as a feature on a screen.

Five things called calendar sync, and what each one costs

ApproachNeeds a calendar permissionWorks when your app is closedSurvives an edit in their calendarWhat you give up
Reminder inside your own appNoas a scheduled notificationnothing to surviveIt never leaves your app
Prefilled event sheet handoffNoNoyou never hear about itNo record that anything was saved
Writing to the device calendarYesNoonly if you stored the event idA refusal you have to design around
A feed they subscribe toNoYesread only, they cannot edit itUpdates arrive on the calendar's schedule
Two-way with a Google or Outlook accountNoYesYesOAuth, tokens, listeners and a server

Building the calendar piece into the rest of the app

Calendar work is rarely the product. It is the last mile of a booking, a rota, a delivery slot or a course. That is why bolt-on calendar plugins disappoint. They get an event onto a phone and leave the thing that created the event living in a spreadsheet. The first decision worth making is which record is the truth, yours or the calendar's, because everything after it follows from that answer.

Newly is an AI app builder. You describe the app in plain English and it writes a real React Native and Expo project you own, then ships it to TestFlight and to Google Play internal testing from the Deploy tab. It is $25 a month and there is no free plan. The code comes out as a ZIP or through two-way GitHub sync, which matters here, because the permission sentence and the copy around a refusal are exactly the things you will want to tune by hand after the first build.

One thing to settle before any of that. Work out whose calendar it is, because a shared staff rota, a manager who can move other people's bookings and a customer's own phone are three different permission problems that look identical on a screen.

Questions people ask about calendar sync

Pick the job first. To put an event on the phone, declare the permission, then either write to the device calendar or hand the person a prefilled event sheet. To keep your app in step with a Google or Outlook account, you need OAuth, stored tokens and a server that runs without the app. The first is a day or two. The second is an ongoing backend project.

Describe the booking, not the calendar

Write down what creates the event, who is allowed to move it, and what has to happen when it is cancelled. Build the calendar piece around those three answers.

Start building