**Connection types** is where you decide which kinds of source your customers are allowed to connect. It is a screen inside Context Link, at **`/white_label/connection_activations`**, listed in the left rail. Before your product can connect a customer's mailbox or their Drive, that source type has to be turned on here.

This is the one screen in the guide that is not read-only, and it is the only place the fleet's source types are set. Everything after it happens over the API, inside your product: [creating connections](/docs/white-label/connect-source), [checking them](/docs/white-label/connection-status) and [removing them](/docs/white-label/disconnect-source).

<figure style="margin: 1rem 0;">
<img src="/docs/white-label/white-label-connection-activations.png" alt="The Connection types screen. An always-on Website row with a count of 4 customers and no controls. Below it three active sources, each with a customer count and a Withdraw button: Email connecting directly, Google Drive on the partner's own OAuth app, and Notion warning in orange that it is falling back to Context Link's app. Under those, an available-to-turn-on list starting with OneDrive's client ID and client secret fields." style="max-width: 100%; border-radius: 8px;">
</figure>

It is visible to **organisation admins on the white-label plan**. It is deliberately not the same thing as your own team's connections screen. What you set here is what your *customers* may connect, never what your organisation indexes for itself.

## What the screen shows

Three groups, in one list.

| Group | What it is |
|---|---|
| **Always on** | Website. Every customer has it, you do not turn it on, and you cannot withdraw it. |
| **Active sources** | Types you have turned on, with whose OAuth app is on the consent screen, how many of your customers hold one, and the keys. |
| **Available to turn on** | Everything else you could offer, each with its credential form where it needs one. |

The number against each row counts **customers holding that type**, not connections. One customer with three YouTube channels counts once. Per-customer detail lives on the [fleet screen](/docs/white-label/in-app-screens), not here.

### Website is always on

Website sits in its own group with a count and no controls. Every customer may hold a website connection whether or not you ever open this screen, so there is nothing here to turn on. Most are created from the `site_url` you pass when you [provision the account](/docs/white-label/create-account). You can also connect one later with [`PUT .../connections/:connection_uid`](/docs/white-label/connect-source) and `connection_type: "site"`. Either route gives that customer one website, and only one.

Withdrawing the type is what the screen refuses, because it would purge the core of every customer's index. The route refuses it as well, so there is no way to reach it by hand.

Memory and [custom connections](/docs/white-label/create-connection) are not on the screen at all. They are infrastructure every account gets rather than choices you make.

**Files is deliberately not offerable.** It is a browser upload with no API surface your customer could push into, and custom connections already cover you pushing content in on their behalf.

## The types you can turn on

| Source | Needs your OAuth app | What your customer supplies |
|---|---|---|
| Email | No | Address, IMAP password, server, optional port |
| Notion | **Yes** | Consent at Notion |
| Google Drive | **Yes** | Consent at Google |
| OneDrive | **Yes** | Consent at Microsoft |
| Basecamp | **Yes** | Consent at Basecamp |
| monday.com | No | An API token they paste, optional workspace id |
| YouTube | No | A channel handle |
| Web Mentions | No | Brand name and web domain |

**monday.com is a pasted token, not OAuth.** Monday's tokens are long-lived with no refresh, so there is no app to register and no consent screen. Your customer copies a token out of monday.com and you post it like any other setup field.

The exact field names and the request that creates each one are on [Connect a source](/docs/white-label/connect-source).

## Your keys put your brand on the consent screen

Four of the types need an OAuth app behind them. Whose `client_id` and `client_secret` we hold decides whose name your customer reads when they are asked to grant access.

- **Supply your own `client_id` and `client_secret`** and the consent screen says *your* company. This is the point of the white-label plan, and it is the only way your customer never sees us.
- **Leave them blank** and we fall back to Context Link's own app, so your customers see **Context Link** on the consent screen instead. The row on the screen says so in plain words rather than leaving you to find out from a customer. Where we have no app of our own to fall back on, the form tells you the key is required before the type will turn on.

Each field carries a **Where to find it** link straight to the provider's credentials page: Google Cloud console, Microsoft Entra, Notion integrations, 37signals launchpad. Registering the app is a link away rather than a support ticket.

> **Provider verification is yours to obtain.** The consent screen shows your brand because it is your OAuth client. That also means the provider's review process and unverified-app caps apply to you. Google restricts Gmail and Drive scopes behind an annual third-party security assessment, and an unverified client is limited to a small number of users. Start that before you launch the type to your fleet.

Types that need no keys turn on with one click. Types that need keys show the form first.

### Keys are write-only

A stored key is reported as **set** and never rendered back into the page. You can replace it, you cannot read it. That is the opposite of your [provisioning token](/docs/white-label/getting-started), which is retrievable on purpose. A third-party OAuth secret has no such need, and rendering it would only put it in browser caches and screenshots.

What that means in practice, before you touch the form:

