Notion Adapter: Polling-Only Architecture
Notion Adapter: Polling-Only Architecture
Note: This page documents an intentional architectural decision. The Notion adapter does not use webhooks. This is expected behaviour, not a bug.
Overview
The Sidekick Notion adapter (src/lib/integrations/adapters/notion/index.ts) is registered in the platform's adapter index alongside all other integrations, but it operates exclusively through scheduled polling rather than webhook delivery. This document explains why, and what that means in practice.
Why Polling?
Notion's public API does not provide outbound webhook support. There is no mechanism for Notion to push change events to an external service. As a result, the Notion adapter cannot participate in the real-time webhook pipeline that most other adapters use.
Instead, Notion data is synchronised by the sync-poll-integrations cron job, which runs on a scheduled interval and pulls the latest state from the Notion API.
Webhook Endpoint Behaviour
Sidekick includes a generic catch-all route:
POST /api/webhooks/[adapter_id]
If this route is called with adapter_id = notion (e.g. POST /api/webhooks/notion), it will return:
HTTP 200
{ "processed": 0 }
This is technically a successful response, but zero events will be processed. There is no dedicated /api/webhooks/notion route and the Notion adapter is not wired into the webhook dedup index. Receiving a request at this endpoint for Notion is a no-op.
Architectural Asymmetry
Because Notion uses polling while most other adapters use webhooks, there is a deliberate asymmetry in how the adapter is set up:
| Property | Webhook-based adapters | Notion adapter |
|---|---|---|
| Registered in adapter index | ✅ | ✅ |
| Dedicated webhook route | ✅ | ❌ (not needed) |
| Included in dedup index | ✅ | ❌ (intentional) |
| Polling via cron | ❌ | ✅ |
This asymmetry is intentional and correct. Do not add Notion to the webhook dedup index or create a /api/webhooks/notion route unless Notion officially supports webhooks.
Future Webhook Support
If Notion adds native webhook support, the following changes will be required:
- Create a dedicated route at
POST /api/webhooks/notionwith signature verification. - Add the adapter to the webhook dedup index imports so duplicate event delivery is handled correctly.
- Evaluate the polling cron — it can either be retired, or kept running in parallel as a fallback for missed events.
- Update this document to reflect the new hybrid or webhook-only architecture.
Related
- Changelog — v1.0.56
- Cron job:
sync-poll-integrations - Adapter source:
src/lib/integrations/adapters/notion/index.ts - Generic webhook route:
src/app/api/webhooks/[adapter_id]/route.ts