User GuideGoogle Drive Integration

Google Drive Integration

StudioBrain can sync your content directly to Google Drive, allowing you to:

  • Store all entity markdown files in Google Drive
  • Access your content from any device with Drive access
  • Collaborate using Drive’s sharing features
  • Backup automatically with Drive’s version history

Overview

The Google Drive integration uses the Google Drive API v3 to:

  • Create folder structures matching StudioBrain’s entity organization
  • Store entity markdown as text files
  • Manage assets (images, audio, video) in subfolders
  • Sync changes using the Drive Changes API
  • Provide temporary download URLs for assets

Prerequisites

Before setting up Google Drive integration:

  1. Google Cloud Project with Drive API enabled
  2. OAuth 2.0 credentials (web application type)
  3. Drive folder to use as root for StudioBrain content

Setting Up Google Cloud Project

  1. Go to Google Cloud Console
  2. Create a new project (or use existing)
  3. Enable Google Drive API
  4. Go to APIs & Services > OAuth consent screen
    • Choose “External” user type
    • Fill in required app information
    • Add scopes: https://www.googleapis.com/auth/drive.file
  5. Go to APIs & Services > Credentials
    • Create OAuth 2.0 Client ID (Web application)
    • Add authorized redirect URIs (StudioBrain will provide)
    • Save the Client ID and Client Secret

Authentication Flow

StudioBrain uses OAuth 2.0 to authenticate with Google Drive on behalf of users:

  1. Authorization Request

    • User clicks “Connect Google Drive” in StudioBrain
    • Redirected to Google OAuth consent screen
    • User grants permission for StudioBrain to access Drive
  2. Token Exchange

    • Google redirects back with authorization code
    • StudioBrain exchanges code for access/refresh tokens
    • Tokens are encrypted and stored on the User model
  3. Token Refresh

    • Access tokens expire after 1 hour
    • StudioBrain automatically refreshes using refresh token
    • Refresh tokens don’t expire (until user revokes)

Token Storage

OAuth tokens are stored encrypted on the User model and may also be stored in tenant storage config:

{
  "google_drive": {
    "root_folder_id": "abc123xyz",
    "root_folder_name": "StudioBrain Content",
    "credentials_json": {
      "access_token": "ya29.a0AeDClZ...",
      "refresh_token": "1//0gHwQ...",
      "client_id": "123456789-abc...",
      "client_secret": "GOCSPX-abc123...",
      "token_expires": "2026-03-10T15:30:00Z"
    },
    "connected_at": "2026-03-10T10:00:00Z",
    "connected_by": "user-uuid"
  }
}

OAuth Through Google Sign-In

OAuth for Drive access is handled through the main Google Sign-In flow:

  • Incremental Authorization: GET /api/auth/oauth/google/drive
  • This endpoint provides the OAuth URL to grant Drive-specific permissions
  • After authorization, tokens are stored on the User model

Folder Structure

StudioBrain mirrors its local filesystem structure on Google Drive:

Drive Root (specified during setup)
├── Characters/
│   ├── john_doe/
│   │   ├── CH_john_doe.md          # Main entity file
│   │   ├── images/
│   │   │   ├── portrait.png
│   │   │   └── concept_art.jpg
│   │   ├── audio/
│   │   │   └── voice_sample.wav
│   │   └── models/
│   └── jane_smith/
│       └── CH_jane_smith.md
├── Locations/
│   ├── neotokyo/
│   │   └── LOC_neotokyo.md
│   └── space_station/
│       └── LOC_spacestation.md
├── Items/
├── Factions/
├── Dialogues/
└── Assets/
    └── shared_resources/

Entity Type Folders

Each entity type gets a top-level folder:

  • Characters
  • Locations
  • Items
  • Factions
  • Jobs
  • Brands
  • Dialogues
  • Workflows
  • Shows
  • Campaigns
  • Music
  • Audio
  • SocialMedia
  • Tools
  • GDD
  • StyleGuide
  • Scripts
  • Timeline
  • Assembly
  • Inventory
  • Archives

Asset Subfolders

Each entity folder can contain these asset subfolders:

  • images - PNG, JPG, GIF, WebP
  • audio - MP3, WAV, OGG
  • video - MP4, WebM
  • models - GLB, GLTF, FBX
  • data - JSON, CSV, XML
  • comfy_workflows - YAML workflow files

Extra Folders by Type

Some entity types get additional folders:

  • Locations: maps/ for location maps

Setup Instructions

1. Configure OAuth Credentials

In StudioBrain admin panel:

  1. Go to Settings > Integrations > Google Drive
  2. Enter your Google Cloud credentials:
    • Client ID
    • Client Secret
    • Redirect URI (provided by StudioBrain)
  3. Save configuration

