--- 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: ```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" # } ``` 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. 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. ## Check what synced List connections to see what's active, and list documents to see what actually got imported: ```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"]}' ``` 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: ```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" ``` 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. 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