Skip to content
CalendarSync
IntegrationsPricingBlogAPI DocsFeatures
Sign InGet Started
Pro plan

CalendarSync API

A developer-friendly REST API to read your meetings, schedule events, check and trigger syncs, and pull AI-generated notes. Same data your dashboard sees, accessible to your scripts, automations, and AI agents.

Get an API keyConnect to Claude (MCP) →Embed booking widget →

Authentication

Send your key as a Bearer token. Generate one in settings.

Authorization:
Bearer cs_live_…

Base URL

https://www.calendarsync.app

JSON in, JSON out. Routes live under /api/v1/….

Rate limits

100 requests / minute per account. Watch X-RateLimit-Remaining in response headers. On a 429, wait the seconds in Retry-After, then retry.

Quick start

From API key to working response in 3 curl commands.

1. Sanity check

curl https://www.calendarsync.app/api/v1/status \
  -H "Authorization: Bearer cs_live_your_key"

2. List today's meetings

curl "https://www.calendarsync.app/api/v1/meetings?day=today" \
  -H "Authorization: Bearer cs_live_your_key"

3. Schedule something

curl -X POST https://www.calendarsync.app/api/v1/events \
  -H "Authorization: Bearer cs_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Quick sync",
    "start": "2026-04-26T07:00:00Z",
    "end": "2026-04-26T07:30:00Z",
    "attendees": [{"email": "friend@x.com"}]
  }'

Reference

AccountCalendarsSync pairsMeetingsCalendar eventsMeeting notesError codesInvited connections

Endpoints

Account

Quick health check on the account that owns the API key.

GET/api/v1/status

Account-wide sync health. Connection count, active/erroring sync pairs, recent errors.

Response

{
  "status": "healthy",
  "connections": 3,
  "sync_pairs": { "total": 3, "active": 3, "errors": 0 },
  "recent_errors_24h": 0,
  "timestamp": "2026-04-25T12:30:00.000Z"
}

Calendars

List the connected calendar accounts (Google, Microsoft, Apple).

GET/api/v1/connections

Returns every calendar connection with its provider, email, status, and the last time one of its sync pairs ran. Use the id when scheduling events.

Response

{
  "data": [
    {
      "id": "abd156d6-...",
      "provider": "google",
      "email": "you@gmail.com",
      "calendar_id": "primary",
      "calendar_name": "you@gmail.com",
      "status": "active",
      "last_synced_at": "2026-04-25T12:30:00Z",
      "created_at": "2026-04-11T10:00:00Z"
    }
  ],
  "count": 1
}

Sync pairs

Inspect, trigger, and audit the calendar-to-calendar sync pairs you set up in the dashboard.

GET/api/v1/sync-pairs

List every sync pair with mode, direction, status, and the underlying connections on each side.

Response

{
  "data": [
    {
      "id": "de1168f5-...",
      "sync_mode": "mirror",
      "direction": "two_way",
      "is_active": true,
      "status": "idle",
      "last_synced_at": "2026-04-25T12:30:00Z",
      "connection_a": { "id": "...", "provider": "google", "email": "a@x.com" },
      "connection_b": { "id": "...", "provider": "google", "email": "b@y.com" }
    }
  ],
  "count": 1
}
POST/api/v1/sync-pairs/{id}/trigger

Run a sync for one pair right now. Useful when an instant-sync webhook was missed or you want to verify a specific change propagated. One manual run per pair per minute (429 with Retry-After), and 409 if the pair is already syncing.

Response

{
  "success": true,
  "data": {
    "events_created": 1,
    "events_updated": 0,
    "events_deleted": 0,
    "duration_ms": 4200,
    "trigger_type": "manual"
  }
}
GET/api/v1/sync-pairs/{id}/logs

Recent sync events for one pair. Supports ?limit (default 20, max 100) and ?offset.

Query params

  • limitMax rows (1-100). Default 20.
  • offsetSkip N rows. Default 0.

Response

{
  "data": [
    {
      "id": "log-...",
      "trigger_type": "webhook",
      "level": "info",
      "events_created": 1,
      "duration_ms": 843,
      "created_at": "2026-04-25T12:30:00Z"
    }
  ],
  "count": 1,
  "limit": 20,
  "offset": 0
}

