mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-11 03:37:56 +00:00
Rewrites 339 TypeScript calls across 50 pages from the rc.5 `method({ namespace, body })` form to the shipped `method(namespace, { ... })` form, and aligns field names with the live v5 spec: `attach` to `include`, `authUrl` to `authorization`, `lastSync` to `latestRun`, `deletedCount` to `count`, and the paginated `namespaces.list()`.
Renames container tags to namespaces across concepts, connectors, integrations and snippets. The namespace pages keep container tag in the description, search keywords and a rename note so old searches still land, and the v3 reference page points at v5.
The migration guide's SDK table now covers both 5.0.0 SDKs, and the SDK integration page uses the real client options (`baseUrl`, `timeoutInSeconds`, `maxRetries`) and error classes.
385 lines
12 KiB
Text
385 lines
12 KiB
Text
---
|
|
title: "Gmail connector"
|
|
sidebarTitle: "Gmail"
|
|
description: "Sync email threads from Gmail with real-time Pub/Sub webhooks and incremental sync"
|
|
icon: "/icons/hugeicons/mail-01.svg"
|
|
---
|
|
|
|
Connect Gmail to automatically sync email threads into your supermemory knowledge base. Supports real-time updates via Google Cloud Pub/Sub webhooks and incremental synchronization.
|
|
|
|
<Note>
|
|
**Max Plan Required:** The Gmail connector is available on Max plan and above.
|
|
</Note>
|
|
|
|
## Quick setup
|
|
|
|
### 1. Create Gmail Connector
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
import { Supermemory } from "supermemory"
|
|
|
|
const supermemory = new Supermemory({ apiKey: process.env.SUPERMEMORY_API_KEY })
|
|
|
|
const connector = await supermemory.connectors.create("user-123", {
|
|
provider: "gmail",
|
|
redirectUrl: "https://yourapp.com/auth/gmail/callback"
|
|
documentLimit: 5000,
|
|
})
|
|
|
|
// 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)
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```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": "gmail",
|
|
"redirectUrl": "https://yourapp.com/auth/gmail/callback",
|
|
"documentLimit": 5000,
|
|
},
|
|
)
|
|
|
|
# Send the user to Google to authorize
|
|
print(f"Redirect to: {connector.authorization.url}")
|
|
print(f"Auth URL expires at: {connector.authorization.expires_at}")
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```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": "gmail",
|
|
"redirectUrl": "https://yourapp.com/auth/gmail/callback",
|
|
"documentLimit": 5000
|
|
}'
|
|
|
|
# Response: {
|
|
# "id": "PTzGiUYei7pgzg5buzZHgA",
|
|
# "authorization": {
|
|
# "url": "https://accounts.google.com/o/oauth2/v2/auth?...",
|
|
# "expiresAt": "2024-01-15T11:30:00.000Z"
|
|
# }
|
|
# }
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
### 2. Handle OAuth callback
|
|
|
|
Send the user to `authorization.url` before `authorization.expiresAt`. After the user grants permissions, Google redirects to your `redirectUrl` and the initial sync begins. A pending OAuth connector is not visible in list or get until the user finishes authorization.
|
|
|
|
### 3. Check Connector Status
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
// Get connector details with recent sync runs
|
|
const connector = await supermemory.connectors.get("user-123", "PTzGiUYei7pgzg5buzZHgA", {
|
|
include: "syncs",
|
|
})
|
|
|
|
console.log("Connected email:", connector.account)
|
|
console.log("Last sync:", connector.latestRun?.system.status)
|
|
console.log("Threads synced:", connector.documentCount)
|
|
|
|
// List synced email threads in the namespace
|
|
const docs = await supermemory.list("user-123", "documents")
|
|
|
|
console.log(`Synced ${docs.pagination.totalItems} email threads`)
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
# Get connector details with recent sync runs
|
|
connector = client.connectors.get("user-123", "PTzGiUYei7pgzg5buzZHgA", include=["syncs"])
|
|
|
|
print(f"Connected email: {connector.account}")
|
|
print(f"Last sync: {connector.latest_run.system.status}")
|
|
print(f"Threads synced: {connector.document_count}")
|
|
|
|
# List synced email threads in the namespace
|
|
docs = client.list("user-123", "documents")
|
|
|
|
print(f"Synced {docs.pagination.total_items} email threads")
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```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 email threads 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 '{}'
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
<Note>
|
|
There is no per-connector document list in v5. `supermemory.list(namespace, "documents")` returns every document in the namespace.
|
|
</Note>
|
|
|
|
## What gets synced
|
|
|
|
### Email threads
|
|
|
|
Gmail threads (conversations) are synced as individual documents with all messages included:
|
|
|
|
- **Thread content** converted to structured markdown
|
|
- **All messages** within each thread preserved in order
|
|
- **Message metadata**: subject, from, to, cc, bcc, date
|
|
- **HTML content** converted to clean markdown
|
|
- **Attachment metadata**: filename, mime type, size (attachments are referenced, not stored)
|
|
|
|
### Document metadata
|
|
|
|
Each synced thread includes searchable metadata:
|
|
|
|
| Field | Description |
|
|
|-------|-------------|
|
|
| `type` | Always `gmail_thread` |
|
|
| `subject` | Email subject line |
|
|
| `threadId` | Gmail thread ID |
|
|
| `from` | Sender email address |
|
|
| `to` | Recipient email addresses |
|
|
| `date` | Date of first message |
|
|
| `messageCount` | Number of messages in thread |
|
|
| `attachmentCount` | Number of attachments (if any) |
|
|
| `attachmentNames` | List of attachment filenames |
|
|
|
|
You can filter searches using these metadata fields:
|
|
|
|
```typescript
|
|
const results = await supermemory.search("user-123", {
|
|
query: "project update",
|
|
filter: {
|
|
operator: "and",
|
|
operands: [
|
|
{ field: "type", operator: "eq", value: "gmail_thread" },
|
|
{ field: "from", operator: "eq", value: "team@company.com" },
|
|
],
|
|
},
|
|
searchMode: "chunks",
|
|
})
|
|
```
|
|
|
|
## Connector Management
|
|
|
|
### List All Connectors
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```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("---")
|
|
})
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```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("---")
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
# List all connectors in a namespace
|
|
curl "https://api.supermemory.ai/ns/user-123/connectors" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
### Delete Connector
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```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,
|
|
})
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```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)
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```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"
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
<Note>
|
|
Deleting a connector will:
|
|
- Stop all future syncs from Gmail
|
|
- Remove the OAuth authorization
|
|
- Delete the synced documents unless you pass `deleteDocuments: false`
|
|
</Note>
|
|
|
|
### Manual sync
|
|
|
|
Trigger a manual synchronization. The call returns `409` while a sync for that connector is already running.
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
const run = await supermemory.connectors.sync("user-123", "PTzGiUYei7pgzg5buzZHgA")
|
|
|
|
console.log(run.status)
|
|
// Output: queued
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
run = client.connectors.sync("user-123", "PTzGiUYei7pgzg5buzZHgA")
|
|
|
|
print(run.status)
|
|
# Output: queued
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```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"}
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
## Sync mechanism
|
|
|
|
Gmail connector supports multiple sync methods:
|
|
|
|
| Feature | Behavior |
|
|
|---------|----------|
|
|
| **Real-time sync** | Via Google Cloud Pub/Sub webhooks (7-day expiry, auto-renewed) |
|
|
| **Scheduled sync** | Every 4 hours |
|
|
| **Manual sync** | On-demand via API |
|
|
| **Incremental sync** | Uses Gmail `historyId` to fetch only changed threads |
|
|
|
|
### How real-time sync works
|
|
|
|
1. When a connector is created, supermemory registers a Gmail API "watch" subscription
|
|
2. Gmail sends notifications to a Google Cloud Pub/Sub topic when emails change
|
|
3. supermemory receives these notifications and fetches updated threads
|
|
4. Watch subscriptions expire after 7 days and are automatically renewed
|
|
|
|
<Note>
|
|
Real-time sync monitors the **INBOX** label. Emails in other labels are synced via scheduled/manual sync.
|
|
</Note>
|
|
|
|
## Permissions & scopes
|
|
|
|
The Gmail connector requests the following OAuth scopes:
|
|
|
|
| Scope | Purpose |
|
|
|-------|---------|
|
|
| `gmail.readonly` | Read-only access to Gmail messages and threads |
|
|
| `userinfo.email` | Access to user's email address for connector identification |
|
|
|
|
<Warning>
|
|
**Read-only Access:** The Gmail connector only reads emails. It cannot send, delete, or modify any emails in the user's account.
|
|
</Warning>
|
|
|
|
## Limitations
|
|
|
|
<Warning>
|
|
**Important Limitations:**
|
|
- **Plan requirement**: Requires Max Plan or above
|
|
- **INBOX only** for real-time sync: Only INBOX label triggers real-time updates; other labels sync via scheduled sync
|
|
- **Watch expiration**: Gmail watch subscriptions expire after 7 days (automatically renewed by supermemory)
|
|
- **Document limit**: Default limit is 10,000 threads per connector (configurable via `documentLimit` parameter)
|
|
- **Attachments**: Attachment metadata is stored, but attachment content is not downloaded
|
|
- **Rate limits**: Gmail API rate limits may affect sync speed for accounts with many emails
|
|
</Warning>
|
|
|
|
## Troubleshooting
|
|
|
|
### OAuth fails or missing refresh token
|
|
|
|
If OAuth fails or the connector stops syncing:
|
|
|
|
1. Delete the existing connector
|
|
2. Create a new connector
|
|
3. Ensure the user completes the full OAuth flow with consent
|
|
|
|
```typescript
|
|
// Re-create the connector to get fresh tokens
|
|
await supermemory.connectors.delete("user-123", "PTzGiUYei7pgzg5buzZHgA", {
|
|
deleteDocuments: false,
|
|
})
|
|
|
|
const next = await supermemory.connectors.create("user-123", {
|
|
provider: "gmail",
|
|
redirectUrl: "https://yourapp.com/auth/gmail/callback"
|
|
})
|
|
|
|
// User must re-authenticate
|
|
if (next.authorization) window.location.href = next.authorization.url
|
|
```
|
|
|
|
### Emails not syncing in real-time
|
|
|
|
If real-time sync isn't working:
|
|
|
|
- Scheduled sync (every 4 hours) and manual sync still work
|
|
- Real-time sync requires supermemory's Pub/Sub infrastructure
|
|
- Check if the connector was created recently (watch registration happens on creation)
|
|
- Trigger a manual sync to verify the connector is working
|
|
|
|
### Permission denied errors
|
|
|
|
If you see permission errors:
|
|
|
|
- Ensure the user granted the required Gmail scopes during OAuth
|
|
- Verify your organization has Max Plan or above access
|
|
- Check if the user revoked app access in their Google Account settings
|