# Compare providers (https://www.cal-sdk.com/docs/providers)

Calendar APIs agree on less than you'd hope. Google can split a recurring series in two, Outlook can't, and Cal.com names every booking after its event type no matter what title you send. Every provider declares what it supports in `calendar.capabilities`, and most of this table comes straight from that data. A dash means no, and "Some" means it depends on a condition, explained below the table.

| Feature            | Google | Outlook | CalDAV | Cal.com | Calendly | Zoom | ICS  | Mock |
| ------------------ | :----: | :-----: | :----: | :-----: | :------: | :--: | :--: | :--: |
| Write events       | Yes    | Yes     | Yes    | Some    | Some     | Yes  | -    | Yes  |
| Keeps title        | Yes    | Yes     | Yes    | -       | -        | Yes  | -    | Yes  |
| All-day            | Yes    | Yes     | Yes    | -       | -        | -    | Some | Yes  |
| Recurring          | Yes    | Yes     | Yes    | -       | -        | Some | Some | Yes  |
| This and following | Yes    | -       | -      | -       | -        | -    | -    | Yes  |
| Attendees          | Yes    | Yes     | Yes    | Yes     | Yes      | Yes  | Some | Yes  |
| Video links        | Yes    | Some    | -      | -       | -        | Yes  | -    | Yes  |
| Reminders          | Yes    | Some    | -      | -       | -        | -    | -    | Yes  |
| Colors             | Yes    | -       | -      | -       | -        | -    | -    | Yes  |
| `ifMatch`          | Yes    | Yes     | Yes    | -       | -        | -    | -    | Yes  |
| Search             | Yes    | -       | -      | -       | -        | -    | -    | Yes  |
| Free/busy API      | Yes    | -       | -      | -       | -        | -    | -    | -    |
| Sync               | Yes    | Yes     | Yes    | Yes     | Yes      | Yes  | Yes  | Yes  |

## Conditions [#conditions]

Where the table says Some:

- Outlook adds Teams links only on work or school accounts.
- Outlook keeps one popup reminder per event.
- Cal.com books, moves (as a new booking with a new id) and cancels.
- Calendly books and cancels; `updateEvent` throws.
- Zoom repeats daily, weekly on set weekdays, or monthly on a day or an nth weekday, for up to 60 meetings or until a date. One meeting of a series can only be moved, resized or deleted.
- ICS feeds are read only: all-day, recurring and attendee data is read but can't be written.

"Keeps title" matters for the scheduling tools. Cal.com and Calendly name bookings after their event type, so a title you pass is ignored with a warning rather than saved.

Free/busy works on every provider. Where there's no endpoint, calsdk computes it from events and returns a warning, so `findFreeTime` behaves the same everywhere. Search is different: providers without it throw `UnsupportedFunctionalityError`, and you filter the listed events yourself.

Webhooks are part of the provider contract, but no provider implements them yet. Until they do, run [sync](/docs/guides/sync) on a schedule.

## Check at runtime [#check-at-runtime]

```ts
const { events } = calendar.capabilities;

if (events.recurrenceScopeThisAndFollowing === true) {
  await updateEvent({ calendar, eventId, scope: 'thisAndFollowing', patch });
}
```

Values are `true`, `false`, `'unknown'` or `{ condition: string }`. Treat anything but `true` as "check first": a condition means it works for some accounts or some inputs, not all of them. See [Capabilities](/docs/reference/capabilities).
