RAG White-Label

Connection types

The in-app screen where you turn source types on for your whole fleet, add the OAuth keys every OAuth source requires, and withdraw a type you no longer want to carry.

Raw markdown guide for AI
Guide contents

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, checking them and removing them.

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 needs the partner's OAuth keys. Under those, an available-to-turn-on list starting with OneDrive's client ID and client secret fields.

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, 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. You can also connect one later with PUT .../connections/:connection_uid 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 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.

Your own OAuth keys are required (except Google Drive)

Four of the types need an OAuth app behind them. For Notion, OneDrive and Basecamp it has to be yours: the type will not turn on until you have entered every key for it, and there is no option to run it on Context Link's app instead. Google Drive is the one exception, below.

  • Why there is no fallback. A provider only sends a customer back to a redirect URI registered on the same OAuth app as the client_id that started the flow. Our own Notion, Microsoft and Basecamp apps are registered for our own sign-in callbacks, not for the fleet callback below, so a customer sent through them would be turned away at the provider with a redirect URI error.
  • What you get for it. The consent screen says your company, which is the point of the white-label plan: your customer never sees us.
  • Types turned on before this rule. A type that was enabled without your keys stays enabled, so nothing already indexed is purged, but it takes no new connections: the connect and re-authorise calls answer 409 partner_credentials_required until you add your keys. The row on the screen says add your OAuth keys. Customers already connected keep syncing.

Google Drive may use Context Link's verified app

Google Drive reads files through drive.readonly and documents.readonly, which Google classes as restricted and sensitive scopes. Your own Google app would need Google's app verification and an annual third-party security assessment before more than a handful of your customers could use it. So for Google Drive, and only Google Drive, you choose:

  • Leave both keys blank and your customers consent through Context Link's verified Google app. It works straight away, with no setup on your side, but the consent screen names Context Link, not you.
  • Add your own client_id and client_secret (both, never one) and the consent screen names you, once you have whitelisted the redirect URI and been through Google's verification.

Adding your own keys later, after customers have connected through ours, moves every one of them to a different OAuth app, so the screen asks for the same counted confirmation as any client id change and those customers re-authorise.

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, with the redirect URI to whitelist beside it, and refuse to turn on until every field is filled. Google Drive shows the same form with the keys optional.

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, 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.
  • There is no clearing. An OAuth type that is turned on needs your keys, so removing them is a withdrawal, not an edit.
  • 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 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 keys on a type turned on before partner keys were required. Every customer already connected there authorised our app, so switching to yours orphans all of them. The screen puts a counted confirmation in front of you first.
  • Keys go in as a set. A client_id without its client_secret is no OAuth app at all, so a half-filled form is refused rather than stored.

Do any of these when you have somewhere to route the connection.auth_failed webhooks.

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 whitelisted 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://www.context-link.ai/api/v1/oauth/callback/notion
Google Drive https://www.context-link.ai/api/v1/oauth/callback/google_doc
OneDrive https://www.context-link.ai/api/v1/oauth/callback/one_drive
Basecamp https://www.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, 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 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, 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.