Get your dream built 10x faster

How to integrate Apple Reminders with OpenClaw

We build custom applications 5x faster and cheaper 🚀

Book a Free Consultation
4.9
Clutch rating 🌟
600+
Happy partners
17+
Countries served
190+
Team members
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Stuck on an error? Book a 30-minute call with an engineer and get a direct fix + next steps. No pressure, no commitment.

How to integrate Apple Reminders with OpenClaw

Integrating Apple Reminders with OpenClaw requires a bridge because Apple does not expose a public server-side Reminders API; the reliable, supported approach is to run client-side code (an iOS or macOS helper app or a Shortcuts flow) that uses EventKit to read/write Reminders with the user’s permission and then forward those events securely to a backend that your OpenClaw skill can consume. Configure authentication explicitly (OAuth or API keys), register and configure the skill in ClawHub to use that backend endpoint (and store secrets as environment variables or service credentials), keep persistent state and queues outside the agent runtime, and instrument logging and retries so you can debug failures by inspecting logs, API responses, and token/scopes.

 

Overview and constraints

 
  • Apple constraints: There is no official Apple-provided public REST API for iCloud Reminders that’s intended for third-party server integrations. The supported, documented client API is EventKit on iOS/macOS, which runs on-device and requires user permission.
  • What that implies: You must run code on the user’s device (or use Shortcuts) to access reminders, then forward data to a trusted server that OpenClaw can reach. Avoid using unsupported/private iCloud endpoints — they can break and violate terms of service.
  • OpenClaw model to follow: Everything OpenClaw does is explicit: configure a skill in ClawHub, provide webhook/API endpoints and credentials, and ensure the skill’s runtime calls or receives calls to your external service. Persistent/stateful systems must live outside the agent runtime (databases, message queues, schedulers).

 

Architecture patterns (pick one)

 
  • Device-side bridge (recommended): Build an iOS/macOS helper app using EventKit to read reminders and POST them to your backend. This is robust and uses supported APIs.
  • Shortcuts + webhook: Use Apple Shortcuts to forward reminders to a webhook on your backend (requires user setup and is lighter-weight but less flexible than a full app).
  • Unsupported approaches (not recommended): Reverse-engineered iCloud APIs — fragile and may violate terms; do not use for production integrations.

 

Step-by-step: Device-side bridge (detailed)

 
  • High-level flow: Device app (EventKit) → secure HTTPS request → Backend (webhook API) → store/process → OpenClaw skill configured in ClawHub either to receive events (webhook) or to poll/backend API.
  • Why an external backend: Agents are ephemeral and not suitable for persistent storage, background scheduling, or retry logic. Keep DBs, queues, and schedulers off-agent.

 

Device code (Swift) — read reminders and forward them

 
import EventKit
import Foundation

let store = EKEventStore()

<b>// Request access to reminders</b>
store.requestAccess(to: .reminder) { granted, error in
  guard granted, error == nil else {
    print("Reminders access denied or error:", error ?? "unknown")
    return
  }

  <b>// Create a predicate for incomplete reminders (example)</b>
  let calendars = store.calendars(for: .reminder)
  let predicate = store.predicateForReminders(in: calendars)

  store.fetchReminders(matching: predicate) { reminders in
    guard let reminders = reminders else { return }

    let jsonArray: [[String: Any]] = reminders.compactMap { r in
      return [
        "id": r.calendarItemIdentifier,
        "title": r.title ?? "",
        "notes": r.notes ?? "",
        "completed": r.isCompleted,
        "dueDate": r.dueDateComponents?.date?.iso8601String ?? NSNull()
      ]
    }

    guard let url = URL(string: "https://api.your-backend.example.com/v1/reminders") else { return }
    var req = URLRequest(url: url)
    req.httpMethod = "POST"
    req.setValue("application/json", forHTTPHeaderField: "Content-Type")
    <b>// Use a secure auth scheme (Bearer token / short-lived JWT)</b>
    req.setValue("Bearer YOUR_DEVICE_TOKEN", forHTTPHeaderField: "Authorization")

    do {
      req.httpBody = try JSONSerialization.data(withJSONObject: ["reminders": jsonArray], options: [])
    } catch {
      print("JSON encoding error:", error)
      return
    }

    let task = URLSession.shared.dataTask(with: req) { data, resp, err in
      if let err = err { print("Network error:", err); return }
      if let http = resp as? HTTPURLResponse, http.statusCode >= 400 {
        print("Server error:", http.statusCode)
      } else {
        print("Forwarded reminders successfully")
      }
    }
    task.resume()
  }
}

 

