> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meetingkit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect calendars

> A call to action where users start in your product. One click takes them through Google or Microsoft consent, and they come back as a member with their calendar syncing.

The first screen is a call to action where your users start: an onboarding step or the
dashboard. The user picks Google or Microsoft, approves access, and lands back in your
product with their calendar connected. You don't create users beforehand: the member is
created when they consent.

<Frame>
  <img src="https://mintcdn.com/meeting-kit/DnaA9m78FJYvG19R/images/diagrams/connect-cta.svg?fit=max&auto=format&n=DnaA9m78FJYvG19R&q=85&s=5319a29171aaa3a855442e89f4ba15f4" alt="A dashboard card, Get your meetings recorded, with Connect Google Calendar and Connect Outlook buttons. Notes: Connect is POST /calendar_connect_links with member_data and return_url; back from consent, the return_url carries member_id." width="680" height="503" data-path="images/diagrams/connect-cta.svg" />
</Frame>

## When the user clicks Connect

Your backend creates a connect link and redirects the browser to its `url`:

```bash theme={null}
curl -X POST "https://api.meetingkit.com/api/v1/calendar_connect_links" \
  -H "Authorization: $MEETINGKIT_API_KEY" \
  -H "Happyscribe-Version: 2026-10-12" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace_id": "wks_01k6a2r9s8x7c2dvq3m5n6p4ab",
    "provider": "google",
    "return_url": "https://app.example.com/setup/calendar",
    "client_reference_id": "user_4821",
    "member_data": {
      "name": "Ana García",
      "email": "ana@acme.com",
      "metadata": { "user_id": "user_4821" }
    }
  }'
```

```json theme={null}
{
  "id": "ccl_01k6c0r9s8x7c2dvq3m5n6p4ab",
  "object": "calendar_connect_link",
  "url": "https://api.meetingkit.com/connect/calendar/ccl_01k6c0r9s8x7c2dvq3m5n6p4ab?token=…",
  "expires_at": "2026-09-30T10:10:00Z",
  "status": "open",
  "…": "…"
}
```

| Field | Meaning |
| - | - |
| `provider` | `google` or `microsoft`. |
| `return_url` | The `https` page in your product the user comes back to. |
| `client_reference_id` | Your own reference, up to 255 characters, returned on the way back. |
| `member_data` | Who this is: `name`, `email` and your `metadata`. Used to create the member when the user consents. |

`member_data.email` only pre-fills the Google or Microsoft account chooser; it is never
checked. The member's email is the account the user approves (for Microsoft, the user
principal name). Without `member_data`, the member is created from the account alone, with
no name or metadata. A link lives 24 hours;
creating it again with the same values while it is open returns the same link, so you can
create it when the page renders.

## When the user comes back

After consent, the browser returns to your `return_url`:

```
https://app.example.com/setup/calendar?calendar_connect_link_id=ccl_01k6c0…&status=connected&calendar_connection_id=cal_01k6c1…&member_id=mem_01k69x…&client_reference_id=user_4821
```

Store the `member_id` next to your user: every other call takes it. The
`calendar_connection.connected` webhook carries the same connection, with `member_id` and
the `account_email` they connected. Treat the query string as a hint to update the page,
and the webhook (or `GET /calendar_connections/{id}`) as the confirmation.

Within minutes the user's upcoming meetings appear in their [meetings list](/meetingkit/meetings),
and `meeting.created` fires for each.

If the account already belongs to a member of the workspace, the connection lands on that
member: their name stays and your `metadata` is merged in. A member created this way is
never one of the workspace's owners or admins, and never hears from MeetingKit: no emails,
no sign-in.

## When it fails

`status=error` comes back with an `error`:

| `error` | What happened |
| - | - |
| `access_denied` | The user declined consent. The link stays open and works again. |
| `calendar_already_connected` | This member already has a connected calendar. |
| `account_in_use` | That calendar account is connected by someone else in the workspace. |
| `link_expired`, `link_used` | Create a new link. |
| `not_authorized` | The key that created the link can no longer manage the workspace, or the account belongs to one of its owners or admins. |
| `connect_failed` | Something unexpected, or `member_data.metadata` would take an existing member past 50 keys. Create a new link and try again. |

Creating the link can fail with `409 calendar_already_connected`, or `422` for an invalid
`provider`, `return_url` (an absolute `https` URL), `member_data` or `client_reference_id`.

Reconnecting a user who already has a member is part of [meeting settings](/meetingkit/meeting-settings#reconnect).
