mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-28 06:24:40 +00:00
Fixes connector docs. - **`authorization.url` examples.** They now show the URL the API actually returns (`/v3/connections/auth/redirect?state=…`), not provider URLs. - **Broken examples:** - TS `connectors.create` examples were missing commas. - Python dicts now use the SDK's snake_case keys. - `connector.createdAt` → `connector.system.createdAt`. - The list default `limit` is 10. - **Pending connectors.** They are visible through get (`pending_authorization`), just not in list. - **Gmail:** - It needs the Max plan. - Nothing syncs until labels are picked. - The watch covers the selected labels, not just INBOX. - `from` filters use `contains`. - **Smaller fixes:** - The OAuth redirect-URI troubleshooting. - Notion property metadata keys. - Picker error codes. Checked against the current API and the published SDKs (TS 5.0.1, Python 5.0.0). Legacy v3/v4 docs are unchanged apart from factual fixes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
236 lines
7.2 KiB
Text
236 lines
7.2 KiB
Text
---
|
|
title: "Granola connector"
|
|
sidebarTitle: "Granola"
|
|
description: "Sync AI meeting notes and transcripts from Granola into your Supermemory knowledge base"
|
|
icon: "/images/granola.svg"
|
|
---
|
|
|
|
Connect Granola to sync AI meeting notes and transcripts into your Supermemory knowledge base. The connector uses a Granola API key, so there is no OAuth redirect flow.
|
|
|
|
<Note>
|
|
The Granola connector requires a **Pro Plan** or higher in Supermemory and a Granola plan that can create API keys. In Granola, create one from **Settings > Connectors > API keys**.
|
|
</Note>
|
|
|
|
## Quick setup
|
|
|
|
### From the console
|
|
|
|
1. Open the [Supermemory Console](https://console.supermemory.ai).
|
|
2. Go to **Connectors**.
|
|
3. Find the **Granola** row and click **Connect**.
|
|
4. Paste your Granola API key.
|
|
5. Optionally set a document limit and namespace.
|
|
6. Click **Connect**.
|
|
|
|
The console creates the connector and starts the initial sync automatically.
|
|
|
|
<Note>
|
|
The console limits connector setup to 500 documents. Use the API setup below for higher `documentLimit` values, up to 10,000.
|
|
</Note>
|
|
|
|
### With the API
|
|
|
|
<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("org-123", {
|
|
provider: "granola",
|
|
config: {
|
|
apiKey: process.env.GRANOLA_API_KEY!,
|
|
},
|
|
documentLimit: 1000,
|
|
})
|
|
|
|
// Granola doesn't require OAuth; authorization is null and the first sync starts now
|
|
console.log("Granola connector:", connector.id)
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
from supermemory import Supermemory
|
|
import os
|
|
|
|
client = Supermemory(api_key=os.environ["SUPERMEMORY_API_KEY"])
|
|
|
|
connector = client.connectors.create(
|
|
"org-123",
|
|
request={
|
|
"provider": "granola",
|
|
"config": {
|
|
"api_key": os.environ["GRANOLA_API_KEY"],
|
|
},
|
|
"document_limit": 1000,
|
|
},
|
|
)
|
|
|
|
# Granola doesn't require OAuth; authorization is None and the first sync starts now
|
|
print(f"Granola connector: {connector.id}")
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl -X POST "https://api.supermemory.ai/ns/org-123/connectors" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"provider": "granola",
|
|
"config": {
|
|
"apiKey": "'"$GRANOLA_API_KEY"'"
|
|
},
|
|
"documentLimit": 1000
|
|
}'
|
|
|
|
# Response: {"id": "PTzGiUYei7pgzg5buzZHgA", "authorization": null}
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
Supermemory validates the Granola API key before creating the connector. The initial sync starts automatically after the connector is created.
|
|
|
|
## Configuration options
|
|
|
|
For Granola, provider-specific fields go inside the `config` object. The namespace is in the URL, and `documentLimit` stays top-level in the body.
|
|
|
|
| Parameter | Location | Required | Description |
|
|
|-----------|----------|----------|-------------|
|
|
| `apiKey` | `config.apiKey` | Yes | Granola API key from **Settings > Connectors > API keys** |
|
|
| `documentLimit` | top-level | No | Maximum notes to sync per connector (default: 10,000) |
|
|
|
|
<Note>
|
|
The API key is stored encrypted and is never returned by `connectors.get` or `connectors.list`.
|
|
</Note>
|
|
|
|
## What gets synced
|
|
|
|
Granola notes are synced as markdown documents. Each document can include:
|
|
|
|
- Note title
|
|
- Meeting time, attendees, and meeting URL when Granola returns them
|
|
- AI-generated summary when present
|
|
- Full transcript when present
|
|
|
|
### Document metadata
|
|
|
|
Each synced note includes searchable metadata:
|
|
|
|
| Field | Description |
|
|
|-------|-------------|
|
|
| `type` | Always `granola` |
|
|
| `title` | Granola note title |
|
|
| `createdAt` | Granola note creation timestamp |
|
|
| `updatedAt` | Granola note update timestamp |
|
|
| `url` | Granola note URL, when available |
|
|
| `attendees` | Attendee names or emails, when available |
|
|
| `meetingStart` | Calendar event start time, when available |
|
|
|
|
You can filter searches using these metadata fields:
|
|
|
|
```typescript
|
|
const results = await supermemory.search("org-123", {
|
|
query: "customer onboarding discussion",
|
|
filter: {
|
|
operator: "and",
|
|
operands: [
|
|
{ field: "type", operator: "eq", value: "granola" },
|
|
{ field: "attendees", operator: "arrayContains", value: "alex@company.com" },
|
|
],
|
|
},
|
|
searchMode: "chunks",
|
|
})
|
|
```
|
|
|
|
## Connector Management
|
|
|
|
### Check Sync Status
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
const connector = await supermemory.connectors.get("org-123", "PTzGiUYei7pgzg5buzZHgA", {
|
|
include: "syncs",
|
|
})
|
|
|
|
console.log("Last sync:", connector.latestRun?.system.status, connector.latestRun?.error)
|
|
console.log("Notes synced:", connector.documentCount)
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl "https://api.supermemory.ai/ns/org-123/connectors/PTzGiUYei7pgzg5buzZHgA?include=syncs" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
### Delete Connector
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
await supermemory.connectors.delete("org-123", "PTzGiUYei7pgzg5buzZHgA")
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
client.connectors.delete("org-123", "PTzGiUYei7pgzg5buzZHgA")
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl -X DELETE "https://api.supermemory.ai/ns/org-123/connectors/PTzGiUYei7pgzg5buzZHgA" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
<Warning>
|
|
By default, deleting a connector removes all synced documents from Supermemory. To keep documents, pass `deleteDocuments: false` (`DELETE /ns/{namespace}/connectors/{id}?deleteDocuments=false`).
|
|
</Warning>
|
|
|
|
### Manual sync
|
|
|
|
The call returns `409` while a sync for that connector is already running.
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
```typescript
|
|
await supermemory.connectors.sync("org-123", "PTzGiUYei7pgzg5buzZHgA")
|
|
```
|
|
</Tab>
|
|
<Tab title="Python">
|
|
```python
|
|
client.connectors.sync("org-123", "PTzGiUYei7pgzg5buzZHgA")
|
|
```
|
|
</Tab>
|
|
<Tab title="cURL">
|
|
```bash
|
|
curl -X POST "https://api.supermemory.ai/ns/org-123/connectors/PTzGiUYei7pgzg5buzZHgA/sync" \
|
|
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
|
|
|
# Response: {"id": "PTzGiUYei7pgzg5buzZHgA", "status": "queued"}
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
## Sync behavior
|
|
|
|
| Feature | Behavior |
|
|
|---------|----------|
|
|
| **Initial sync** | Fetches Granola notes up to `documentLimit` |
|
|
| **Incremental sync** | Uses Granola `updated_at` timestamps to fetch notes changed since the previous sync |
|
|
| **Transcript handling** | Fetches each note with transcript content included |
|
|
| **Sync schedule** | Initial sync after connector creation + manual triggers |
|
|
| **Document limit** | 10,000 notes per connector (default) |
|
|
|
|
## Troubleshooting
|
|
|
|
| Error | Solution |
|
|
|-------|----------|
|
|
| `Granola API key is required` | Include a non-empty `config.apiKey` value when creating the connector |
|
|
| `Granola API key is invalid` | Create a new key in Granola and reconnect |
|
|
| `Could not reach Granola API` | Retry after checking Granola API availability and network access |
|
|
| Missing notes | Check `documentLimit`; if the workspace has more notes than the limit, only notes up to the limit are imported |
|