2. Connect Google Drive

  1. Go to Settings > Integrations > Google Drive
  2. Click Connect to Google Drive
  3. Authorize StudioBrain in the Google popup
  4. Select the Drive folder to use as root using the folder picker
  5. Click Select Folder

3. Enable Cloud Sync

  1. Go to Settings > Sync
  2. Enable Cloud Sync
  3. Select Google Drive as storage provider
  4. Configure sync frequency (real-time or manual)

Usage

Creating Entities

When you create a new entity:

  1. StudioBrain creates the entity folder on Drive
  2. Standard asset subfolders are created automatically
  3. The main markdown file is created with entity frontmatter
  4. Content is saved to Drive on every save

Syncing Changes

StudioBrain uses Drive’s Changes API to detect changes:

  1. Polling: StudioBrain polls Drive for changes every N minutes
  2. Start Page Token: Stored to resume from last known state
  3. Change Events:
    • created - New file/folder detected
    • updated - File modified
    • deleted - File/folder trashed

Asset Management

Assets are uploaded to Drive as binary files:

  1. Upload: Asset data sent via multipart upload
  2. URL Generation: Drive provides temporary webContentLink
  3. Caching: URLs cached for performance
  4. Cleanup: Orphaned assets detected and cleaned

Conflict Resolution

When conflicts occur (local vs Drive):

  1. Timestamp check: Most recent wins
  2. Manual resolve: User prompted if conflicts persist
  3. Version history: Drive keeps versions for 30 days

API Reference

Connection Status Endpoints

Check Drive Connection Status

GET /api/drive/status

Check if Google Drive is connected and the user has valid tokens.

Response:

{
  "connected": true,
  "configured": true,
  "has_access_token": true,
  "auth_provider": "google",
  "token_expires": "2026-03-10T15:30:00Z",
  "upgrade_url": "/api/auth/oauth/google/drive"
}

Response Fields:

FieldTypeDescription
connectedbooleanTrue when user has stored Google access token
configuredbooleanTrue when Google OAuth is configured on server
has_access_tokenbooleanWhether user has valid tokens
auth_providerstringOAuth provider (e.g., “google”)
token_expiresstringISO 8601 token expiration timestamp
upgrade_urlstringURL to start drive.file upgrade flow (null if not configured)

Drive Storage Provider Endpoints

These endpoints manage Google Drive as a storage provider for the tenant.

Check Storage Provider Status

GET /api/drive-storage/status

Return the Google Drive storage provider status for the current tenant.

Response:

{
  "server_configured": true,
  "user_has_tokens": true,
  "is_active_provider": true,
  "root_folder_id": "abc123xyz",
  "root_folder_name": "StudioBrain Content",
  "connected_at": "2026-03-10T10:00:00Z",
  "connected_by": "user-uuid",
  "login_url": "/api/auth/oauth/google",
  "upgrade_url": "/api/auth/oauth/google/drive"
}

Response Fields:

FieldTypeDescription
server_configuredbooleanTrue when Google OAuth is configured on server
user_has_tokensbooleanWhether user has Drive tokens
is_active_providerbooleanTrue when Drive is the active storage provider
root_folder_idstringDrive folder ID used as project root
root_folder_namestringDisplay name of the root folder
connected_atstringISO 8601 timestamp when connected
connected_bystringUser ID who connected
login_urlstringURL to sign in with Google
upgrade_urlstringURL to grant Drive access

List Drive Folders for Picker

GET /api/drive-storage/folders

List folders on the user’s Google Drive for the folder picker UI.

Query Parameters:

ParameterTypeDefaultDescription
parent_idstringnullParent folder ID (omit for root)
page_tokenstringnullPagination token
page_sizeinteger50Max results (1-200)

Response:

{
  "folders": [
    {
      "id": "folder123",
      "name": "StudioBrain Content",
      "modified_time": "2026-03-09T14:20:00Z"
    },
    {
      "id": "folder456",
      "name": "Characters Backup",
      "modified_time": "2026-03-08T10:00:00Z"
    }
  ],
  "next_page_token": "CgkIAhIFGNnQ8wMSFQoNCPqL9tICEgkI9ov2wgISAggBGAEgAQ==",
  "parent_id": "root"
}

Example:

curl -X GET "http://localhost:8201/api/drive-storage/folders" \
  -H "Authorization: Bearer YOUR_TOKEN"

Select Project Folder

POST /api/drive-storage/select-folder

Select a Google Drive folder as the project root and activate Drive as the storage provider.

Request Body:

{
  "folder_id": "abc123xyz",
  "folder_name": "StudioBrain Content"
}

Request Body Fields:

FieldTypeRequiredDescription
folder_idstringYesGoogle Drive folder ID
folder_namestringNoDisplay name of the folder (for UI)

Response:

