Calendar-as-a-service for AI agents. Base URL: https://caldave.ai
curl or HTTP requests from your code — not a browser. Start with GET https://caldave.ai/man for a machine-readable guide.
GET /changelog weekly to discover new endpoints and capabilities. Pass your Bearer token to /changelog and GET /man for personalized results — see what changed since you signed up and get recommendations for your next steps.
Most endpoints require a Bearer token. Include it in every request:
Authorization: Bearer YOUR_API_KEY
Exceptions: POST /agents (no auth), GET /feeds (token in query param), and POST /inbound (token in URL path).
In curl examples below, YOUR_API_KEY, CAL_ID, EVT_ID, and FEED_TOKEN are placeholders — replace them with your real values.
All error responses return a JSON object with a single error field:
{ "error": "Human-readable message" }
error message for detailsRateLimit-ResetGET /errors for detailsRateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset (RFC draft-7). Monitor these to avoid 429 responses.Responses include RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers (RFC draft-7). When exceeded, you receive a 429 response.
X-Human-Key header on POST /agents or POST /agents/claim for programmatic access.
Claim an existing agent by providing its API key. The agent is immediately associated with your human account.
hk_live_...)sk_live_...)curl -s -X POST "https://caldave.ai/agents/claim" \
-H "Content-Type: application/json" \
-H "X-Human-Key: hk_live_YOUR_HUMAN_KEY" \
-d '{"api_key": "sk_live_AGENT_KEY_TO_CLAIM"}'
Create a new agent identity. Returns credentials you must save — the API key is shown once. Include name and description to identify your agent — the name appears in outbound email From headers.
hk_live_...). When provided, the new agent is automatically associated with your human account.curl -s -X POST "https://caldave.ai/agents" \
-H "Content-Type: application/json" \
-d '{"name": "Meeting Scheduler", "description": "Books rooms and sends reminders"}'
curl -s -X POST "https://caldave.ai/agents" \
-H "Content-Type: application/json" \
-H "X-Human-Key: hk_live_YOUR_HUMAN_KEY" \
-d '{"name": "Meeting Scheduler"}'
{
"agent_id": "agt_x7y8z9AbCd",
"api_key": "sk_live_abc123...",
"name": "Meeting Scheduler",
"description": "Books rooms and sends reminders",
"owned_by": "hum_abc123...",
"message": "Store these credentials securely. The API key will not be shown again."
}
owned_by field only appears when X-Human-Key is provided. Without it, the agent is created unclaimed.Get the authenticated agent's profile.
curl -s "https://caldave.ai/agents/me" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"agent_id": "agt_x7y8z9AbCd",
"name": "Meeting Scheduler",
"description": "Books rooms and sends reminders",
"created_at": "2026-02-14T10:30:00.000Z"
}
Update agent metadata. Does not change the API key. Set a field to null to clear it.
curl -s -X PATCH "https://caldave.ai/agents" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"name": "Updated Name"}'
{
"agent_id": "agt_x7y8z9AbCd",
"name": "Updated Name",
"description": "Books rooms and sends reminders",
"created_at": "2026-02-14T10:30:00.000Z"
}
Configure an SMTP server for outbound emails. When set, all invite and RSVP emails for this agent are sent via your SMTP server instead of CalDave's built-in delivery. This lets invites come from your own email address.
true) or STARTTLS (false). Defaults to true for port 465, false otherwise.curl -s -X PUT "https://caldave.ai/agents/smtp" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"host": "smtp.agentmail.to", "port": 465, "username": "inbox@agentmail.to", "password": "YOUR_SMTP_PASSWORD", "from": "inbox@agentmail.to"}'
{
"smtp": {
"host": "smtp.agentmail.to",
"port": 465,
"username": "inbox@agentmail.to",
"from": "inbox@agentmail.to",
"secure": true,
"configured": true
}
}
from address replaces the calendar email as the From address on all outbound emails. If your agent has a name, it appears as the display name (e.g. "My Agent" <inbox@agentmail.to>).View the current SMTP configuration (password excluded).
curl -s "https://caldave.ai/agents/smtp" \
-H "Authorization: Bearer YOUR_API_KEY"
Remove the SMTP configuration. Outbound emails revert to CalDave's built-in delivery.
curl -s -X DELETE "https://caldave.ai/agents/smtp" \
-H "Authorization: Bearer YOUR_API_KEY"
Send a test email to verify your SMTP configuration works. Defaults to the configured from address; override with to.
from address.curl -s -X POST "https://caldave.ai/agents/smtp/test" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"to": "test@example.com"}'
{
"success": true,
"message_id": "<abc123@smtp.agentmail.to>",
"from": "inbox@agentmail.to",
"to": "test@example.com",
"message": "Test email sent successfully to test@example.com."
}
Create a new calendar for the authenticated agent.
X-CalDave-Signature header)false to skip the auto-created welcome event (recommended for production agents). Defaults to true.curl -s -X POST "https://caldave.ai/calendars" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"name": "Work Schedule", "timezone": "America/Denver"}'
{
"calendar_id": "cal_a1b2c3XyZ",
"name": "Work Schedule",
"timezone": "America/Denver",
"email": "cal-a1b2c3XyZ@invite.caldave.ai",
"ical_feed_url": "https://caldave.ai/feeds/cal_a1b2c3XyZ.ics?token=feed_...",
"feed_token": "feed_...",
"inbound_webhook_url": "https://caldave.ai/inbound/inb_...",
"message": "This calendar can receive invites at cal-a1b2c3XyZ@invite.caldave.ai. ..."
}
List all calendars for the authenticated agent.
curl -s "https://caldave.ai/calendars" \
-H "Authorization: Bearer YOUR_API_KEY"
Get a single calendar by ID.
curl -s "https://caldave.ai/calendars/CAL_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Update calendar settings. All fields are optional.
curl -s -X PATCH "https://caldave.ai/calendars/CAL_ID" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"name": "Updated Name", "timezone": "America/New_York"}'
Delete a calendar and all its events. Returns 204 on success.
curl -s -X DELETE "https://caldave.ai/calendars/CAL_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Send a test payload to the calendar's configured webhook URL. Returns the HTTP status code from the webhook endpoint. Useful for verifying webhook configuration before real events fire.
curl -s -X POST "https://caldave.ai/calendars/CAL_ID/webhook/test" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"success": true,
"status_code": 200,
"webhook_url": "https://example.com/webhook",
"message": "Webhook delivered successfully."
}
type: "test" so your webhook handler can distinguish test pings from real events. If webhook_secret is set, the payload is signed with HMAC-SHA256 via the X-CalDave-Signature header.webhook_url on a calendar via POST /calendars or PATCH /calendars/:id. Optionally set webhook_secret for HMAC-SHA256 signature verification. Use POST /calendars/:id/webhook/test to verify your endpoint is reachable.
When webhook_secret is set on a calendar, CalDave signs every webhook payload with HMAC-SHA256. The hex digest is sent in the X-CalDave-Signature header. Verify it on your server to confirm the request came from CalDave and wasn't tampered with.
| 1. | CalDave computes HMAC-SHA256(webhook_secret, raw_request_body) |
| 2. | The hex digest is sent in X-CalDave-Signature |
| 3. | Your server recomputes the HMAC over the raw body and compares |
const crypto = require('crypto');
// Use the raw body string, NOT parsed JSON
const signature = req.headers['x-caldave-signature'];
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(rawBody)
.digest('hex');
const valid = crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
if (!valid) {
return res.status(401).json({ error: 'Invalid signature' });
}
import hmac, hashlib
signature = request.headers.get('X-CalDave-Signature')
expected = hmac.new(
WEBHOOK_SECRET.encode(),
request.data, # raw bytes
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
abort(401)
timingSafeEqual / compare_digest) to prevent timing attacks. If no webhook_secret is set, the header is omitted and payloads are unsigned.When a calendar has a webhook_url configured, CalDave automatically delivers webhooks whenever events are created, updated, deleted, or responded to — whether via the API or inbound email. Time-based webhooks (event.starting and event.ending) fire automatically when an event's start or end time arrives, polled every 60 seconds.
{
"type": "event.created",
"calendar_id": "cal_...",
"event_id": "evt_...",
"event": { ... },
"timestamp": "2026-02-17T12:00:00.000Z"
}
POST /calendars/:id/webhook/test to verify your endpoint is reachable before relying on live events.Create an event on a calendar. Supports one-off and recurring events.
rrulecurl -s -X POST "https://caldave.ai/calendars/CAL_ID/events" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"title": "Team standup",
"start": "2025-03-01T09:00:00-07:00",
"end": "2025-03-01T09:15:00-07:00",
"location": "https://meet.google.com/abc-defg-hij"
}'
curl -s -X POST "https://caldave.ai/calendars/CAL_ID/events" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"title": "Daily weather email",
"start": "2025-03-01T08:00:00-07:00",
"end": "2025-03-01T08:05:00-07:00",
"metadata": {"action": "send_email", "prompt": "Send weather forecast"},
"recurrence": "FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR"
}'
curl -s -X POST "https://caldave.ai/calendars/CAL_ID/events" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"title": "Company Holiday",
"start": "2025-12-25",
"end": "2025-12-25",
"all_day": true
}'
instances_created count.List events with optional filters. Returns expanded recurring event instances.
curl -s "https://caldave.ai/calendars/CAL_ID/events?start=2025-03-01T00:00:00Z&limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"
Get a single event by ID.
curl -s "https://caldave.ai/calendars/CAL_ID/events/EVT_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Update an event. For recurring events: patching an instance marks it as an exception; patching the parent propagates to all non-exception instances.
rrulecurl -s -X PATCH "https://caldave.ai/calendars/CAL_ID/events/EVT_ID" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"title": "Updated title", "location": "Room 42"}'
Delete an event. For recurring event instances, use the mode query parameter.
single — cancel this instance only (default)future — cancel this and all future instancesall — delete entire seriescurl -s -X DELETE "https://caldave.ai/calendars/CAL_ID/events/EVT_ID?mode=single" \
-H "Authorization: Bearer YOUR_API_KEY"
Get the next N events starting from now. Designed for agent polling.
curl -s "https://caldave.ai/calendars/CAL_ID/upcoming" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"events": [...],
"next_event_starts_in": "PT14M30S"
}
next_event_starts_in is an ISO 8601 duration showing how long until the next event. Useful for setting poll intervals.Plain text table of upcoming events. Useful for quick inspection via curl or agent debugging.
curl -s "https://caldave.ai/calendars/CAL_ID/view" \
-H "Authorization: Bearer YOUR_API_KEY"
Work (cal_xxx) tz: America/Denver
-----------------------------------------
TITLE START ...
-----------------------------------------
Daily standup 2026-02-13 16:00:00Z ...
-----------------------------------------
1 event(s)
Accept or decline an inbound calendar invite.
curl -s -X POST "https://caldave.ai/calendars/CAL_ID/events/EVT_ID/respond" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"response": "accepted"}'
Read-only iCalendar feed. Subscribe to this URL from Google Calendar, Apple Calendar, or any iCal-compatible app. The feed_token is returned when you create a calendar.
curl -s "https://caldave.ai/feeds/CAL_ID.ics?token=FEED_TOKEN"
Receives forwarded emails containing .ics calendar invite attachments and creates events from them. Each calendar has a unique inbound URL (returned at creation as inbound_webhook_url). Supports Postmark and AgentMail providers.
agentmail_api_key.
{ "status": "created", "event_id": "evt_..." }
{ "status": "updated", "event_id": "evt_..." }
{ "status": "cancelled", "event_id": "evt_..." }
{ "status": "ignored", "reason": "..." }
List recent API errors scoped to your agent. Useful for debugging failed requests.
curl -s "https://caldave.ai/errors" \
-H "Authorization: Bearer YOUR_API_KEY"
Get a single error with full stack trace.
curl -s "https://caldave.ai/errors/42" \
-H "Authorization: Bearer YOUR_API_KEY"
Structured list of API changes with dates and docs links. With a Bearer token, highlights changes since your agent was created and includes personalized recommendations. Poll ~weekly to discover new features.
curl -s "https://caldave.ai/changelog" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"description": "CalDave API changelog...",
"your_agent": { "agent_id": "agt_...", "created_at": "..." },
"changes_since_signup": [{ "date": "2026-02-14", "changes": [...] }],
"changes_since_signup_count": 2,
"changelog": [{ "date": "2026-02-08", "changes": [...] }],
"recommendations": [
{ "action": "Name your agent", "why": "...", "how": "PATCH /agents ...", "docs": "..." }
]
}
recommendations array includes actionable suggestions based on your agent state (e.g. name your agent, create a calendar, create an event). Only present when authenticated and there are suggestions.Machine-readable API manual. Returns all endpoints with curl examples and parameters. With Bearer auth, includes your real calendar IDs and a recommended next step. Use ?guide for a compact onboarding overview.
?guide)agents, smtp, calendars, events, feeds, errorscurl -s "https://caldave.ai/man" \
-H "Authorization: Bearer YOUR_API_KEY"
curl -s "https://caldave.ai/man?guide" \
-H "Authorization: Bearer YOUR_API_KEY"
curl -s "https://caldave.ai/man?topic=events" \
-H "Authorization: Bearer YOUR_API_KEY"
curl -s "https://caldave.ai/man?topic=agents,smtp" \
-H "Authorization: Bearer YOUR_API_KEY"
?guide mode returns only an overview, your context, a recommended next step, and links to discover more. Ideal for first-time agent onboarding.?topic= filter is useful when you only need docs for a specific area. For example, ?topic=events returns only event endpoints plus discovery. Combine topics with commas: ?topic=agents,smtp.Get up and running in three steps:
curl -s -X POST "https://caldave.ai/agents" \
-H "Content-Type: application/json" \
-d '{"name": "My Agent", "description": "What this agent does"}'
Save the agent_id and api_key from the response. The name appears in outbound emails.
curl -s -X POST "https://caldave.ai/calendars" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"name": "My Calendar", "timezone": "America/Denver"}'
Save the calendar_id, email, and feed URLs from the response.
curl -s -X POST "https://caldave.ai/calendars/CAL_ID/events" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"title": "My first event",
"start": "2025-03-01T10:00:00-07:00",
"end": "2025-03-01T11:00:00-07:00"
}'