Meetings

List, read, update, and log meetings. Mirrors what you see on the dashboard's Meetings page.

GET/api/v1/meetings

List meetings with flexible filters. Each row includes attendees, event time, status, AI-generated summary, and structured action items when matched. Add compact=1 to leave the summary and action items out.

Query params

  • dayShortcut: today | tomorrow | yesterday (in your stored timezone). Overrides from/to.
  • fromISO timestamp lower bound (inclusive).
  • toISO timestamp upper bound (exclusive).
  • statusComma-separated list of statuses to include. Default: today,active. Possible: today, active, done, notes.
  • qSearch meeting titles (partial match) or an attendee's exact email address.
  • limitMax rows (1-200). Default 50.
  • compactSet to 1 to leave out meeting_summary and action_items. GET /api/v1/meetings/{id} still returns them.

Response

{
  "meetings": [
    {
      "id": "mtg-...",
      "title": "Kickoff with Sam",
      "status": "today",
      "event_date": "2026-04-26T09:00:00Z",
      "is_all_day": false,
      "attendees": [
        { "name": "Sam Lee", "email": "sam@example.com" }
      ],
      "meeting_summary": null,
      "action_items": [],
      "matched_transcript_id": null,
      "is_dismissed": false
    }
  ],
  "count": 1,
  "timezone": "Asia/Singapore",
  "window": { "from": "...", "to": "..." }
}
GET/api/v1/meetings/{id}

Full meeting record with notetaker-generated narrative and structured action items.

Response

{
  "meeting": {
    "id": "mtg-...",
    "title": "Kickoff with Sam",
    "event_date": "2026-04-26T09:00:00Z",
    "meeting_summary": "Discussed scope, timelines, and onboarding...",
    "action_items": [
      {
        "text": "Send the proposal by Friday",
        "done": false,
        "owner": "Ryan Tan",
        "timestamp": "12:34"
      }
    ]
  }
}
PATCH/api/v1/meetings/{id}

Update one or more fields on a meeting. Use to mark a meeting done, dismiss, replace notes, or rewrite the action item list. Notes up to 20,000 characters; up to 100 action items of up to 1,000 characters each.

Request body

{
  "status": "done",
  "is_dismissed": false,
  "meeting_summary": "Updated remarks here.",
  "action_items": [
    { "text": "Email the deck", "done": false }
  ]
}

Response

{
  "meeting": {
    "id": "mtg-...",
    "status": "done",
    "is_dismissed": false,
    "updated_at": "2026-04-25T13:00:00Z"
  }
}
POST/api/v1/meetings

Log an ad-hoc or retrospective meeting (no calendar event behind it). Same as the dashboard's Log Meeting button. Title up to 500 characters, notes up to 20,000, up to 50 attendees.

Request body

{
  "title": "Quick chat with Sam",
  "event_date": "2026-04-25T08:30:00Z",
  "is_all_day": false,
  "attendees": [
    { "name": "Sam Lee", "email": "sam@example.com" }
  ],
  "notes": "Aligned on next steps.",
  "status": "active"
}

Response

{
  "meeting": {
    "id": "mtg-...",
    "title": "Quick chat with Sam",
    "status": "active",
    "event_date": "2026-04-25T08:30:00Z",
    "meeting_summary": "Aligned on next steps.",
    "created_at": "2026-04-25T13:00:00Z"
  }
}

Calendar events

Schedule new events on a connected calendar. The dashboard's calendar provider (Google / Microsoft / Apple) handles the write.

POST/api/v1/events

Create a calendar event. Pick which calendar via connection_id (omit it if you have only one active calendar of your own). Calendars other people connected through an invite can't be written to. Up to 10 events a minute and 200 a day per account; title up to 500 characters, description up to 8,000, up to 50 attendees.

Request body

{
  "connection_id": "abd156d6-...",
  "title": "Catch-up with Sam",
  "start": "2026-04-26T07:00:00Z",
  "end": "2026-04-26T07:30:00Z",
  "description": "30-min check-in.",
  "location": "Google Meet",
  "attendees": [
    { "email": "sam@example.com", "displayName": "Sam Lee" }
  ],
  "all_day": false
}

Response

