You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Human accounts, event webhooks, claim recommendations, and test coverage
- Human accounts: signup/login/dashboard with session auth, X-Human-Key header
for API claiming, POST /agents/claim, auto-claim on POST /agents
- Event webhooks: fire-and-forget POST to calendar webhook_url on event CRUD,
HMAC-SHA256 signing via webhook_secret, POST /calendars/:id/webhook/test
- Claim recommendations: GET /man and GET /changelog suggest unclaimed agents
with events should be claimed by a human account
- Docs: split "Feeds & Webhooks" into "Feeds & Inbound Email" + "Event Webhooks",
clarified inbound email vs event webhook terminology throughout
- Tests: 19 new tests covering human auth flow, POST /agents/claim, calendar
view (GET /view), webhook test endpoint; helpers now support custom headers
- Docker: NODE_ENV passthrough in docker-compose for test rate limit bypass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CALDAVE_SPEC.md
+85-33Lines changed: 85 additions & 33 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,16 +69,19 @@ Agents need to know when it's time to act. Two mechanisms:
69
69
70
70
**Polling (primary):** Agents call `GET /calendars/:id/upcoming` to check what's next. Simple, stateless, works with any agent framework.
71
71
72
-
**Webhooks (optional, per-calendar):** A calendar can register a webhook URL. CalDave sends a POST to that URL at configurable offsets before an event starts (e.g. 5 minutes before). Webhook delivery uses a simple retry policy (3 attempts, exponential backoff).
72
+
**Webhooks (optional, per-calendar):** A calendar can register a webhook URL. CalDave sends a POST to that URL whenever events are created, updated, deleted, or responded to — whether via the API or inbound email. Payloads are signed with HMAC-SHA256 if a `webhook_secret` is set. Delivery is fire-and-forget.
73
73
74
74
---
75
75
76
76
## Auth Model
77
77
78
78
| Concept | Details |
79
79
|---------|---------|
80
-
|**API Key**| Bearer token, one per agent. Sent as `Authorization: Bearer <key>`|
80
+
|**Agent API Key**| Bearer token, one per agent. Sent as `Authorization: Bearer sk_live_...`|
81
+
|**Human API Key**| One per human account. Passed as `X-Human-Key` header for claiming agents. |
81
82
|**Provisioning**|`POST /agents` returns `agent_id` + `api_key`. Agent must store these — the key is shown once. |
83
+
|**Human Accounts**| Humans sign up at `/signup` to get a dashboard and human API key (`hk_live_...`). |
84
+
|**Agent Claiming**| Humans claim agents by providing the agent's `sk_live_` key — via dashboard or `POST /agents/claim` with `human_key`. |
82
85
|**Scoping**| An API key grants access to all calendars owned by that agent. No cross-agent access. |
83
86
84
87
---
@@ -88,7 +91,12 @@ Agents need to know when it's time to act. Two mechanisms:
88
91
### Agent Provisioning
89
92
90
93
#### `POST /agents`
91
-
Creates a new agent identity. No auth required. Optionally accepts `name` and `description` to identify the agent.
94
+
Creates a new agent identity. No auth required. Optionally accepts `name` and `description` to identify the agent. Pass the `X-Human-Key` header to associate with a human account.
95
+
96
+
**Headers (optional):**
97
+
| Header | Description |
98
+
|--------|-------------|
99
+
|`X-Human-Key`| Human API key (`hk_live_...`) to auto-associate the new agent |
92
100
93
101
**Request (optional):**
94
102
```json
@@ -105,7 +113,35 @@ Creates a new agent identity. No auth required. Optionally accepts `name` and `d
105
113
"api_key": "sk_live_abc123...",
106
114
"name": "My Assistant",
107
115
"description": "Manages team calendars and sends meeting reminders",
108
-
"message": "Store these credentials securely. The API key will not be shown again."
116
+
"message": "Store these credentials securely. The API key will not be shown again.",
117
+
"owned_by": "hum_abc123..."
118
+
}
119
+
```
120
+
121
+
The `owned_by` field only appears when `X-Human-Key` header is provided.
122
+
123
+
#### `POST /agents/claim`
124
+
Claim an existing agent by providing its API key. Requires `X-Human-Key` header.
125
+
126
+
**Headers:**
127
+
| Header | Description |
128
+
|--------|-------------|
129
+
|`X-Human-Key`|**Required.** Human API key (`hk_live_...`) |
130
+
131
+
**Request:**
132
+
```json
133
+
{
134
+
"api_key": "sk_live_abc123..."
135
+
}
136
+
```
137
+
138
+
**Response:**
139
+
```json
140
+
{
141
+
"agent_id": "agt_x7y8z9",
142
+
"agent_name": "My Assistant",
143
+
"claimed": true,
144
+
"owned_by": "hum_abc123..."
109
145
}
110
146
```
111
147
@@ -444,26 +480,29 @@ Set or update webhook configuration:
444
480
}
445
481
```
446
482
447
-
**Webhook payload (POST to the registered URL):**
483
+
#### Webhook Event Types
484
+
485
+
When a calendar has a `webhook_url` configured, CalDave automatically delivers a webhook POST whenever events change — via the API or inbound email.
486
+
487
+
| Type | Trigger |
488
+
|------|---------|
489
+
|`event.created`| New event via POST or inbound email |
490
+
|`event.updated`| Event modified via PATCH or inbound email update |
491
+
|`event.deleted`| Event deleted via DELETE or inbound email CANCEL |
492
+
|`event.responded`| Event accepted/declined/tentative via POST respond |
Signature is HMAC-SHA256 of the body using `webhook_secret`.
460
-
461
-
#### `GET /calendars/:id/webhook-logs`
462
-
List webhook delivery attempts for a calendar. Supports query params:
463
-
-`status` — filter by `pending` / `delivered` / `failed`
464
-
-`limit` / `offset` — pagination
465
-
466
-
Useful for debugging failed deliveries.
505
+
If `webhook_secret` is set, the payload is signed with HMAC-SHA256 and sent in the `X-CalDave-Signature` header. Delivery is fire-and-forget (no retries). Use `POST /calendars/:id/webhook/test` to verify your endpoint.
467
506
468
507
---
469
508
@@ -477,9 +516,9 @@ Read-only iCalendar feed. Can be subscribed to from Google Calendar, Apple Calen
Per-calendar endpoint for receiving forwarded emails containing `.ics` calendar invite attachments. Creates, updates, or cancels events based on the iCal METHOD.
481
520
482
-
No Bearer auth. The unguessable `inbound_token` in the URL authenticates the request. Each calendar gets its own unique webhook URL (returned at creation as `inbound_webhook_url`).
521
+
No Bearer auth. The unguessable `inbound_token` in the URL authenticates the request. Each calendar gets its own unique inbound URL (returned at creation as `inbound_webhook_url`).
483
522
484
523
Supports multiple email-to-webhook providers:
485
524
-**Postmark Inbound** — attachments include base64 content inline in the webhook payload
@@ -691,18 +730,32 @@ For local development or offline use, run the STDIO server directly:
691
730
-`calendars(email)` — for inbound email lookup
692
731
-`calendars(inbound_token)` — partial index for webhook URL lookup
1.**Agent provisioning auth** — Open, no operator key. Rate-limited (see Rate Limits section).
750
803
2.**Feed authentication** — Token required. Feed URLs include a token param: `/feeds/:calendar_id.ics?token=feed_abc123`. Token is generated at calendar creation and returned in the response.
751
-
3.**Webhook logs** — Failed deliveries are queryable via `GET /calendars/:id/webhook-logs`.
804
+
3.**Webhook delivery** — Fire-and-forget on event mutations. Use `POST /calendars/:id/webhook/test` to verify endpoint reachability.
752
805
4.**Domain** — `caldave.ai` for v1. Email addresses: `cal-abc123@caldave.ai`.
753
806
5.**Event size limits** — 64KB for description, 16KB for metadata JSON.
754
807
6.**Outbound email** — Implemented. Creating/updating events with attendees sends METHOD:REQUEST invite emails via Postmark. Responding to inbound invites sends METHOD:REPLY emails to the organiser. Requires `POSTMARK_SERVER_TOKEN` env var; gracefully skipped if not set.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+12-5Lines changed: 12 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
7
7
## [Unreleased]
8
8
9
9
### Added
10
+
-**Webhook delivery on event mutations** — Calendars with a `webhook_url` now receive automatic webhooks when events are created, updated, deleted, or responded to. Works for both API operations and inbound email invites. Event types: `event.created`, `event.updated`, `event.deleted`, `event.responded`. Payloads are signed with HMAC-SHA256 if `webhook_secret` is set. Delivery is fire-and-forget (no retries).
11
+
-**Human accounts with agent key claiming** — Humans can sign up at `/signup`, log in at `/login`, and manage their agent keys from a `/dashboard`. Agents are claimed by providing the agent's secret key (`sk_live_...`) — if you have the key, you own it. No calendar invites needed.
12
+
-**Human API keys** (`hk_live_...`) — pass via `X-Human-Key` header to `POST /agents` to auto-associate new agents, or to `POST /agents/claim` to claim existing agents programmatically.
13
+
-**Dashboard** — web UI to view claimed agents, claim new ones by pasting a secret key, and release agents.
14
+
-**Session auth** — cookie-based sessions for the dashboard (7-day expiry, automatic cleanup).
15
+
- New tables: `humans`, `human_agents`, `human_sessions`.
16
+
10
17
-**MCP server at full parity with API** — Added 16 new MCP tools covering all documented API endpoints. Previously the MCP server only had 8 core tools; it now exposes 24 tools matching every REST endpoint:
@@ -48,7 +55,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
48
55
-**Personalized recommendations in changelog** — `GET /changelog` with auth now includes a `recommendations` array with actionable suggestions based on agent state (e.g. name your agent, create your first calendar, add a description).
49
56
-**API changelog endpoint** — `GET /changelog` returns a structured list of API changes with dates and docs links. With optional Bearer auth, highlights changes introduced since the agent was created. Designed for agents to poll ~weekly.
50
57
-**Agent metadata** — `POST /agents` now accepts optional `name` and `description` fields to identify agents. New `GET /agents/me` returns the agent's profile. New `PATCH /agents` updates metadata without changing the API key. Agent name and description are surfaced in `GET /man` context.
51
-
-**Outbound calendar invites** — when an event is created or updated with attendees, CalDave sends METHOD:REQUEST iCal invite emails via Postmark. Invites include `.ics` attachments that work with Google Calendar, Outlook, and Apple Calendar. From address is the calendar's email so replies route back through the inbound webhook.
58
+
-**Outbound calendar invites** — when an event is created or updated with attendees, CalDave sends METHOD:REQUEST iCal invite emails via Postmark. Invites include `.ics` attachments that work with Google Calendar, Outlook, and Apple Calendar. From address is the calendar's email so replies route back through inbound email.
52
59
-**Agent name in outbound emails** — when an agent has a name set (via `PATCH /agents`), outbound invite and RSVP reply emails use `"Agent Name" <calendar-email>` as the From address, so recipients see a friendly display name instead of just the calendar email.
53
60
-**Outbound RSVP replies** — when an agent responds to an inbound invite via `POST /respond`, CalDave sends a METHOD:REPLY iCal email back to the organiser with the agent's acceptance, decline, or tentative status.
54
61
-**Graceful degradation** — if `POSTMARK_SERVER_TOKEN` is not set, outbound emails are silently skipped. All API endpoints continue to work normally.
@@ -111,8 +118,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
111
118
- Uses `rrule` npm package for RRULE parsing and expansion
112
119
-**API documentation page** (`GET /docs`) — self-contained HTML docs with curl examples for every endpoint, copy buttons, quick start guide, and dark theme matching the status page
0 commit comments