Skip to content
Skip to main content

Schedule reminders from calendar events

Last updated:

Calendar apps send push notifications to the person who owns the event. That’s fine if you only need to remind yourself. The moment your application needs to reach other people — patients before an appointment, students before a tutoring session, prospects before a demo — built-in notifications fall short. You need branded, personalized email reminders sent on behalf of your users.

This recipe builds that. A scheduled job scans a calendar for events starting soon, filters out the noise, and sends a tailored HTML reminder to each attendee. A webhook listener catches reschedules and cancellations and pushes updates the same way. The whole thing runs across Google Calendar, Microsoft, and Exchange without provider-specific code.

How the reminder pipeline sends and updates reminders

A scheduled scan sends reminders before events start. Webhooks catch reschedules and cancellations after a reminder went out. Both paths share one dedup store. Subscribe to event.updated and event.deleted in the Dashboard or with POST /v3/webhooks.
Diagram as text
  • Two paths run side by side:
    • Scheduled scan
      • Your backend: List upcoming events: Every 15 minutes, GET /v3/grants/{grant_id}/events for the next 24 hours.
      • Your backend: Filter the events: Keep timed events that still need a reminder.
        • Skipped: All-day events, where when.object is date or datespan.
        • Skipped: Cancelled events.
        • Skipped: Events with no participants besides the organizer.
        • Skipped: Events already in the dedup store.
      • Your backend: Send the reminder: POST /v3/grants/{grant_id}/messages/send to the event's external participants.
      • Your backend: Record the reminder: Save the event ID, plus the title and participants for later cancellations.
    • Event changes
      • Nylas: Send a webhook: event.updated or event.deleted when the event changes or is deleted.
      • Your backend: Look up the reminder: Find the event ID in the dedup store.
        • No reminder sent → Ignore it
      • Your backend: Send an update or cancellation: Deleted or cancelled events get a cancellation. Other changes get an update.
      • Your backend: Update the record: Remove it after a cancellation.
  • Your backend: Shared dedup store: One record per event ID, read and written by both paths.

Two flows around one shared dedup store. The cron handles proactive sends; the webhook handles reactive updates.

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)

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)

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.

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.

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.

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:

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.

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.