Google Drive
Sync Google Docs, Sheets, Slides, and PDFs from a user's Drive into a Memuron space. Files are parsed, chunked, embedded, and semantically linked exactly like uploads — and Memuron only ever sees the files the user hands over.
Quick setup
1. Create a connection
Pick the target space and where to send the user afterwards. The response carries the Google authorization link.
curl -X POST https://memuron-production.up.railway.app/memuron/connectors/google-drive \
-H "Authorization: Bearer $MEMURON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"space_ref": "space.work",
"redirect_url": "https://yourapp.com/connected",
"document_limit": 3000
}'{
"id": "8f2c1a9e-…",
"provider": "google-drive",
"auth_link": "https://accounts.google.com/o/oauth2/v2/auth?…",
"expires_in": "15 minutes",
"redirects_to": "https://yourapp.com/connected"
}2. Handle the OAuth callback
Redirect the user to auth_link. Google returns them to Memuron, which redirects on to your redirect_url with ?status=connected&connection=<id>. A user who declines arrives with ?status=error instead.
3. Let the user pick files
Authorizing is not enough on its own. Memuron holds the connection in pending_selection until the user chooses files in the Google Picker, and saving a non-empty selection activates the connection and queues the first sync.
# 1. Mint short-lived picker credentials
curl https://memuron-production.up.railway.app/memuron/connectors/$CONNECTION_ID/picker \
-H "Authorization: Bearer $MEMURON_API_KEY"
# { "client_id": "…", "app_id": "…", "api_key": "…",
# "oauth_token": "ya29.…",
# "scopes": ["https://www.googleapis.com/auth/drive.file"] }4. Check status
# List connections and their last sync run
curl https://memuron-production.up.railway.app/memuron/connectors \
-H "Authorization: Bearer $MEMURON_API_KEY"
# List the documents that landed in the space
curl "https://memuron-production.up.railway.app/memuron/documents?space_ref=space.work" \
-H "Authorization: Bearer $MEMURON_API_KEY"{
"connections": [
{
"id": "8f2c1a9e-…",
"provider": "google-drive",
"status": "active",
"account_email": "person@example.com",
"space_token": "space.work",
"selection_count": 2,
"revisions_retained": 1,
"item_counts": { "synced": 42, "remote_deleted": 1, "skipped": 2 },
"last_sync": {
"status": "completed",
"started_at": "2026-08-03T09:14:00Z",
"completed_at": "2026-08-03T09:15:22Z",
"counts": {
"ingest": 3, "reingest": 1, "unchanged": 38,
"pending_deletions": 1, "queued": 4
},
"error_code": null
}
}
],
"count": 1,
"providers": ["google-drive"]
}Sync scope
Memuron requests only the Google drive.file scope. That scope grants access to the specific items handed over through the Picker — Memuron cannot list, read, or index anything else in the account.
| Mode | Behaviour |
|---|---|
selected | The user picks files and folders. Picked folders are walked recursively; only those items sync. |
Supported document types
Google-native files are exported before parsing. Everything else is downloaded as-is and handled by the standard document parser.
| Type | Handling |
|---|---|
| Google Docs | Exported to markdown |
| Google Sheets | Exported to .xlsx |
| Google Slides | Exported to .pptx |
| PDF, DOCX, XLSX, PPTX, XLS, PPT | Downloaded and parsed directly |
| CSV, TSV, JSON, YAML, HTML, XML, TXT, MD | Downloaded and parsed directly |
| PNG, JPEG, WEBP, GIF | Parsed, with an optional vision pass describing the image |
skipped with a reason. One bad file never fails the rest of a sync.Syncing
Sync runs on demand: once when the selection is saved, and whenever you call the sync endpoint. Each call returns a job_id you poll like any other Memuron job. Internally one job enumerates Drive and queues a separate job per changed file, so a large first import makes progress incrementally and retries per file rather than all-or-nothing.
curl -X POST https://memuron-production.up.railway.app/memuron/connectors/$CONNECTION_ID/sync \
-H "Authorization: Bearer $MEMURON_API_KEY"
# { "status": "queued", "connection_id": "…", "job_id": "…" }
# Poll like any other Memuron job
curl https://memuron-production.up.railway.app/memuron/jobs/$JOB_ID \
-H "Authorization: Bearer $MEMURON_API_KEY"Change detection is per file. Binary files compare Drive's content hash; Google-native files have no hash and fall back to modified time plus version. Unchanged files are never downloaded.
pending_selection returns 409. Finish the picker first.Edited files keep their history
When a synced file changes, Memuron ingests a new document graph and retains the previous revision, linking the two with a supersedes edge and marking the older node state:superseded. Listings and search show one current document per Drive file; pass include_superseded=true to GET /memuron/documents to see the full chain.
curl -X POST https://memuron-production.up.railway.app/memuron/connectors/$CONNECTION_ID/prune-revisions \
-H "Authorization: Bearer $MEMURON_API_KEY"
# { "pruned_document_count": 4, "deleted_memory_count": 51,
# "released_pages": 9 }Deletions are always your decision
A sync never deletes anything. When a file disappears from Drive — moved to the trash, deleted, or unshared — the tracked item moves to remote_deleted and waits. The document stays searchable until you answer.
# 1. See what disappeared from Drive. Nothing has been removed.
curl "https://memuron-production.up.railway.app/memuron/connectors/$CONNECTION_ID/items?status=remote_deleted" \
-H "Authorization: Bearer $MEMURON_API_KEY"
# 2. Answer. "keep" orphans the item so it is never raised again.
curl -X POST https://memuron-production.up.railway.app/memuron/connectors/$CONNECTION_ID/deletions \
-H "Authorization: Bearer $MEMURON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "item_ids": ["…"], "decision": "delete" }'
# { "decision": "delete", "resolved_count": 1,
# "deleted_memory_count": 12, "released_pages": 3 }| Decision | Result |
|---|---|
keep | The document stays. The item is orphaned so it is never raised again. |
delete | Every revision of the document is purged and its stored pages are released. |
Disconnecting
Deleting a connection revokes Memuron's Google authorization and stops all future syncs. Documents already imported are kept by default — pass delete_documents=true to purge them and reclaim their pages.
# Disconnect, keeping every document already imported (default)
curl -X DELETE https://memuron-production.up.railway.app/memuron/connectors/$CONNECTION_ID \
-H "Authorization: Bearer $MEMURON_API_KEY"
# Disconnect and purge the documents, reclaiming their stored pages
curl -X DELETE "https://memuron-production.up.railway.app/memuron/connectors/$CONNECTION_ID?delete_documents=true" \
-H "Authorization: Bearer $MEMURON_API_KEY"Source identity
Every node a sync produces — the collection, the document, each chunk, and each placement — carries the Drive file id as source_id, a source_url linking back to the file, and a custom_id of google-drive:<file id>. Search results therefore cite back to the exact Drive file at any granularity.
Bring your own OAuth application
By default every organization authorizes against Memuron's shared Google application. On the Scale plan an organization can supply its own instead, so consent screens carry your branding and Drive access is governed by your Cloud project rather than ours.
Create a Web application OAuth client in your Google Cloud project, enable the Drive and Picker APIs, and register <memuron-api>/memuron/connectors/auth/callback/google-drive as an authorized redirect URI. The callback stays on Memuron even when the application is yours.
# Point this organization's connections at your own Google Cloud project
curl -X PUT https://memuron-production.up.railway.app/memuron/connector-settings/google-drive \
-H "Authorization: Bearer $MEMURON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"client_id": "…apps.googleusercontent.com",
"client_secret": "…",
"extras": { "app_id": "1234567890", "picker_api_key": "…" },
"enabled": true
}'
# Inspect what is configured. Secrets are never returned.
curl https://memuron-production.up.railway.app/memuron/connector-settings \
-H "Authorization: Bearer $MEMURON_API_KEY"
# { "credentials": [{ "provider": "google-drive",
# "client_id": "…", "has_client_secret": true,
# "enabled": true, "in_use": true }], "count": 1 }
# Revert to Memuron's shared application
curl -X DELETE https://memuron-production.up.railway.app/memuron/connector-settings/google-drive \
-H "Authorization: Bearer $MEMURON_API_KEY"has_client_secret. Omit client_secret on a later update to keep the stored one while changing other fields.auth_expired and asks the user to reconnect rather than failing their next sync with an opaque Google error.Status and error codes
| Code | Meaning |
|---|---|
pending_selection | Authorized, but no files chosen yet. Sync is skipped until the picker is finished. |
auth_expired | Google access was revoked or the refresh token died. The user must reconnect. |
rate_limited | Drive quota exceeded. The job retries with backoff. |
too_large | File exceeds the 8 MB document limit; recorded as skipped. |
provider_unavailable | Drive was unreachable. The job retries automatically. |