Backend webhook example (Node.js + Express)

 
const express = require('express')
const bodyParser = require('body-parser')
const crypto = require('crypto')

const app = express()
app.use(bodyParser.json())

<b>// Shared secret to validate device requests (or validate JWT)</b>
const SHARED_SECRET = process.env.DEVICE_SHARED_SECRET

function validateSignature(req) {
  <b>// Example: HMAC over payload with shared secret</b>
  const sig = req.get('X-Signature') || ''
  const body = JSON.stringify(req.body)
  const expected = crypto.createHmac('sha256', SHARED_SECRET).update(body).digest('hex')
  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))
}

app.post('/v1/reminders', (req, res) => {
  if (!validateSignature(req)) return res.status(401).send('invalid signature')

  const reminders = req.body.reminders || []
  <b>// Persist reminders into a database or push into a queue for processing</b>
  // db.saveReminders(reminders)

  <b>// Option A: Notify OpenClaw by making an explicit API call that your skill expects</b>
  <b>// Option B: The OpenClaw skill can poll this backend or consume a message queue (preferred for scale)</b>

  res.status(200).json({ received: reminders.length })
})

app.listen(3000, () => console.log('webhook running on :3000'))

 

How to wire this to OpenClaw (vendor-neutral, actionable)

 
  • Skill registration: In ClawHub create or register your OpenClaw skill and configure the skill’s external integration settings to point to your backend endpoints (webhook URL or API base) — store any required credentials (API keys, client IDs, client secrets) as environment variables or service credentials in ClawHub.
  • Authentication model: Use OAuth where user delegation is required (e.g., if your backend performs actions on behalf of a user) or use service-to-service tokens/API keys for server-level calls. Keep secrets out of code and in secure vaults / ClawHub environment settings.
  • Invocation style: Decide whether the skill should be event-driven (your backend posts events directly to an endpoint that the skill listens to or which triggers the agent) or polling-based (the agent calls your backend APIs to fetch new reminders). For scale and reliability, publish incoming reminders to a queue and have worker(s) process them; the agent can pick up work from the queue.
  • Secrets & scopes: Ensure OAuth scopes and API scopes only grant minimum permissions needed. If you expose device-to-backend endpoints, validate requests (HMAC, mutual TLS, or JWT) to prevent spoofing.

 

Persistence, reliability, and operations

 
  • Keep state external: Store reminders, processing state, and retry queues in external systems (Postgres, Redis, SQS/RabbitMQ). Agents should be stateless.
  • Retries and idempotency: Design your webhook and processing to be idempotent (use reminder ID and dedupe). Implement retry policies for transient failures.
  • Logging and observability: Emit structured logs at device forwarding, backend ingest, and skill invocation points. Correlate with request IDs and timestamps.
  • Security: Use HTTPS, validate signatures, rotate keys regularly, and keep secrets in ClawHub’s secret store or your vault.

 

Debugging checklist when things break

 
  • Device side: Confirm EventKit permissions granted, check device logs, verify the HTTP request is sent and contains the right Authorization header or HMAC signature.
  • Network: Confirm DNS and TLS (certificate) validity for your backend endpoint from the device and from the OpenClaw environment.
  • Backend: Inspect access logs, signature validation errors, and payload parsing errors. Ensure the DB/queue is reachable and not throwing errors.
  • OpenClaw side: Verify the skill is configured with the correct endpoint and secrets in ClawHub. Check agent execution logs to confirm the skill was invoked and record the HTTP API responses.
  • Tokens & scopes: Confirm tokens aren’t expired, revoke/reissue if required, and ensure scopes cover the exact operations needed.

Book Your Free 30‑Minute Migration Call

Speak one‑on‑one with a senior engineer about your no‑code app, migration goals, and budget. In just half an hour you’ll leave with clear, actionable next steps—no strings attached.

Book a Free Consultation

Troubleshooting Apple Reminders and OpenClaw Integration

1

Why does EventKit authorization for Apple Reminders fail in the OpenClaw ClawConnector even after adding NSRemindersUsageDescription?

Because the OpenClaw ClawConnector typically runs inside the OpenClaw agent/runtime (a non‑UI or extension host) iOS cannot present the Reminders permission prompt. Adding NSRemindersUsageDescription to your project’s Info.plist is necessary but not sufficient—the key must be in the Info.plist of the actual running target (the host app or extension) and the request must be made from a UI‑capable process.

 

What to check

 

Verify these points before retrying:

  • Info.plist placement: the key appears in the final binary’s Info.plist (host app or extension target).
  • Runtime context: ClawConnector runs where permission prompts are allowed; app extensions or background agents can’t show dialogs.
  • Device testing: reminders permission often behaves differently on simulator.