{
  "status": "connected",
  "folder_id": "abc123xyz",
  "folder_name": "StudioBrain Content",
  "provider": "google_drive"
}

Example:

curl -X POST "http://localhost:8201/api/drive-storage/select-folder" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "folder_id": "abc123xyz",
    "folder_name": "StudioBrain Content"
  }'

Disconnect Drive Storage

POST /api/drive-storage/disconnect

Disconnect Google Drive as the storage provider, reverting to local_fs.

Response:

{
  "status": "disconnected",
  "provider": "local_fs"
}

Test Drive Connection

POST /api/drive-storage/test

Test the Google Drive connection by listing the root folder contents.

Response:

{
  "status": "ok",
  "root_folder_id": "abc123xyz",
  "root_folder_name": "StudioBrain Content",
  "folders_found": 5,
  "files_found": 127,
  "folder_names": ["Characters", "Locations", "Items", "Factions", "Dialogues"]
}

Example:

curl -X POST "http://localhost:8201/api/drive-storage/test" \
  -H "Authorization: Bearer YOUR_TOKEN"

Register Desktop Tokens

POST /api/drive-storage/register-desktop-tokens

Accept Google Drive OAuth tokens pushed from a desktop client and store them in the tenant’s storage config.

This is used when a desktop user completes Google Drive OAuth, pushing tokens to the SaaS backend for cloud sync.

Request Body:

{
  "access_token": "ya29.a0AeDClZ...",
  "refresh_token": "1//0gHwQ...",
  "token_expires": "2026-03-10T15:30:00Z",
  "root_folder_id": "abc123xyz",
  "root_folder_name": "StudioBrain Content"
}

Request Body Fields:

FieldTypeRequiredDescription
access_tokenstringNoGoogle OAuth access token (fallback to user tokens)
refresh_tokenstringNoGoogle OAuth refresh token
token_expiresstringNoISO 8601 expiration timestamp
root_folder_idstringYesGoogle Drive folder ID
root_folder_namestringNoDisplay name of the folder

Response:

{
  "status": "registered",
  "folder_id": "abc123xyz",
  "folder_name": "StudioBrain Content",
  "provider": "google_drive",
  "source": "desktop"
}

Cloud Sync Endpoints

Note: These endpoints are only available in cloud deployments.

Check Cloud Sync Status

GET /api/drive-storage/cloud-sync-status

Return the cloud Drive sync worker status including desktop presence.

Response:

{
  "sync_worker": {
    "running": true,
    "last_sync": "2026-03-10T10:30:00Z",
    "entities_synced": 1247,
    "assets_synced": 3456,
    "last_error": null
  },
  "desktop_presence": {
    "online": true,
    "sessions": 1
  },
  "token_health": {
    "healthy": true,
    "last_refresh": "2026-03-10T10:25:00Z",
    "refreshes_remaining": 45
  }
}

Response Fields:

FieldTypeDescription
sync_workerobjectWorker statistics (null if not running)
desktop_presenceobjectWhether desktop client is online
token_healthobjectOAuth token status

Force Drive Sync

POST /api/drive-storage/force-sync

Trigger an immediate Drive sync for the current tenant, bypassing the desktop-online check.

Response:

{
  "status": "completed",
  "results": {
    "entities_created": 2,
    "entities_updated": 5,
    "entities_deleted": 0,
    "assets_synced": 12
  }
}

Drive File Operations Endpoints

These endpoints provide direct file operations on Google Drive.

Note: Write operations (export-entity, update, share) require drive.file scope. Users without write scope receive a 403 with an upgrade_url.

List Drive Files

GET /api/drive/files

List files from the user’s Google Drive.

Query Parameters:

ParameterTypeDefaultDescription
querystringnullDrive API query string
folder_idstringnullRestrict to folder ID
page_tokenstringnullPagination token
page_sizeinteger20Max results (1-100)

Response:

{
  "files": [
    {
      "id": "file123",
      "name": "CH_john_doe.md",
      "mimeType": "text/markdown",
      "size": "4096",
      "modifiedTime": "2026-03-10T09:15:00Z",
      "webContentLink": "https://..."
    }
  ],
  "nextPageToken": "CgkIAhIFGNnQ8wMSFQoNCPqL9tICEgkI9ov2wgISAggBGAEgAQ=="
}

Get Drive File Metadata

GET /api/drive/files/{file_id}

Return metadata for a specific Google Drive file.

Path Parameters:

ParameterTypeDescription
file_idstringGoogle Drive file ID

Response:

{
  "id": "file123",
  "name": "CH_john_doe.md",
  "mimeType": "text/markdown",
  "size": "4096",
  "createdTime": "2026-03-09T10:00:00Z",
  "modifiedTime": "2026-03-10T09:15:00Z",
  "webLink": "https://drive.google.com/file/d/file123/view",
  "webViewLink": "https://drive.google.com/file/d/file123/view",
  "description": "Character profile for John Doe"
}

