--- title: "Google Drive connector" sidebarTitle: "Google Drive" description: "Connect Google Drive to sync documents into your Supermemory knowledge base" icon: "/images/google-drive-icon.svg" --- Connect Google Drive to sync documents into your Supermemory knowledge base with OAuth authentication and custom app support. ## Sync scope **Default for new connectors:** after OAuth, the user completes a **folder and file** picker (Google Docs, Sheets, Slides, and PDFs). Only items they select are synced and updated until they change the selection (for example from the Supermemory console). **Whole Drive:** set `config.syncScope` to `"full"` when creating the connector so the entire Drive syncs without the picker. **Explicit scoped mode:** set `config.syncScope` to `"selected"` for the picker flow, or rely on the default for new connects. If you use scoped sync and the user has not finished the picker yet, **scheduled or manual sync may skip that connector** until a selection is saved on the connector. ## Quick setup ### 1. Create Google Drive Connector ```typescript import { Supermemory } from "supermemory" const supermemory = new Supermemory({ apiKey: process.env.SUPERMEMORY_API_KEY }) const connector = await supermemory.connectors.create("user-123", { provider: "google-drive", redirectUrl: "https://yourapp.com/auth/google-drive/callback" documentLimit: 3000, config: { syncScope: "selected" }, }) // Send the user to Google to authorize if (connector.authorization) window.location.href = connector.authorization.url console.log("Auth URL expires at:", connector.authorization?.expiresAt) ``` ```python from supermemory import Supermemory import os client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY")) connector = client.connectors.create( "user-123", request={ "provider": "google-drive", "redirectUrl": "https://yourapp.com/auth/google-drive/callback", "documentLimit": 3000, "config": {"syncScope": "selected"}, }, ) # Send the user to Google to authorize print(f"Redirect to: {connector.authorization.url}") print(f"Auth URL expires at: {connector.authorization.expires_at}") ``` ```bash curl -X POST "https://api.supermemory.ai/ns/user-123/connectors" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "provider": "google-drive", "redirectUrl": "https://yourapp.com/auth/google-drive/callback", "documentLimit": 3000, "config": { "syncScope": "selected" } }' # Response: { # "id": "PTzGiUYei7pgzg5buzZHgA", # "authorization": { # "url": "https://accounts.google.com/o/oauth2/v2/auth?...", # "expiresAt": "2024-01-15T11:30:00.000Z" # } # } ``` For **whole Drive** sync, send `"config": { "syncScope": "full" }` on the same `POST /ns/{namespace}/connectors` request instead of `"selected"`. ### 2. Handle OAuth callback Send the user to `authorization.url` before `authorization.expiresAt`. After the user grants permissions, Google redirects through Supermemory to finish the connector. A pending OAuth connector is not visible in list or get until the user finishes authorization. With **scoped** sync (`syncScope` omitted or `"selected"`), the user is sent to Supermemory’s **hosted file and folder picker**; they must complete that step before syncs run. With **`syncScope: "full"`**, Supermemory redirects to your `redirectUrl` **without** the picker. You can open the picker again later for an existing connector. Read the connector with `include: "picker"` and send the user to `picker.url`; the link works once and expires at `picker.expiresAt`. Pass `returnUrl` to choose where the picker sends the user afterwards. ```typescript const connector = await supermemory.connectors.get("user-123", "PTzGiUYei7pgzg5buzZHgA", { include: "picker", returnUrl: "https://yourapp.com/settings/integrations" }) if (connector.picker) window.location.href = connector.picker.url ``` ```bash curl "https://api.supermemory.ai/ns/user-123/connectors/PTzGiUYei7pgzg5buzZHgA?include=picker&returnUrl=https%3A%2F%2Fyourapp.com%2Fsettings%2Fintegrations" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" # Response includes: "picker": { "url": "https://...", "expiresAt": "2024-01-15T11:30:00.000Z" } ``` If you already know the Drive file and folder ids, set them directly. A new selection replaces the old one and starts a sync. ```typescript await supermemory.connectors.update("user-123", "PTzGiUYei7pgzg5buzZHgA", { selection: { files: ["1AbCdEfGhIjKlMnOpQrStUvWxYz"], folders: ["0BxYzAbCdEfGhIjKlMnOpQrStU"], }, }) ``` ```bash curl -X PATCH "https://api.supermemory.ai/ns/user-123/connectors/PTzGiUYei7pgzg5buzZHgA" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "selection": { "files": ["1AbCdEfGhIjKlMnOpQrStUvWxYz"], "folders": ["0BxYzAbCdEfGhIjKlMnOpQrStU"] } }' ``` ### 3. Check Connector Status ```typescript // Get connector details with recent sync runs const connector = await supermemory.connectors.get("user-123", "PTzGiUYei7pgzg5buzZHgA", { include: "syncs", }) console.log("Account:", connector.account) console.log("Selection:", connector.selection) console.log("Last sync:", connector.latestRun?.system.status) // List synced documents in the namespace const { documents } = await supermemory.list("user-123", "documents") ``` ```python # Get connector details with recent sync runs connector = client.connectors.get("user-123", "PTzGiUYei7pgzg5buzZHgA", include=["syncs"]) print(f"Account: {connector.account}") print(f"Selection: {connector.selection}") print(f"Last sync: {connector.latest_run.system.status}") # List synced documents in the namespace documents = client.list("user-123", "documents").documents ``` ```bash # Get connector details with recent sync runs curl "https://api.supermemory.ai/ns/user-123/connectors/PTzGiUYei7pgzg5buzZHgA?include=syncs" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" # List synced documents in the namespace curl -X POST "https://api.supermemory.ai/ns/user-123/list/documents" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` There is no per-connector document list in v5. `supermemory.list(namespace, "documents")` returns every document in the namespace. ## Supported document types Based on the API type definitions, Google Drive documents are identified with these types: - `google_doc` - Google Docs - `google_slide` - Google Slides - `google_sheet` - Google Sheets Drive documents are converted to markdown before ingestion. This conversion is lossy — some formatting may not be preserved. ## Connector Management ### List All Connectors ```typescript // List all connectors in a namespace const { connectors } = await supermemory.connectors.list("user-123") connectors.forEach(connector => { console.log(`Provider: ${connector.provider}`) console.log(`ID: ${connector.id}`) console.log(`Account: ${connector.account}`) console.log(`Created: ${connector.createdAt}`) console.log(`Document limit: ${connector.documentLimit}`) console.log("---") }) ``` ```python # List all connectors in a namespace connectors = client.connectors.list("user-123").connectors for connector in connectors: print(f"Provider: {connector.provider}") print(f"ID: {connector.id}") print(f"Account: {connector.account}") print(f"Created: {connector.created_at}") print(f"Document limit: {connector.document_limit}") print("---") ``` ```bash # List all connectors in a namespace curl "https://api.supermemory.ai/ns/user-123/connectors" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" # Response example: # { # "connectors": [ # { # "id": "PTzGiUYei7pgzg5buzZHgA", # "provider": "google-drive", # "namespace": "user-123", # "account": "user@example.com", # "documentLimit": 3000, # "documentCount": 120, # "latestRun": { "system": { "status": "completed", ... }, "error": null }, # "system": { "status": "active", "createdAt": "2024-01-15T10:30:00.000Z", "lastSuccessfulSyncAt": "..." } # } # ], # "pagination": { "currentPage": 1, "limit": 50, "totalItems": 1, "totalPages": 1 } # } ``` ### Delete Connector ```typescript // Delete the connector and its imported documents (default) await supermemory.connectors.delete("user-123", "PTzGiUYei7pgzg5buzZHgA") // Delete the connector but keep the imported documents await supermemory.connectors.delete("user-123", "PTzGiUYei7pgzg5buzZHgA", { deleteDocuments: false, }) ``` ```python # Delete the connector and its imported documents (default) client.connectors.delete("user-123", "PTzGiUYei7pgzg5buzZHgA") # Delete the connector but keep the imported documents client.connectors.delete("user-123", "PTzGiUYei7pgzg5buzZHgA", delete_documents=False) ``` ```bash # Delete the connector and its imported documents (default) curl -X DELETE "https://api.supermemory.ai/ns/user-123/connectors/PTzGiUYei7pgzg5buzZHgA" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" # Delete the connector but keep the imported documents curl -X DELETE "https://api.supermemory.ai/ns/user-123/connectors/PTzGiUYei7pgzg5buzZHgA?deleteDocuments=false" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" ``` Deleting a connector will: - Stop all future syncs from Google Drive - Remove the OAuth authorization - Delete the synced documents unless you pass `deleteDocuments: false` ### Manual sync Trigger a manual synchronization. The call returns `409` while a sync for that connector is already running. ```typescript const run = await supermemory.connectors.sync("user-123", "PTzGiUYei7pgzg5buzZHgA") console.log(run.status) // Output: queued ``` ```python run = client.connectors.sync("user-123", "PTzGiUYei7pgzg5buzZHgA") print(run.status) # Output: queued ``` ```bash curl -X POST "https://api.supermemory.ai/ns/user-123/connectors/PTzGiUYei7pgzg5buzZHgA/sync" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" # Response: {"id": "PTzGiUYei7pgzg5buzZHgA", "status": "queued"} ``` ## Advanced configuration ### Custom OAuth application You can connect with your own Google OAuth app. Custom OAuth credentials are an organization setting and are not part of the v5 connector routes. See [Custom OAuth Applications](/connectors/overview#custom-oauth-applications) for the setup steps and callback URL. **Important Notes:** - Document processing happens asynchronously - Use one namespace per user or tenant - Check `latestRun.system.status` and `latestRun.error` for failed syncs