mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-09-06 08:16:03 +00:00
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>
228 lines
11 KiB
Text
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
|