- **Blank means "keep what is stored", not "clear it".** Because the field is never populated, an untouched field is always blank, so saving an unchanged form leaves your keys exactly as they were.
- **Clearing is its own checkbox**, labelled *Remove this key and use Context Link's own app instead*. That is the one way to go back to our app, and it is deliberately a separate action from typing a new value.
- **Rotating the secret alone is safe.** A refresh token is bound to the `client_id` that issued it; the secret only authenticates your app at the provider's token endpoint. We read both fresh on every refresh, so the next one presents your new secret against the same `client_id` and succeeds. Nobody has to reconnect.
- **Changing the `client_id` is a fleet-wide reconnect campaign.** Every refresh token your customers hold was issued by the old OAuth app and is worthless to a different one. Those connections fail their next refresh, land in `auth_failed` and need [re-authorising](/docs/white-label/connect-source#re-authorising-a-dead-connection) one by one. The same is true of deleting the app in the provider's console. Three things count as changing the app, and the last one is the easy one to miss:
    - pointing the activation at a different OAuth client.
    - **supplying your own keys after running on Context Link's**. Every customer already connected authorised *our* app, so switching to yours orphans all of them.
    - clearing your keys to fall back to ours, which is the same move in reverse.
- **Clear both fields or neither.** The two fall back to our app independently, so removing only your secret pairs your `client_id` with our secret, and every refresh and every new authorisation fails. Nothing warns you, because our own key is present to fall back on.

Do any of these when you have somewhere to route the `connection.auth_failed` [webhooks](/docs/white-label/webhooks), and prefer supplying your own keys **before** you launch the type to customers rather than after.

### Register our redirect URI on your own app

Your keys mean your OAuth app, so the provider sends the customer back to us through a
redirect URI that has to be registered on **your** app. Add the one for that type before you
turn it on. The screen shows the exact value with a copy button next to the key fields.

| Type | Redirect URI to register |
|---|---|
| Notion | `https://context-link.ai/api/v1/oauth/callback/notion` |
| Google Drive | `https://context-link.ai/api/v1/oauth/callback/google_doc` |
| OneDrive | `https://context-link.ai/api/v1/oauth/callback/one_drive` |
| Basecamp | `https://context-link.ai/api/v1/oauth/callback/basecamp` |

Skipping this does not fail on our side. Your customer is turned away at the provider's own
consent screen with an error we never see, so there is nothing for us to report back to you.

The code exchange needs a client secret, which is why the provider returns to us rather than
to you. Where the customer lands afterwards is still yours: that is the `return_url` you send
on the [connect call](/docs/white-label/connect-source), carried through the flow in a signed
payload so it cannot be tampered with.

## Withdrawing a type purges your whole fleet

Withdrawing a source type is the most destructive action available to you anywhere in this product. **Every connection of that type, belonging to every one of your customers, is destroyed**, and with it every document indexed from those connections and every embedded passage of those documents. There is no frozen middle state and nothing to restore from.

The screen is built to make that impossible to do by accident:

1. **Withdraw** opens a modal carrying the **real counts, computed before it opens**: how many connections, how many posts, how many of your customers. Never a generic "are you sure?".
2. Above **10 connections** across the fleet you must **type the source's name** to confirm. Below it, the counts alone are the confirmation.
3. The deletion then runs **in the background**, so a fleet of ninety thousand posts does not depend on a browser tab staying open.
4. **An audit row is written before anything is destroyed**, recording who withdrew what, when, and the counts. Somebody will ask later, and by then the content is gone.
5. You receive **one org-level [`connection_type.revoked` webhook](/docs/white-label/webhooks)** at your organisation's default webhook URL, carrying the type and the number of connections destroyed. Not one per customer.

**Your keys survive the withdrawal.** The type moves back down to *Available to turn on* marked as still holding your keys, so turning it back on later is one click. What does not survive is your customers' indexed content: they would have to reconnect the source and re-sync from nothing.

Withdrawal is not the tool for a single customer who wants one source gone. That is [`DELETE .../connections/:connection_uid`](/docs/white-label/disconnect-source), which touches one connection and nobody else's.

## Limits that come with turning a type on

Turning a type on does not make it unbounded. Syncing spends your question allowance, and that is **one pool shared across your whole fleet, sized at 5,000 questions per bundle per month**. Without the caps below, one customer with an enormous mailbox could spend that pool on everybody's behalf.

| Limit | Value |
|---|---|
| Connections per customer, all types | 10, and the memory connection is exempt |
| Connections of one type per customer | 5, counting toward the 10 |
| Websites per customer | 1, counting toward the 10 |
| Custom connections per customer | 6, counting toward the 10 |
| Documents per sync per connection | 500 by default, 30 for YouTube, 50 for Web Mentions |

**10 is the binding ceiling.** The per-type numbers are maxima within it, not slices that add up to it. A customer can hold 6 custom connections or 5 mailboxes, but not both, because the total still has to come in at 10. The memory connection is the one exception: it never counts.

If a per-connection document ceiling needs turning down for one heavy customer, ask us. It is a single field on that connection rather than a cap on everyone using that type.
