supermemory/apps/docs/connectors/overview.mdx
Dhravya Shah 48167c3246 docs: fix production build breaker — HTML comments are invalid MDX
71 '<!-- CONFIRM -->' review markers across 19 files used HTML comment
syntax, which MDX cannot parse. One parse error breaks the whole
production build — this is why the deployed site 404'd on every page
while local dev limped along. All converted to {/* */} (code-fence
contents untouched). Also: remove the legacy source-'/' redirect,
replace the phantom architecture-diagram image with an ASCII diagram
until the real one lands.

Verified locally: mintlify broken-links parses all pages clean (one
known-good /api-reference tab link that 307s at runtime), and /,
/overview, /concepts/architecture, /quickstart, /patterns/*,
/versioning all render 200 with content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 16:47:05 -07:00

228 lines
11 KiB
Text

---
title: "Connectors"
description: "Sync content from Google Drive, Notion, Gmail, OneDrive, GitHub, S3, Granola, and the web into supermemory — and know each connector's limits before you commit."
sidebarTitle: "Overview"
icon: "layers"
---
Connectors pull content from the tools your users already work in and feed it into the same ingestion pipeline as everything else. A synced Notion page becomes a document, the pipeline derives memories from it, and those memories show up in [search](/search), [profiles](/concepts/user-profiles), and every other surface — exactly as if you'd added it through the API.
You create a connection, your user completes OAuth (or supplies credentials, for S3 and Granola), and sync starts. That's the whole integration.
## What you can connect
{/* CONFIRM: plan matrix — verify per-plan availability against current billing config before publish */}
| Connector | What syncs | Plan | Sync behavior |
|-----------|-----------|------|---------------|
| [Notion](/connectors/notion) | Pages, databases, blocks | All paid plans | Webhooks + every ~4h |
| [Google Drive](/connectors/google-drive) | Docs, Sheets, Slides, PDFs | All paid plans | Webhooks + every ~4h |
| [OneDrive](/connectors/onedrive) | Word, Excel, PowerPoint | All paid plans | Webhooks + every ~4h |
| [Gmail](/connectors/gmail) | Email threads | Scale and up | Pub/Sub webhooks + every ~4h |
| [GitHub](/connectors/github) | Documentation files in repos | Scale and up | Delayed — hours, not real-time |
| [S3](/connectors/s3) | Files in S3-compatible buckets | Scale and up | Scheduled |
| [Web Crawler](/connectors/web-crawler) | Web pages, docs sites | Scale and up | Scheduled recrawl |
| [Granola](/connectors/granola) | Meeting notes, transcripts | Pro and up | Manual only |
The default cadence: a full import on connect, a scheduled pass roughly every 4 hours, webhook-triggered updates where the provider supports them, and manual sync on demand. The table above notes where a connector deviates — Granola is manual-only, for example. The details — debounce windows, webhook renewal, monitoring endpoints — live in [sync lifecycle](/connectors/sync-lifecycle).
## Connect your first source
Create a connection to get an auth link, then send your user to it:
<CodeGroup>
```typescript TypeScript
import Supermemory from 'supermemory';
const client = new Supermemory({
apiKey: process.env.SUPERMEMORY_API_KEY,
});
const connection = await client.connections.create('notion', {
redirectUrl: 'https://yourapp.com/integrations/callback',
containerTags: ['user_4f8a'],
});
// send the user here to authorize
console.log(connection.authLink);
console.log(connection.expiresIn); // "1 hour"
```
```python Python
from supermemory import Supermemory
import os
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
connection = client.connections.create(
'notion',
redirect_url='https://yourapp.com/integrations/callback',
container_tags=['user_4f8a'],
)
# send the user here to authorize
print(connection.auth_link)
print(connection.expires_in) # "1 hour"
```
```bash cURL
# POST /v3/connections/{provider}
curl -X POST "https://api.supermemory.ai/v3/connections/notion" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"redirectUrl": "https://yourapp.com/integrations/callback",
"containerTags": ["user_4f8a"]
}'
# {
# "id": "conn_9f2c1b",
# "authLink": "https://api.notion.com/v1/oauth/authorize?...",
# "expiresIn": "1 hour",
# "redirectsTo": "https://yourapp.com/integrations/callback"
# }
```
</CodeGroup>
The auth link expires in one hour. Generate it when the user clicks "connect", not ahead of time — a stale link means a failed OAuth and a confused user.
Once they authorize, sync starts on its own. There's no second API call to make. Everything the connection imports is tagged with the `containerTags` you set at creation, so a per-user tag keeps each user's synced content inside their own boundary — the same [permissioning](/concepts/permissioning) model as the rest of supermemory.
<Note>
The connections API takes `containerTags` as an array — it's a v3 endpoint. Keep one tag per isolation boundary anyway; tags on a connection are fixed after creation, so pick the tag as carefully as you'd pick it for a document.
</Note>
## Check what synced
List connections to see what's active, and list documents to see what actually got imported:
<CodeGroup>
```typescript TypeScript
const connections = await client.connections.list({
containerTags: ['user_4f8a'],
});
for (const conn of connections) {
console.log(conn.provider, conn.email, conn.createdAt);
}
// then verify the imported documents themselves
const docs = await client.documents.list({
containerTags: ['user_4f8a'],
});
```
```python Python
connections = client.connections.list(container_tags=['user_4f8a'])
for conn in connections:
print(conn.provider, conn.email, conn.created_at)
# then verify the imported documents themselves
docs = client.documents.list(container_tags=['user_4f8a'])
```
```bash cURL
# POST /v3/connections/list
curl -X POST "https://api.supermemory.ai/v3/connections/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"containerTags": ["user_4f8a"]}'
# POST /v3/documents/list
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"containerTags": ["user_4f8a"]}'
```
</CodeGroup>
Each imported document carries a processing status (`queued → extracting → chunking → embedding → indexing → done`, or `failed`), so polling the document list tells you exactly how far an import has gotten. The full verification recipe — and how long indexing should take — is in the [connectors FAQ](/connectors/faq).
## Know the limits before you commit
Every connector has edges. These are the ones that surprise people.
### Google Drive syncs what the user picks — not the whole Drive
By default, after OAuth your user completes a file-and-folder picker, and **only the items they select** sync. If they pick one folder out of twenty, you sync one folder out of twenty. Users who expect "connect Drive, get Drive" will report missing files — set that expectation in your UI before they hit connect.
Whole-Drive sync exists: pass `metadata.syncScope: "full"` when you create the connection and the picker is skipped. But broad Drive access runs into Google's rules, not ours. Google treats full-Drive scopes as restricted: consent screens show an unverified-app warning until your OAuth app passes Google's verification, and restricted scopes carry a recurring security assessment per client ID — a cost you own, annually. {/* CONFIRM: Google verification/annual security assessment specifics */}
The production path for whole-Drive sync is a [custom OAuth app](/connectors/google-drive#custom-oauth-application): register your own Google client, complete verification under your brand, then point supermemory at it with `client.settings.update({ googleDriveCustomKeyEnabled: true, ... })`. Your users see your name on the consent screen instead of a warning.
### The rest, briefly
- **GitHub** syncs on a delay — changes land in hours, not seconds. Don't build "push to repo, query immediately" flows on it.
- **Granola** has no automatic sync. You trigger imports manually.
- **Web Crawler** recrawls on a schedule, so page edits take time to appear. It respects robots.txt — pages it's told not to fetch won't sync.
- **Notion** connects to one workspace per authorization. To switch accounts, delete the connection and reconnect.
- **Large files**: connector files over 50MB are skipped. {/* CONFIRM: 50MB per-file connector limit */}
## What doesn't exist yet
Sources people often ask about that don't sync today:
- **Microsoft Teams, Outlook, and SharePoint** — no connectors today. OneDrive covers files in Microsoft 365, but Teams messages, Outlook mail, and SharePoint sites do **not** sync.
- **HubSpot** — in development, not shipped. {/* CONFIRM: HubSpot in development */}
- **Slack, Jira, Confluence, Linear** — not available as connectors.
If your source isn't listed, you don't have to wait. The document API is itself a connector surface: pull from the source's API, add each item with a `customId` (so re-adds update instead of duplicate), and you've built the sync yourself. [Ingestion best practices](/patterns/ingestion) walks through the pattern.
## Disconnect a source
Deleting a connection stops sync — and deletes the imported documents with it, because `deleteDocuments` defaults to `true` on `DELETE /v3/connections/{connectionId}`. To keep what's already imported, say so explicitly:
<CodeGroup>
```typescript TypeScript
// stop syncing and delete the imported documents (the default)
await client.connections.deleteByID('conn_9f2c1b');
// stop syncing, keep everything already imported
await client.connections.deleteByID('conn_9f2c1b', {
query: { deleteDocuments: false },
});
```
```python Python
# stop syncing and delete the imported documents (the default)
client.connections.delete_by_id('conn_9f2c1b')
# stop syncing, keep everything already imported
client.connections.delete_by_id(
'conn_9f2c1b',
extra_query={'deleteDocuments': 'false'},
)
```
```bash cURL
# DELETE /v3/connections/{connectionId} — deletes imported documents too
curl -X DELETE "https://api.supermemory.ai/v3/connections/conn_9f2c1b" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
# keep the imported documents
curl -X DELETE "https://api.supermemory.ai/v3/connections/conn_9f2c1b?deleteDocuments=false" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
```
</CodeGroup>
<Warning>
The default delete is permanent — the documents and the memories derived from them are gone, and deletion does **not** restore used quota. If you only need to pause sync, pass `deleteDocuments=false` so the documents stay, then reconnect later.
</Warning>
The SDK doesn't type `deleteDocuments` as a method parameter — it's a query parameter on the request, which is why the examples pass it through the request options. {/* CONFIRM: python — extra_query kwarg name against the published pypi package */}
That's the whole surface: connect, verify, disconnect. Everything a connector imports lives in the same engine as your API-added content — one search, one graph, one set of profiles.
## Where next
- [Sync lifecycle](/connectors/sync-lifecycle) — cadence, debounce, webhook renewal, and monitoring sync runs
- [Connectors FAQ](/connectors/faq) — expired auth links, immutable tags, verifying imports
- [Google Drive](/connectors/google-drive) — the custom OAuth app setup in full
- [Ingestion best practices](/patterns/ingestion) — build your own connector on the document API