Granola uses WorkOS for authentication with refresh token rotation.
Authentication Flow:
Initial Authentication
Requires refresh_token from WorkOS authentication flow
Requires client_id to identify the application to WorkOS
Access Token Exchange
Refresh token is exchanged for short-lived access_token via WorkOS /user_management/authenticate endpoint
Request: client_id, grant_type: "refresh_token", current refresh_token
Response: new access_token, rotated refresh_token, expires_in (3600 seconds)
Token Rotation (IMPORTANT)
Refresh tokens CANNOT be reused - each token is valid for ONE use only
Each exchange automatically invalidates the old refresh token and issues a new one
You MUST save and use the new refresh token from each response for the next request
Attempting to reuse an old refresh token will result in authentication failure
This rotation mechanism prevents token replay attacks
Access tokens expire after 1 hour
main.py - Document fetching and conversion logic (includes workspace, folder, and batch fetching)
token_manager.py - OAuth token management and refresh
list_workspaces.py - List all available workspaces (organizations)
list_folders.py - List all document lists (folders)
filter_by_workspace.py - Filter and organize documents by workspace
filter_by_folder.py - Filter and organize documents by folder
GETTING_REFRESH_TOKEN.md - Method to extract tokens from Granola app
Exchanges a refresh token for a new access token using WorkOS authentication.
Endpoint: POST https://api.workos.com/user_management/authenticate
Request Body:
{
"client_id": "string", // WorkOS client ID"grant_type": "refresh_token", // OAuth 2.0 grant type"refresh_token": "string"// Current refresh token
}
Response:
{
"access_token": "string", // New JWT access token"refresh_token": "string", // New refresh token (rotated - MUST be saved for next use)"expires_in": 3600, // Token lifetime in seconds"token_type": "Bearer"
}
IMPORTANT - Refresh Token Rotation:
The refresh_token in the response is a NEW token that replaces the old one
The old refresh token is immediately invalidated and CANNOT be reused
You MUST save this new refresh token and use it for the next authentication request
Failure to update the refresh token will cause subsequent authentication attempts to fail
This is a security feature called "refresh token rotation" that prevents token replay attacks
Retrieves a paginated list of user's Granola documents.
Endpoint: POST https://api.granola.ai/v2/get-documents
[
{
"id": "string", // List unique identifier"name": "string", // List/folder name (v1)"title": "string", // List/folder name (v2)"created_at": "ISO8601", // Creation timestamp"workspace_id": "string", // Workspace this list belongs to"owner_id": "string", // Owner user ID"documents": [ // Document objects in this list (v2)
{"id": "doc_id1", ...}
],
"document_ids": ["doc_id1", "..."], // Document IDs in this list (v1)"is_favourite": false// Whether user favourited this list
}
]
Notes:
Document lists are the folder system in Granola
A document can belong to multiple lists
Lists are workspace-specific
Try v2 endpoint first, fallback to v1 if not available
Response format differs slightly between v1 and v2
Fetch multiple documents by their IDs. This is the most reliable way to fetch documents from folders, especially shared documents.
Endpoint: POST https://api.granola.ai/v1/get-documents-batch