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:
- Google Cloud Project with Drive API enabled
- OAuth 2.0 credentials (web application type)
- Drive folder to use as root for StudioBrain content
Setting Up Google Cloud Project
- Go to Google Cloud Console
- Create a new project (or use existing)
- Enable Google Drive API
- 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
- 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
OAuth 2.0 Flow (Recommended)
StudioBrain uses OAuth 2.0 to authenticate with Google Drive on behalf of users:
-
Authorization Request
- User clicks “Connect Google Drive” in StudioBrain
- Redirected to Google OAuth consent screen
- User grants permission for StudioBrain to access Drive
-
Token Exchange
- Google redirects back with authorization code
- StudioBrain exchanges code for access/refresh tokens
- Tokens are encrypted and stored on the User model
-
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:
CharactersLocationsItemsFactionsJobsBrandsDialoguesWorkflowsShowsCampaignsMusicAudioSocialMediaToolsGDDStyleGuideScriptsTimelineAssemblyInventoryArchives
Asset Subfolders
Each entity folder can contain these asset subfolders:
images- PNG, JPG, GIF, WebPaudio- MP3, WAV, OGGvideo- MP4, WebMmodels- GLB, GLTF, FBXdata- JSON, CSV, XMLcomfy_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:
- Go to Settings > Integrations > Google Drive
- Enter your Google Cloud credentials:
- Client ID
- Client Secret
- Redirect URI (provided by StudioBrain)
- Save configuration
2. Connect Google Drive
- Go to Settings > Integrations > Google Drive
- Click Connect to Google Drive
- Authorize StudioBrain in the Google popup
- Select the Drive folder to use as root using the folder picker
- Click Select Folder
3. Enable Cloud Sync
- Go to Settings > Sync
- Enable Cloud Sync
- Select Google Drive as storage provider
- Configure sync frequency (real-time or manual)
Usage
Creating Entities
When you create a new entity:
- StudioBrain creates the entity folder on Drive
- Standard asset subfolders are created automatically
- The main markdown file is created with entity frontmatter
- Content is saved to Drive on every save
Syncing Changes
StudioBrain uses Drive’s Changes API to detect changes:
- Polling: StudioBrain polls Drive for changes every N minutes
- Start Page Token: Stored to resume from last known state
- Change Events:
created- New file/folder detectedupdated- File modifieddeleted- File/folder trashed
Asset Management
Assets are uploaded to Drive as binary files:
- Upload: Asset data sent via multipart upload
- URL Generation: Drive provides temporary webContentLink
- Caching: URLs cached for performance
- Cleanup: Orphaned assets detected and cleaned
Conflict Resolution
When conflicts occur (local vs Drive):
- Timestamp check: Most recent wins
- Manual resolve: User prompted if conflicts persist
- 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:
| Field | Type | Description |
|---|---|---|
connected | boolean | True when user has stored Google access token |
configured | boolean | True when Google OAuth is configured on server |
has_access_token | boolean | Whether user has valid tokens |
auth_provider | string | OAuth provider (e.g., “google”) |
token_expires | string | ISO 8601 token expiration timestamp |
upgrade_url | string | URL 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:
| Field | Type | Description |
|---|---|---|
server_configured | boolean | True when Google OAuth is configured on server |
user_has_tokens | boolean | Whether user has Drive tokens |
is_active_provider | boolean | True when Drive is the active storage provider |
root_folder_id | string | Drive folder ID used as project root |
root_folder_name | string | Display name of the root folder |
connected_at | string | ISO 8601 timestamp when connected |
connected_by | string | User ID who connected |
login_url | string | URL to sign in with Google |
upgrade_url | string | URL 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
parent_id | string | null | Parent folder ID (omit for root) |
page_token | string | null | Pagination token |
page_size | integer | 50 | Max 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:
| Field | Type | Required | Description |
|---|---|---|---|
folder_id | string | Yes | Google Drive folder ID |
folder_name | string | No | Display 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:
| Field | Type | Required | Description |
|---|---|---|---|
access_token | string | No | Google OAuth access token (fallback to user tokens) |
refresh_token | string | No | Google OAuth refresh token |
token_expires | string | No | ISO 8601 expiration timestamp |
root_folder_id | string | Yes | Google Drive folder ID |
root_folder_name | string | No | Display 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:
| Field | Type | Description |
|---|---|---|
sync_worker | object | Worker statistics (null if not running) |
desktop_presence | object | Whether desktop client is online |
token_health | object | OAuth 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | null | Drive API query string |
folder_id | string | null | Restrict to folder ID |
page_token | string | null | Pagination token |
page_size | integer | 20 | Max 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:
| Parameter | Type | Description |
|---|---|---|
file_id | string | Google 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:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Document title |
content | string | Yes | Plain-text or Markdown content |
folder_id | string | No | Optional 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:
| Parameter | Type | Description |
|---|---|---|
file_id | string | Google 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:
| Parameter | Type | Description |
|---|---|---|
file_id | string | Google Drive file ID |
Request Body:
{
"email": "colleague@example.com",
"role": "writer"
}Request Body Fields:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Recipient email address |
role | string | No | Default: “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:
- Verify Client ID and Secret in Google Cloud Console
- Add StudioBrain’s redirect URI to authorized list
- 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:
- Reconnect Google Drive and select the correct folder
- Verify Drive folder still exists
- 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:
- Check network connectivity
- Review Drive API quota in Google Cloud Console
- Verify entity content is valid markdown
- 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:
- Reconnect Google Drive (re-authorize)
- Verify Client credentials haven’t changed
- 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:
- Re-authenticate:
GET /api/auth/oauth/google/drive - Verify Drive API is enabled in Google Cloud Console
- 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
- Use dedicated folder: Create a separate Drive folder for StudioBrain
- Limit scope: Drive API scope is limited to StudioBrain files only
- Monitor quota: Watch Drive API usage in Google Cloud Console
- Regular backups: Enable Drive version history
- Test connection: Use
POST /api/drive-storage/testregularly
Related Documentation
- Cloud Sync - Overview of sync features
- Self-Hosting - Drive integration on self-hosted
- Google Drive API Docs - Official Google Drive API