Skip to content

How to schedule reminders from calendar events

Calendar apps send push notifications to the person who owns the event. That works fine if you only need to remind yourself. But the moment your application needs to reach other people, built-in notifications fall short. A healthcare platform needs to remind patients about upcoming appointments. A tutoring service needs to ping students before a session starts. A sales tool needs to nudge prospects so they actually show up to demos.

These are email reminders, not push notifications, and they need to be personalized, branded, and sent on behalf of your users. This tutorial builds exactly that: a system that periodically scans a calendar for upcoming events and sends tailored reminder emails to each attendee using the Nylas Calendar and Email APIs.

The reminder system runs on a simple loop:

  1. A scheduled job runs every 15 minutes and queries the Nylas Calendar API for events starting in the next 24 hours.
  2. The job filters events to skip all-day events, events without external participants, and events that already received a reminder.
  3. For each qualifying event, the job composes a personalized HTML email with the meeting time, location, conferencing link, and agenda.
  4. The job sends the reminder to each attendee using the Nylas Email API and records the event ID to prevent duplicates.
  5. A webhook listener watches for event.updated and event.deleted triggers so your system can send updated or cancellation notices when meetings change.

The result is a hands-free reminder pipeline that works across Google Calendar, Outlook, and Exchange without any provider-specific code.

Make sure you have the following before starting this tutorial:

  • A Nylas account with an active application
  • A valid API key from your Nylas Dashboard
  • At least one connected grant (an authenticated user account) for the provider you want to work with
  • Node.js 18+ or Python 3.8+ installed (depending on which code samples you follow)

New to Nylas? Start with the quickstart guide to set up your app and connect a test account before continuing here.

You also need:

  • A connected grant with calendar read access and email send access for the account you want to send reminders from
  • A calendar ID for the calendar you want to scan (use the List Calendars endpoint to find it)
  • A persistent store for tracking which events have already received reminders (a database table, Redis set, or even a local JSON file for prototyping)

One grant handles both read and send. The same connected account that reads calendar events can also send reminder emails. You do not need separate grants for calendar and email access.

Query the Nylas Calendar API for events in a time window. The Events API accepts start and end query parameters as Unix timestamps, so you can request exactly the window you care about. A 24-hour lookahead works well for most reminder systems.

The start and end parameters are Unix timestamps in seconds. They filter events whose time range overlaps with the window you specify. Use the next_cursor value from the response to paginate through large result sets.

Not every event deserves a reminder. All-day events (like holidays or out-of-office blocks) rarely need one. Events where you are the only participant are just calendar holds. And you definitely do not want to send the same reminder twice.

The key design decisions: track by event ID for deduplication, filter by when.object to distinguish timed events ("timespan") from all-day events ("date" or "datespan"), and exclude the organizer’s email so they do not receive their own reminder.

An in-memory set resets when your process restarts. For production, use a database keyed by event ID with a timestamp so you can distinguish “reminder sent” from “update needed” if the event changes later.

For each qualifying event, build a personalized email and send it through the Nylas Email API. Include the meeting title, time, location or conferencing link, and any agenda from the event description.

Use the POST /v3/grants/<NYLAS_GRANT_ID>/messages/send endpoint to deliver the reminder to each attendee.

Each reminder email is sent from the account associated with your grant. If the grant belongs to a service account, all reminders come from that address. If it belongs to an individual user, reminders come from their personal email. Choose the grant that matches your desired sender identity.

Reminders are only useful if they reflect the current state of the event. When someone reschedules or cancels a meeting after you already sent a reminder, you need to notify attendees.

Subscribe to event.updated and event.deleted webhooks:

Then handle updates and cancellations. Only act on events you have already sent reminders for:

The event.deleted payload is minimal. It only includes the event ID, grant ID, and calendar ID. Store event metadata (title, participants) alongside the reminder record in your database so you can compose a useful cancellation email even after the event is gone.

Tie the pieces together with a scheduled job. Use node-cron in Node.js or schedule in Python to run the scan every 15 minutes.

Combine the cron job and webhook handler in one process. Run the Express or Flask server for webhooks alongside the scheduled scanner. The cron job handles proactive reminders, while the webhook listener reacts to changes. Together, they cover both sides of the problem.

A few practical details that will save you time in production:

  • Timezone handling is the hardest part. Events include start_timezone and end_timezone fields, but not all providers populate them consistently. Always fall back to UTC if the timezone is missing, and format times using the event’s timezone rather than your server’s local time. An attendee in Tokyo does not want to see a time formatted for Chicago.

  • All-day events use a different when object. Timed events have when.object set to "timespan" with Unix timestamps. All-day events use "date" (single day) or "datespan" (multi-day) with date strings like "2024-03-15". Check the when.object value rather than looking for missing timestamps.

  • Recurring events produce separate instances. When you query the Events API with a time range, each occurrence of a recurring series appears as its own event with its own ID. You do not need to expand recurrence rules yourself. Track reminders by the individual occurrence ID, not the master_event_id.

  • Rate limits apply to both APIs. Nylas enforces rate limits per grant. If you are sending reminders for a calendar with dozens of events, add a small delay between email sends. For high-volume use cases, queue your sends and process them with a rate-limited worker.

  • Deduplication prevents double reminders. Your scan runs on a schedule, so the same event appears in multiple scans. Without deduplication, an attendee could receive the same reminder every 15 minutes. In production, store the event ID alongside a hash of key fields (time, title, participants) so you can detect whether the event changed enough to warrant a new notification.

  • Some providers sync with a delay. Google Calendar events typically appear in Nylas within seconds. Microsoft and Exchange accounts may take slightly longer. If your reminder window is narrow (for example, 30 minutes before the event), factor in sync latency to avoid missing recently created events.

  • Do not hardcode calendar IDs. The primary calendar ID varies by provider. Google uses the user’s email address. Microsoft uses a long opaque string. Use the List Calendars endpoint to discover calendars dynamically.