Export Drive File Content

GET /api/drive/files/{file_id}/export

Export a Google Workspace document or regular text file as plain text.

Google Docs are exported via the Drive /export API. Other file types are downloaded directly via ?alt=media.

Response: text/plain

---
type: Character
name: John Doe
---

Character content here...

Export Entity to Drive

POST /api/drive/export-entity

Create a new Google Doc containing the supplied entity content.

Request Body:

{
  "name": "John Doe Character Profile",
  "content": "---\ntype: Character\nname: John Doe\n...\n\nCharacter content here.",
  "folder_id": "abc123xyz"  // optional
}

Request Body Fields:

FieldTypeRequiredDescription
namestringYesDocument title
contentstringYesPlain-text or Markdown content
folder_idstringNoOptional parent folder ID

Response:

{
  "file_id": "xyz789abc",
  "name": "John Doe Character Profile",
  "web_view_link": "https://drive.google.com/file/d/xyz789abc/view",
  "mime_type": "application/vnd.google-apps.document"
}

Update Drive File Content

PUT /api/drive/files/{file_id}

Overwrite the content of an existing Google Drive file.

Path Parameters:

ParameterTypeDescription
file_idstringGoogle Drive file ID

Request Body:

{
  "content": "---\ntype: Character\nname: John Doe\n...\n\nUpdated character content."
}

Response:

{
  "file_id": "file123",
  "name": "CH_john_doe.md",
  "modified": true,
  "modified_time": "2026-03-10T11:30:00Z"
}

Share Drive File

POST /api/drive/files/{file_id}/share

Share a Google Drive file with another user by email address.

Path Parameters:

ParameterTypeDescription
file_idstringGoogle Drive file ID

Request Body:

{
  "email": "colleague@example.com",
  "role": "writer"
}

Request Body Fields:

FieldTypeRequiredDescription
emailstringYesRecipient email address
rolestringNoDefault: “reader”. One of: “reader”, “commenter”, “writer”

Response:

{
  "permission_id": "perm123",
  "email": "colleague@example.com",
  "role": "writer"
}

Troubleshooting

OAuth Connection Fails

Error: OAuth authorization failed

Possible Causes:

  • Client ID/Secret incorrect
  • Redirect URI mismatch
  • OAuth consent not configured

Solutions:

  1. Verify Client ID and Secret in Google Cloud Console
  2. Add StudioBrain’s redirect URI to authorized list
  3. Complete OAuth consent screen setup

Drive Folder Not Found

Error: Root folder not found on Drive

Possible Causes:

  • Folder was deleted
  • Folder ID changed
  • Permission issue

Solutions:

  1. Reconnect Google Drive and select the correct folder
  2. Verify Drive folder still exists
  3. Check folder permissions

Sync Failures

Error: Failed to sync entity to Drive

Possible Causes:

  • Network connectivity issue
  • Drive API quota exceeded
  • Invalid entity ID or content

Solutions:

  1. Check network connectivity
  2. Review Drive API quota in Google Cloud Console
  3. Verify entity content is valid markdown
  4. Force sync: POST /api/drive-storage/force-sync

Token Refresh Failed

Error: Token refresh failed (401)

Possible Causes:

  • Refresh token expired
  • User revoked access
  • Client credentials changed

Solutions:

  1. Reconnect Google Drive (re-authorize)
  2. Verify Client credentials haven’t changed
  3. Check if user revoked access in Google account

Insufficient Permissions

Error: Insufficient Drive scope

Possible Causes:

  • Token doesn’t have drive.file scope
  • Drive API not enabled on project

Solutions:

  1. Re-authenticate: GET /api/auth/oauth/google/drive
  2. Verify Drive API is enabled in Google Cloud Console
  3. Grant Drive permissions during OAuth flow

Security Considerations

Data Encryption

  • At Rest: Drive stores data encrypted
  • In Transit: All Drive API calls use HTTPS
  • Tokens: OAuth tokens encrypted in database

Permission Scopes

StudioBrain requests minimal scopes:

  • https://www.googleapis.com/auth/drive.file - Create, read, update, delete own files

Access Control

  • Each tenant has separate Drive folder
  • Tenant tokens stored separately
  • No cross-tenant data access

Backup and Recovery

  • Drive keeps file versions for 30 days
  • Use Drive’s version history to restore
  • StudioBrain maintains local cache as backup

Best Practices

  1. Use dedicated folder: Create a separate Drive folder for StudioBrain
  2. Limit scope: Drive API scope is limited to StudioBrain files only
  3. Monitor quota: Watch Drive API usage in Google Cloud Console
  4. Regular backups: Enable Drive version history
  5. Test connection: Use POST /api/drive-storage/test regularly