let store = EKEventStore()
store.requestAccess(to: .reminder) { granted, error in
  <b>//</b> update UI or handle denial on main queue
}

2

Why are duplicate ClawTask entries created when syncing EKReminder items to the OpenClaw SyncEngine (identifier mismatch between EKReminder and ClawTask.id)?

Direct answer: Duplicate ClawTask entries appear because the EKReminder's identifier isn't being used as the stable key when creating/updating ClawTask records. If each sync creates a new ClawTask.id (or doesn't persist the EKReminder.identifier into a consistent external key), the SyncEngine can't match existing tasks and inserts duplicates.

 

Why this happens and how to fix it

 
  • Root cause: identifier mismatch or missing mapping between EKReminder.identifier and the ClawTask identity used by the SyncEngine.
  • Fix: persist EKReminder.identifier as the canonical key (either set ClawTask.id or store in task metadata) and perform upsert/match by that key instead of always creating a new record.
  • Operational tips: add idempotent checks, logging of identifiers, and guard against race conditions during concurrent syncs.

3

How should EKRecurrenceRule and alarms from Apple Reminders be mapped to the OpenClaw RecurrenceModel in the ClawMapper to preserve repeat rules and reminders?

Direct answer: Map an EKRecurrenceRule’s core components into OpenClaw’s RecurrenceModel fields: frequency (daily/weekly/monthly/yearly), interval, weekday set (byWeekday), month-day or month-position rules (byMonthDay / bySetPosition), and the end condition (count or until/date). Convert Apple alarms into RecurrenceModel.reminders as either absolute timestamps or relative offsets (seconds before/after occurrence). Keep original RRULE/EK metadata in a raw field for fidelity.

 

Details

 

Practical mapping:

  • frequency: map EKFrequency to RecurrenceModel.frequency.
  • interval: copy interval.
  • byWeekday: map EKWeekday + week position to byWeekday/bySetPosition.
  • end: map EKRecurrenceEnd.date -> until; EKRecurrenceEnd.count -> count.
  • timezone/start: preserve startDate and timezone to compute occurrences.
  • alarms: absolute -> reminder.timestamp; relative -> reminder.offsetSeconds (negative before, positive after).
  • fallback: store raw RRULE/EK objects in metadata if any field can’t be represented exactly.

4

Why do changes in Apple Reminders not trigger the OpenClaw ClawSyncDaemon background sync or ClawWebhook notifications on iOS/macOS?

Changes in Apple Reminders don’t reliably trigger ClawSyncDaemon background sync or ClawWebhook because iOS/macOS restricts background execution, Reminders data is managed by Apple (EventKit/iCloud/CloudKit) without a public push hook, and OpenClaw agents run only when explicitly scheduled or authorized. In short: the system doesn’t deliver an immediate, third-party-consumable change event by default, and ClawSyncDaemon/Webhook need explicit configuration and a reachable notification path.

 

Why this happens and what to check

 

Common causes to verify:

  • Background limits: iOS suspends apps/agents; no persistent daemon unless using supported background modes or server push.
  • Permissions: EventKit access and user grants are required; without them the agent can’t read reminders.
  • No public Reminders webhook: Apple provides no direct external webhook for Reminders—CloudKit sync is eventual.
  • Claw config: Ensure ClawSyncDaemon is scheduled, has credentials, and ClawWebhook endpoints are validated.
  • Workarounds: Use server-side polling, CloudKit subscriptions where available, or an authorized app that forwards changes to your webhook.
Book a Free Consultation

Still stuck?
Copy this prompt into ChatGPT and get a clear, personalized explanation.

This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.

AI AI Prompt


Recognized by the best

Trusted by 600+ businesses globally

From startups to enterprises and everything in between, see for yourself our incredible impact.

RapidDev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with.

They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

Arkady
CPO, Praction
Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost.

He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Donald Muir
Co-Founder, Arc
RapidDev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space.

They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Mat Westergreen-Thorne
Co-CEO, Grantify
RapidDev is an excellent developer for custom-code solutions.

We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Emmanuel Brown
Co-Founder, Church Real Estate Marketplace
Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 

This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Samantha Fekete
Production Manager, Media Production Company
The pSEO strategy executed by RapidDev is clearly driving meaningful results.

Working with RapidDev has delivered measurable, year-over-year growth. Comparing the same period, clicks increased by 129%, impressions grew by 196%, and average position improved by 14.6%. Most importantly, qualified contact form submissions rose 350%, excluding spam.

Appreciation as well to Matt Graham for championing the collaboration!

Michael W. Hammond
Principal Owner, OCD Tech

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.Â