# Choose a provider (https://www.cal-sdk.com/docs/choose-a-provider)

You rarely get to choose your users' calendar. One team lives in Google Workspace, the next in Microsoft 365, and someone always books through Calendly. So most apps end up with one provider per calendar their users connect. Providers are plain objects, so your app can hold a Google provider for Priya and an Outlook provider for Tom, and pass whichever applies to the same functions.

## Full calendars [#full-calendars]

Use these when your users keep their schedule in the calendar itself. You can read and write any event, invite attendees and create repeating series.

| Calendar                          | Use                                                     | Credentials                                               |
| --------------------------------- | ------------------------------------------------------- | --------------------------------------------------------- |
| Google Calendar                   | [`google()`](/docs/providers/google)                    | OAuth access token with a Calendar scope                  |
| Outlook, Microsoft 365            | [`microsoft()`](/docs/providers/microsoft)              | Microsoft Graph token with `Calendars.ReadWrite`          |
| iCloud                            | [`icloud()`](/docs/providers/caldav)                    | Apple ID and an app-specific password                     |
| Zoho Calendar                     | [`zoho()`](/docs/providers/caldav)                      | Email and password, or an app-specific password           |
| Other CalDAV servers              | [`caldav()`](/docs/providers/caldav)                    | Server address, username and password                     |

Fastmail, Nextcloud and Radicale are CalDAV servers, so they use `caldav()`.

## Scheduling tools [#scheduling-tools]

Use these when your app reads and makes bookings or meetings rather than managing someone's whole calendar. Cal.com and Calendly book an event type, and the event type sets the booking's name and length, not you. Zoom meetings keep the title and length you give them.

| Tool     | Use                                      | Credentials                                       |
| -------- | ---------------------------------------- | ------------------------------------------------- |
| Cal.com  | [`calcom()`](/docs/providers/calcom)     | API key or OAuth access token                     |
| Calendly | [`calendly()`](/docs/providers/calendly) | Personal access token or OAuth access token       |
| Zoom     | [`zoom()`](/docs/providers/zoom)         | OAuth access token with meeting scopes            |

## Feeds and tests [#feeds-and-tests]

| Source                                  | Use                                  | Credentials                     |
| --------------------------------------- | ------------------------------------ | ------------------------------- |
| A `.ics` or `webcal://` feed            | [`ics()`](/docs/providers/ics)       | None, or headers for a private feed |
| An in-memory calendar                   | [`mockCalendar()`](/docs/providers/mock) | None                        |

## Check before you rely on a feature [#check-before-you-rely-on-a-feature]

The same function doesn't mean the same features. Outlook can't change "this and following" occurrences, Zoom has no all-day meetings, and an ICS feed is read only. Each provider lists what it supports in `capabilities`, so you can check before you show a feature to a user:

```ts
if (calendar.capabilities.events.search === true) {
  await listEvents({ calendar, timeMin, timeMax, query: 'standup' });
}
```

A capability is `true`, `false`, `'unknown'`, or `{ condition }` when it depends on something, such as Teams meetings needing a work or school account. The [comparison table](/docs/providers) shows them all side by side.

If you ask for something a provider can't do anyway, calsdk picks one of two outcomes. When the rest of the event is still right, the call succeeds with a [warning](/docs/concepts/warnings): an Outlook event can't have a color, so the color is dropped. When going ahead would save something you didn't ask for, such as a rule Outlook can't repeat, it throws `UnsupportedFunctionalityError`. Each provider page lists which is which.