{
  "event": {
    "id": "google-evt-id",
    "summary": "Catch-up with Sam",
    "start": { "dateTime": "2026-04-26T07:00:00Z" },
    "end": { "dateTime": "2026-04-26T07:30:00Z" },
    "html_link": "https://calendar.google.com/...",
    "attendees": [{ "email": "sam@example.com" }]
  },
  "connection": {
    "id": "abd156d6-...",
    "email": "you@gmail.com",
    "provider": "google"
  }
}

Meeting notes

Run a Fireflies pull now. Useful right after a call to attach the transcript without waiting for the 15-min cron.

POST/api/v1/pull-notes

Pull recent notetaker transcripts and match them to your meetings that have no notes yet. Returns which tasks got matched. One pull every 2 minutes per account.

Request body

{
  "window_days": 7
}

Response

{
  "matched": 1,
  "total_tasks": 8,
  "total_transcripts": 3,
  "matches": [
    {
      "taskId": "mtg-...",
      "taskTitle": "Kickoff with Sam",
      "transcriptTitle": "Kickoff with Sam"
    }
  ],
  "skipped_reason": null
}

Error codes

StatusMeaning
400Malformed request body, a missing required field, a field over its length limit, or a request the resource can't take (for example, triggering an inactive pair)
401Missing or invalid API key
403Key valid but the account is not on Pro or in its trial
404Not found, including anything that belongs to another account
409The sync pair is already syncing. Try again once it finishes.
413Request body over 64 KB
429Rate limited, or an endpoint's own limit reached. Wait the seconds in Retry-After, then retry.
500Server error. Retry with backoff.
503Temporarily unavailable. Wait the seconds in Retry-After, then retry.

Invited connections

Accounts on a paid Pro plan can invite other people to connect their own calendar. Managed from the dashboard, not the API.

How it works

From Dashboard → Calendars, click “Invite someone”. We email them a single-use link that expires in 7 days, and you can copy it too. The invitee opens the link and connects Google or Outlook. Their calendar then appears in your connection list with an “Invited” badge. It can be the source of one-way sync pairs, and booking links can check it for conflicts, including a “Book Sam” link for that person. CalendarSync never syncs events into it, and a booking from their own link is written to it only if they turn that on from their manage link.

What the invitee sees

Who is asking (your name and email), a note that you will see their busy times only, and one Connect button per provider. No CalendarSync account is created for them. After connecting they receive an email with a private manage link where they can disconnect, or choose whether bookings made for them land on their calendar. Lost the link? The original invite page can resend it to the email on file.

Privacy

Invited calendars share busy times only: no event names, descriptions, locations or guests reach you, and nothing on your side can widen that. Either side can disconnect at any time; the other side is notified by email.

Billing

SGD 2 per invited connection per month by default. If your own Pro plan is monthly, it is added as a quantity line to that subscription. If your Pro plan is annual, it runs as a separate monthly subscription on the same card by default, so you are not charged a year up front for someone who may only be connected for a few weeks. If you prefer one renewal, the Seat billing control on the Billing page switches annual-plan seats to SGD 24 per person per year on the same invoice as your Pro plan; the remainder of your current plan year is charged straight away, prorated, and nothing is refunded mid-cycle. Annual seats are paid for the year: if someone disconnects, their seat stays available for the next person you invite at no extra charge until your renewal, when you are charged only for the seats in use. Switching back to monthly credits the unused part of the year to your plan renewal. Charged only when the invitee actually connects, prorated for the current period; a monthly seat is removed when they disconnect. Calendars you connect yourself are not counted.

Next: connect this to Claude

The CalendarSync MCP server turns every endpoint above except the sync logs into a tool your AI assistant can call directly. Ask it about your schedule, get notes, log meetings, and book events with plain English.

MCP setup guide →
CalendarSync

Keep all your calendars in sync. Share scheduling links. Never get double-booked again.

Product

  • Integrations
  • Pricing
  • Features

Resources

  • API Reference
  • Connect Apple Calendar
  • Blog
  • Partner Program
  • Compare Alternatives
  • Sign In

Legal

  • Privacy Policy
  • Terms of Service

© 2026 CalendarSync. All rights reserved.

Fazier badge

Built for people who live in their calendars.