google-workspace

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Google Workspace

Google Workspace

Comprehensive AI agent skill for all Google Workspace document operations — Docs, Sheets, Slides, Drive, Gmail, Calendar, Chat, Forms, Admin SDK, and Apps Script — via official REST APIs.
这是适用于所有Google Workspace文档操作的综合AI Agent技能,可通过官方REST API操作Docs、Sheets、Slides、Drive、Gmail、Calendar、Chat、Forms、Admin SDK和Apps Script。

When to use this skill

何时使用该技能

  • Creating or editing Google Docs, Sheets, Slides
  • Uploading, downloading, organizing Google Drive files and folders
  • Sending/reading Gmail, managing labels and drafts
  • Creating calendar events, inviting attendees, checking availability
  • Posting Google Chat messages, managing spaces
  • Building and reading Google Forms/surveys
  • Provisioning/managing Google Workspace users (Admin SDK)
  • Running automated workflows via Apps Script
  • 创建或编辑Google Docs、Sheets、Slides
  • 上传、下载、整理Google Drive文件和文件夹
  • 发送/读取Gmail,管理标签和草稿
  • 创建日历事件、邀请参会人、查看可用时间
  • 发送Google Chat消息、管理空间
  • 创建和收集Google Forms/问卷反馈
  • 配置/管理Google Workspace用户(Admin SDK)
  • 通过Apps Script运行自动化工作流

Quick Setup

快速配置

Step 1: Enable APIs in Google Cloud Console

步骤1:在Google Cloud Console中启用API

bash
undefined
bash
undefined

Install gcloud CLI (if not available)

Install gcloud CLI (if not available)

brew install --cask google-cloud-sdk # macOS
brew install --cask google-cloud-sdk # macOS

Enable all Workspace APIs

Enable all Workspace APIs

gcloud services enable docs.googleapis.com
sheets.googleapis.com slides.googleapis.com
drive.googleapis.com gmail.googleapis.com
calendar-json.googleapis.com chat.googleapis.com
forms.googleapis.com admin.googleapis.com
script.googleapis.com
undefined
gcloud services enable docs.googleapis.com
sheets.googleapis.com slides.googleapis.com
drive.googleapis.com gmail.googleapis.com
calendar-json.googleapis.com chat.googleapis.com
forms.googleapis.com admin.googleapis.com
script.googleapis.com
undefined

Step 2: Install Python client library

步骤2:安装Python客户端库

bash
pip install --upgrade \
  google-api-python-client \
  google-auth-httplib2 \
  google-auth-oauthlib
bash
pip install --upgrade \
  google-api-python-client \
  google-auth-httplib2 \
  google-auth-oauthlib

Step 3: Authenticate

步骤3:身份验证

bash
undefined
bash
undefined

OAuth2 — interactive user auth (for accessing user's own data)

OAuth2 — interactive user auth (for accessing user's own data)

bash scripts/auth-setup.sh --oauth2 credentials.json
bash scripts/auth-setup.sh --oauth2 credentials.json

Service Account — server-to-server (for automation/backend)

Service Account — server-to-server (for automation/backend)

bash scripts/auth-setup.sh --service-account service-account-key.json

---
bash scripts/auth-setup.sh --service-account service-account-key.json

---

API Reference by Product

各产品API参考

Google Docs

Google Docs

Endpoint:
https://docs.googleapis.com/v1
Scope:
https://www.googleapis.com/auth/documents
python
from googleapiclient.discovery import build

docs = build('docs', 'v1', credentials=creds)
接口地址:
https://docs.googleapis.com/v1
权限范围:
https://www.googleapis.com/auth/documents
python
from googleapiclient.discovery import build

docs = build('docs', 'v1', credentials=creds)

Create document

Create document

doc = docs.documents().create(body={'title': 'My Document'}).execute() doc_id = doc['documentId']
doc = docs.documents().create(body={'title': 'My Document'}).execute() doc_id = doc['documentId']

Read document

Read document

doc = docs.documents().get(documentId=doc_id).execute() content = doc.get('body', {}).get('content', [])
doc = docs.documents().get(documentId=doc_id).execute() content = doc.get('body', {}).get('content', [])

Edit: replace all text matching a pattern

Edit: replace all text matching a pattern

requests = [{ 'replaceAllText': { 'containsText': {'text': '{{name}}', 'matchCase': False}, 'replaceText': 'Alice' } }] docs.documents().batchUpdate(documentId=doc_id, body={'requests': requests}).execute()
requests = [{ 'replaceAllText': { 'containsText': {'text': '{{name}}', 'matchCase': False}, 'replaceText': 'Alice' } }] docs.documents().batchUpdate(documentId=doc_id, body={'requests': requests}).execute()

Insert text at position

Insert text at position

requests = [{'insertText': {'location': {'index': 1}, 'text': 'Hello!\n'}}] docs.documents().batchUpdate(documentId=doc_id, body={'requests': requests}).execute()

**Key batchUpdate operations**: `insertText`, `deleteContentRange`, `replaceAllText`, `updateTextStyle`, `updateParagraphStyle`, `insertTable`, `insertInlineImage`, `createHeader`, `createFooter`, `createNamedRange`

---
requests = [{'insertText': {'location': {'index': 1}, 'text': 'Hello!\n'}}] docs.documents().batchUpdate(documentId=doc_id, body={'requests': requests}).execute()

**核心batchUpdate操作**: `insertText`, `deleteContentRange`, `replaceAllText`, `updateTextStyle`, `updateParagraphStyle`, `insertTable`, `insertInlineImage`, `createHeader`, `createFooter`, `createNamedRange`

---

Google Sheets

Google Sheets

Endpoint:
https://sheets.googleapis.com/v4
Scope:
https://www.googleapis.com/auth/spreadsheets
python
sheets = build('sheets', 'v4', credentials=creds)
ss = sheets.spreadsheets()
接口地址:
https://sheets.googleapis.com/v4
权限范围:
https://www.googleapis.com/auth/spreadsheets
python
sheets = build('sheets', 'v4', credentials=creds)
ss = sheets.spreadsheets()

Create spreadsheet

Create spreadsheet

spreadsheet = ss.create(body={ 'properties': {'title': 'My Sheet'}, 'sheets': [{'properties': {'title': 'Data'}}] }).execute() sheet_id = spreadsheet['spreadsheetId']
spreadsheet = ss.create(body={ 'properties': {'title': 'My Sheet'}, 'sheets': [{'properties': {'title': 'Data'}}] }).execute() sheet_id = spreadsheet['spreadsheetId']

Write data

Write data

ss.values().update( spreadsheetId=sheet_id, range='Sheet1!A1', valueInputOption='USER_ENTERED', body={'values': [['Name', 'Score'], ['Alice', 95], ['Bob', 87]]} ).execute()
ss.values().update( spreadsheetId=sheet_id, range='Sheet1!A1', valueInputOption='USER_ENTERED', body={'values': [['Name', 'Score'], ['Alice', 95], ['Bob', 87]]} ).execute()

Read data

Read data

result = ss.values().get(spreadsheetId=sheet_id, range='Sheet1!A:B').execute() rows = result.get('values', [])
result = ss.values().get(spreadsheetId=sheet_id, range='Sheet1!A:B').execute() rows = result.get('values', [])

Append rows

Append rows

ss.values().append( spreadsheetId=sheet_id, range='Sheet1!A1', valueInputOption='USER_ENTERED', body={'values': [['Charlie', 91]]} ).execute()
ss.values().append( spreadsheetId=sheet_id, range='Sheet1!A1', valueInputOption='USER_ENTERED', body={'values': [['Charlie', 91]]} ).execute()

Batch update (format: freeze row 1, bold header)

Batch update (format: freeze row 1, bold header)

ss.batchUpdate(spreadsheetId=sheet_id, body={'requests': [ {'updateSheetProperties': { 'properties': {'sheetId': 0, 'gridProperties': {'frozenRowCount': 1}}, 'fields': 'gridProperties.frozenRowCount' }}, {'repeatCell': { 'range': {'sheetId': 0, 'startRowIndex': 0, 'endRowIndex': 1}, 'cell': {'userEnteredFormat': {'textFormat': {'bold': True}}}, 'fields': 'userEnteredFormat.textFormat.bold' }} ]}).execute()

---
ss.batchUpdate(spreadsheetId=sheet_id, body={'requests': [ {'updateSheetProperties': { 'properties': {'sheetId': 0, 'gridProperties': {'frozenRowCount': 1}}, 'fields': 'gridProperties.frozenRowCount' }}, {'repeatCell': { 'range': {'sheetId': 0, 'startRowIndex': 0, 'endRowIndex': 1}, 'cell': {'userEnteredFormat': {'textFormat': {'bold': True}}}, 'fields': 'userEnteredFormat.textFormat.bold' }} ]}).execute()

---

Google Slides

Google Slides

Endpoint:
https://slides.googleapis.com/v1
Scope:
https://www.googleapis.com/auth/presentations
python
slides = build('slides', 'v1', credentials=creds)
接口地址:
https://slides.googleapis.com/v1
权限范围:
https://www.googleapis.com/auth/presentations
python
slides = build('slides', 'v1', credentials=creds)

Create presentation

Create presentation

presentation = slides.presentations().create( body={'title': 'My Presentation'} ).execute() pres_id = presentation['presentationId']
presentation = slides.presentations().create( body={'title': 'My Presentation'} ).execute() pres_id = presentation['presentationId']

Read presentation

Read presentation

pres = slides.presentations().get(presentationId=pres_id).execute() slide_ids = [s['objectId'] for s in pres.get('slides', [])]
pres = slides.presentations().get(presentationId=pres_id).execute() slide_ids = [s['objectId'] for s in pres.get('slides', [])]

Add a new slide

Add a new slide

slides.presentations().batchUpdate(presentationId=pres_id, body={'requests': [ {'createSlide': { 'insertionIndex': 1, 'slideLayoutReference': {'predefinedLayout': 'TITLE_AND_BODY'} }} ]}).execute()
slides.presentations().batchUpdate(presentationId=pres_id, body={'requests': [ {'createSlide': { 'insertionIndex': 1, 'slideLayoutReference': {'predefinedLayout': 'TITLE_AND_BODY'} }} ]}).execute()

Replace placeholder text

Replace placeholder text

slides.presentations().batchUpdate(presentationId=pres_id, body={'requests': [ {'replaceAllText': { 'containsText': {'text': '{{title}}', 'matchCase': False}, 'replaceText': 'Q1 Report' }} ]}).execute()
slides.presentations().batchUpdate(presentationId=pres_id, body={'requests': [ {'replaceAllText': { 'containsText': {'text': '{{title}}', 'matchCase': False}, 'replaceText': 'Q1 Report' }} ]}).execute()

Get slide thumbnail

Get slide thumbnail

page_id = slide_ids[0] thumb = slides.presentations().pages().getThumbnail( presentationId=pres_id, pageObjectId=page_id, thumbnailProperties_thumbnailSize='LARGE' ).execute() image_url = thumb['contentUrl']

---
page_id = slide_ids[0] thumb = slides.presentations().pages().getThumbnail( presentationId=pres_id, pageObjectId=page_id, thumbnailProperties_thumbnailSize='LARGE' ).execute() image_url = thumb['contentUrl']

---

Google Drive

Google Drive

Endpoint:
https://www.googleapis.com/drive/v3
Scope:
https://www.googleapis.com/auth/drive
python
drive = build('drive', 'v3', credentials=creds)
接口地址:
https://www.googleapis.com/drive/v3
权限范围:
https://www.googleapis.com/auth/drive
python
drive = build('drive', 'v3', credentials=creds)

Create folder

Create folder

folder = drive.files().create(body={ 'name': 'My Folder', 'mimeType': 'application/vnd.google-apps.folder' }).execute() folder_id = folder['id']
folder = drive.files().create(body={ 'name': 'My Folder', 'mimeType': 'application/vnd.google-apps.folder' }).execute() folder_id = folder['id']

Upload file

Upload file

from googleapiclient.http import MediaFileUpload media = MediaFileUpload('report.pdf', mimetype='application/pdf') file = drive.files().create( body={'name': 'report.pdf', 'parents': [folder_id]}, media_body=media, fields='id' ).execute()
from googleapiclient.http import MediaFileUpload media = MediaFileUpload('report.pdf', mimetype='application/pdf') file = drive.files().create( body={'name': 'report.pdf', 'parents': [folder_id]}, media_body=media, fields='id' ).execute()

Search files

Search files

results = drive.files().list( q="name contains 'report' and mimeType='application/pdf'", fields='files(id, name, modifiedTime)' ).execute()
results = drive.files().list( q="name contains 'report' and mimeType='application/pdf'", fields='files(id, name, modifiedTime)' ).execute()

Share file

Share file

drive.permissions().create( fileId=file['id'], body={'type': 'user', 'role': 'reader', 'emailAddress': 'alice@example.com'}, sendNotificationEmail=True ).execute()
drive.permissions().create( fileId=file['id'], body={'type': 'user', 'role': 'reader', 'emailAddress': 'alice@example.com'}, sendNotificationEmail=True ).execute()

Export Google Doc to PDF

Export Google Doc to PDF

import io from googleapiclient.http import MediaIoBaseDownload request = drive.files().export_media(fileId=doc_id, mimeType='application/pdf') fh = io.BytesIO() downloader = MediaIoBaseDownload(fh, request) done = False while not done: _, done = downloader.next_chunk() with open('document.pdf', 'wb') as f: f.write(fh.getvalue())
import io from googleapiclient.http import MediaIoBaseDownload request = drive.files().export_media(fileId=doc_id, mimeType='application/pdf') fh = io.BytesIO() downloader = MediaIoBaseDownload(fh, request) done = False while not done: _, done = downloader.next_chunk() with open('document.pdf', 'wb') as f: f.write(fh.getvalue())

Move file

Move file

drive.files().update( fileId=file['id'], addParents=folder_id, removeParents='root', fields='id, parents' ).execute()
drive.files().update( fileId=file['id'], addParents=folder_id, removeParents='root', fields='id, parents' ).execute()

Copy file (e.g., from template)

Copy file (e.g., from template)

copy = drive.files().copy( fileId='TEMPLATE_FILE_ID', body={'name': 'New Document from Template', 'parents': [folder_id]} ).execute()

---
copy = drive.files().copy( fileId='TEMPLATE_FILE_ID', body={'name': 'New Document from Template', 'parents': [folder_id]} ).execute()

---

Gmail

Gmail

Endpoint:
https://gmail.googleapis.com/gmail/v1
Scope:
https://www.googleapis.com/auth/gmail.modify
python
import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

gmail = build('gmail', 'v1', credentials=creds)
接口地址:
https://gmail.googleapis.com/gmail/v1
权限范围:
https://www.googleapis.com/auth/gmail.modify
python
import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

gmail = build('gmail', 'v1', credentials=creds)

Send email

Send email

def send_email(to, subject, body): msg = MIMEText(body) msg['to'] = to msg['subject'] = subject raw = base64.urlsafe_b64encode(msg.as_bytes()).decode() gmail.users().messages().send(userId='me', body={'raw': raw}).execute()
send_email('alice@example.com', 'Hello', 'This is the body.')
def send_email(to, subject, body): msg = MIMEText(body) msg['to'] = to msg['subject'] = subject raw = base64.urlsafe_b64encode(msg.as_bytes()).decode() gmail.users().messages().send(userId='me', body={'raw': raw}).execute()
send_email('alice@example.com', 'Hello', 'This is the body.')

Send with attachment

Send with attachment

msg = MIMEMultipart() msg['to'] = 'alice@example.com' msg['subject'] = 'Report' msg.attach(MIMEText('Please find the report attached.')) with open('report.pdf', 'rb') as f: from email.mime.application import MIMEApplication part = MIMEApplication(f.read(), Name='report.pdf') part['Content-Disposition'] = 'attachment; filename="report.pdf"' msg.attach(part) raw = base64.urlsafe_b64encode(msg.as_bytes()).decode() gmail.users().messages().send(userId='me', body={'raw': raw}).execute()
msg = MIMEMultipart() msg['to'] = 'alice@example.com' msg['subject'] = 'Report' msg.attach(MIMEText('Please find the report attached.')) with open('report.pdf', 'rb') as f: from email.mime.application import MIMEApplication part = MIMEApplication(f.read(), Name='report.pdf') part['Content-Disposition'] = 'attachment; filename="report.pdf"' msg.attach(part) raw = base64.urlsafe_b64encode(msg.as_bytes()).decode() gmail.users().messages().send(userId='me', body={'raw': raw}).execute()

Search emails

Search emails

results = gmail.users().messages().list( userId='me', q='from:boss@company.com subject:urgent is:unread' ).execute()
results = gmail.users().messages().list( userId='me', q='from:boss@company.com subject:urgent is:unread' ).execute()

Read email

Read email

msg_id = results['messages'][0]['id'] msg = gmail.users().messages().get(userId='me', id=msg_id, format='full').execute() subject = next(h['value'] for h in msg['payload']['headers'] if h['name'] == 'Subject')
msg_id = results['messages'][0]['id'] msg = gmail.users().messages().get(userId='me', id=msg_id, format='full').execute() subject = next(h['value'] for h in msg['payload']['headers'] if h['name'] == 'Subject')

Create label and apply

Create label and apply

label = gmail.users().labels().create( userId='me', body={'name': 'AI-Processed'} ).execute() gmail.users().messages().modify( userId='me', id=msg_id, body={'addLabelIds': [label['id']], 'removeLabelIds': ['UNREAD']} ).execute()
label = gmail.users().labels().create( userId='me', body={'name': 'AI-Processed'} ).execute() gmail.users().messages().modify( userId='me', id=msg_id, body={'addLabelIds': [label['id']], 'removeLabelIds': ['UNREAD']} ).execute()

Create draft

Create draft

raw_draft = base64.urlsafe_b64encode(MIMEText('Draft body').as_bytes()).decode() gmail.users().drafts().create( userId='me', body={'message': {'raw': raw_draft}} ).execute()
raw_draft = base64.urlsafe_b64encode(MIMEText('Draft body').as_bytes()).decode() gmail.users().drafts().create( userId='me', body={'message': {'raw': raw_draft}} ).execute()

Set vacation responder

Set vacation responder

gmail.users().settings().updateVacation( userId='me', body={ 'enableAutoReply': True, 'responseSubject': 'Out of Office', 'responseBodyPlainText': 'I am OOO until Monday.', 'startTime': '1704067200000', # Unix ms 'endTime': '1704326400000' } ).execute()

---
gmail.users().settings().updateVacation( userId='me', body={ 'enableAutoReply': True, 'responseSubject': 'Out of Office', 'responseBodyPlainText': 'I am OOO until Monday.', 'startTime': '1704067200000', # Unix ms 'endTime': '1704326400000' } ).execute()

---

Google Calendar

Google Calendar

Endpoint:
https://www.googleapis.com/calendar/v3
Scope:
https://www.googleapis.com/auth/calendar
python
from datetime import datetime, timedelta
import pytz

calendar = build('calendar', 'v3', credentials=creds)
接口地址:
https://www.googleapis.com/calendar/v3
权限范围:
https://www.googleapis.com/auth/calendar
python
from datetime import datetime, timedelta
import pytz

calendar = build('calendar', 'v3', credentials=creds)

Create event

Create event

event = calendar.events().insert( calendarId='primary', body={ 'summary': 'Team Standup', 'description': 'Daily sync', 'start': {'dateTime': '2026-03-15T09:00:00+09:00', 'timeZone': 'Asia/Seoul'}, 'end': {'dateTime': '2026-03-15T09:30:00+09:00', 'timeZone': 'Asia/Seoul'}, 'attendees': [ {'email': 'alice@example.com'}, {'email': 'bob@example.com'}, ], 'conferenceData': { 'createRequest': {'requestId': 'meeting-001', 'conferenceSolutionKey': {'type': 'hangoutsMeet'}} }, 'recurrence': ['RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR'] }, conferenceDataVersion=1 ).execute() meet_link = event.get('hangoutLink')
event = calendar.events().insert( calendarId='primary', body={ 'summary': 'Team Standup', 'description': 'Daily sync', 'start': {'dateTime': '2026-03-15T09:00:00+09:00', 'timeZone': 'Asia/Seoul'}, 'end': {'dateTime': '2026-03-15T09:30:00+09:00', 'timeZone': 'Asia/Seoul'}, 'attendees': [ {'email': 'alice@example.com'}, {'email': 'bob@example.com'}, ], 'conferenceData': { 'createRequest': {'requestId': 'meeting-001', 'conferenceSolutionKey': {'type': 'hangoutsMeet'}} }, 'recurrence': ['RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR'] }, conferenceDataVersion=1 ).execute() meet_link = event.get('hangoutLink')

List today's events

List today's events

now = datetime.utcnow().isoformat() + 'Z' end_of_day = (datetime.utcnow() + timedelta(hours=24)).isoformat() + 'Z' events_result = calendar.events().list( calendarId='primary', timeMin=now, timeMax=end_of_day, singleEvents=True, orderBy='startTime' ).execute() events = events_result.get('items', [])
now = datetime.utcnow().isoformat() + 'Z' end_of_day = (datetime.utcnow() + timedelta(hours=24)).isoformat() + 'Z' events_result = calendar.events().list( calendarId='primary', timeMin=now, timeMax=end_of_day, singleEvents=True, orderBy='startTime' ).execute() events = events_result.get('items', [])

Check free/busy

Check free/busy

body = { 'timeMin': now, 'timeMax': end_of_day, 'items': [{'id': 'alice@example.com'}, {'id': 'bob@example.com'}] } freebusy = calendar.freebusy().query(body=body).execute()
body = { 'timeMin': now, 'timeMax': end_of_day, 'items': [{'id': 'alice@example.com'}, {'id': 'bob@example.com'}] } freebusy = calendar.freebusy().query(body=body).execute()

Block time / set OOO

Block time / set OOO

calendar.events().insert( calendarId='primary', body={ 'summary': 'Out of Office', 'eventType': 'outOfOffice', 'start': {'date': '2026-03-20'}, 'end': {'date': '2026-03-22'} } ).execute()
calendar.events().insert( calendarId='primary', body={ 'summary': 'Out of Office', 'eventType': 'outOfOffice', 'start': {'date': '2026-03-20'}, 'end': {'date': '2026-03-22'} } ).execute()

Share calendar

Share calendar

calendar.acl().insert( calendarId='primary', body={'role': 'reader', 'scope': {'type': 'user', 'value': 'alice@example.com'}} ).execute()

---
calendar.acl().insert( calendarId='primary', body={'role': 'reader', 'scope': {'type': 'user', 'value': 'alice@example.com'}} ).execute()

---

Google Chat

Google Chat

Endpoint:
https://chat.googleapis.com/v1
Scope:
https://www.googleapis.com/auth/chat.messages
python
chat = build('chat', 'v1', credentials=creds)
接口地址:
https://chat.googleapis.com/v1
权限范围:
https://www.googleapis.com/auth/chat.messages
python
chat = build('chat', 'v1', credentials=creds)

Send message to a space

Send message to a space

space_name = 'spaces/SPACE_ID' # From Chat URL chat.spaces().messages().create( parent=space_name, body={ 'text': 'Hello from AI agent! 🤖', 'cards_v2': [{ 'cardId': 'card1', 'card': { 'header': {'title': 'Update', 'subtitle': 'Automated report'}, 'sections': [{'widgets': [{'textParagraph': {'text': 'Task completed.'}}]}] } }] } ).execute()
space_name = 'spaces/SPACE_ID' # From Chat URL chat.spaces().messages().create( parent=space_name, body={ 'text': 'Hello from AI agent! 🤖', 'cards_v2': [{ 'cardId': 'card1', 'card': { 'header': {'title': 'Update', 'subtitle': 'Automated report'}, 'sections': [{'widgets': [{'textParagraph': {'text': 'Task completed.'}}]}] } }] } ).execute()

Create a new space

Create a new space

space = chat.spaces().create( body={ 'spaceType': 'SPACE', 'displayName': 'Project Alpha' } ).execute()
space = chat.spaces().create( body={ 'spaceType': 'SPACE', 'displayName': 'Project Alpha' } ).execute()

List spaces

List spaces

spaces = chat.spaces().list().execute()
spaces = chat.spaces().list().execute()

Add member to space

Add member to space

chat.spaces().members().create( parent=space['name'], body={'member': {'name': 'users/alice@example.com', 'type': 'HUMAN'}} ).execute()
chat.spaces().members().create( parent=space['name'], body={'member': {'name': 'users/alice@example.com', 'type': 'HUMAN'}} ).execute()

Find or create direct message

Find or create direct message

dm = chat.spaces().findDirectMessage(name='users/alice@example.com').execute()

---
dm = chat.spaces().findDirectMessage(name='users/alice@example.com').execute()

---

Google Forms

Google Forms

Endpoint:
https://forms.googleapis.com/v1
Scope:
https://www.googleapis.com/auth/forms.body
python
forms = build('forms', 'v1', credentials=creds)
接口地址:
https://forms.googleapis.com/v1
权限范围:
https://www.googleapis.com/auth/forms.body
python
forms = build('forms', 'v1', credentials=creds)

Create form

Create form

form = forms.forms().create(body={ 'info': {'title': 'Customer Feedback Survey', 'documentTitle': 'Customer Feedback'} }).execute() form_id = form['formId']
form = forms.forms().create(body={ 'info': {'title': 'Customer Feedback Survey', 'documentTitle': 'Customer Feedback'} }).execute() form_id = form['formId']

Add questions

Add questions

forms.forms().batchUpdate(formId=form_id, body={'requests': [ { 'createItem': { 'item': { 'title': 'How satisfied are you?', 'questionItem': { 'question': { 'required': True, 'scaleQuestion': { 'low': 1, 'high': 5, 'lowLabel': 'Not satisfied', 'highLabel': 'Very satisfied' } } } }, 'location': {'index': 0} } }, { 'createItem': { 'item': { 'title': 'Any comments?', 'questionItem': { 'question': { 'required': False, 'textQuestion': {'paragraph': True} } } }, 'location': {'index': 1} } } ]}).execute()
forms.forms().batchUpdate(formId=form_id, body={'requests': [ { 'createItem': { 'item': { 'title': 'How satisfied are you?', 'questionItem': { 'question': { 'required': True, 'scaleQuestion': { 'low': 1, 'high': 5, 'lowLabel': 'Not satisfied', 'highLabel': 'Very satisfied' } } } }, 'location': {'index': 0} } }, { 'createItem': { 'item': { 'title': 'Any comments?', 'questionItem': { 'question': { 'required': False, 'textQuestion': {'paragraph': True} } } }, 'location': {'index': 1} } } ]}).execute()

Get form responses

Get form responses

responses = forms.forms().responses().list(formId=form_id).execute() for r in responses.get('responses', []): for qid, ans in r.get('answers', {}).items(): print(qid, ans.get('textAnswers', {}).get('answers', []))

---
responses = forms.forms().responses().list(formId=form_id).execute() for r in responses.get('responses', []): for qid, ans in r.get('answers', {}).items(): print(qid, ans.get('textAnswers', {}).get('answers', []))

---

Admin SDK — Directory API

Admin SDK — Directory API

Endpoint:
https://admin.googleapis.com
Scope:
https://www.googleapis.com/auth/admin.directory.user
Requires: Service account with domain-wide delegation
python
from google.oauth2 import service_account

SA_FILE = 'service-account.json'
SCOPES  = ['https://www.googleapis.com/auth/admin.directory.user',
           'https://www.googleapis.com/auth/admin.directory.group']
creds = service_account.Credentials.from_service_account_file(
    SA_FILE, scopes=SCOPES
).with_subject('admin@yourdomain.com')

admin = build('admin', 'directory_v1', credentials=creds)
接口地址:
https://admin.googleapis.com
权限范围:
https://www.googleapis.com/auth/admin.directory.user
前置要求: 配置了全域权限委托的服务账号
python
from google.oauth2 import service_account

SA_FILE = 'service-account.json'
SCOPES  = ['https://www.googleapis.com/auth/admin.directory.user',
           'https://www.googleapis.com/auth/admin.directory.group']
creds = service_account.Credentials.from_service_account_file(
    SA_FILE, scopes=SCOPES
).with_subject('admin@yourdomain.com')

admin = build('admin', 'directory_v1', credentials=creds)

Create user

Create user

admin.users().insert(body={ 'primaryEmail': 'newuser@yourdomain.com', 'name': {'givenName': 'New', 'familyName': 'User'}, 'password': 'TemporaryPassword123!', 'changePasswordAtNextLogin': True }).execute()
admin.users().insert(body={ 'primaryEmail': 'newuser@yourdomain.com', 'name': {'givenName': 'New', 'familyName': 'User'}, 'password': 'TemporaryPassword123!', 'changePasswordAtNextLogin': True }).execute()

List users

List users

users_result = admin.users().list(domain='yourdomain.com', maxResults=100).execute() for user in users_result.get('users', []): print(user['primaryEmail'], user.get('suspended', False))
users_result = admin.users().list(domain='yourdomain.com', maxResults=100).execute() for user in users_result.get('users', []): print(user['primaryEmail'], user.get('suspended', False))

Suspend user

Suspend user

admin.users().update( userKey='user@yourdomain.com', body={'suspended': True} ).execute()
admin.users().update( userKey='user@yourdomain.com', body={'suspended': True} ).execute()

Add user to group

Add user to group

admin.members().insert( groupKey='team@yourdomain.com', body={'email': 'user@yourdomain.com', 'role': 'MEMBER'} ).execute()
admin.members().insert( groupKey='team@yourdomain.com', body={'email': 'user@yourdomain.com', 'role': 'MEMBER'} ).execute()

List groups

List groups

groups = admin.groups().list(domain='yourdomain.com').execute()

---
groups = admin.groups().list(domain='yourdomain.com').execute()

---

Apps Script API

Apps Script API

Endpoint:
https://script.googleapis.com/v1
Scope:
https://www.googleapis.com/auth/script.projects
python
script = build('script', 'v1', credentials=creds)
接口地址:
https://script.googleapis.com/v1
权限范围:
https://www.googleapis.com/auth/script.projects
python
script = build('script', 'v1', credentials=creds)

Run a deployed function

Run a deployed function

response = script.scripts().run( scriptId='DEPLOYED_SCRIPT_ID', body={ 'function': 'myFunction', 'parameters': ['arg1', 42] } ).execute() result = response.get('response', {}).get('result')

---
response = script.scripts().run( scriptId='DEPLOYED_SCRIPT_ID', body={ 'function': 'myFunction', 'parameters': ['arg1', 42] } ).execute() result = response.get('response', {}).get('result')

---

Common Automation Patterns

常见自动化模式

Pattern 1: Create Document from Template

模式1:从模板创建文档

python
def create_doc_from_template(drive, docs, template_id, replacements, dest_folder_id=None):
    """Clone a template Google Doc and fill in placeholders."""
    body = {'name': replacements.get('{{title}}', 'New Document')}
    if dest_folder_id:
        body['parents'] = [dest_folder_id]
    copy = drive.files().copy(fileId=template_id, body=body).execute()
    new_id = copy['id']
    requests = [
        {'replaceAllText': {'containsText': {'text': k, 'matchCase': False}, 'replaceText': v}}
        for k, v in replacements.items()
    ]
    if requests:
        docs.documents().batchUpdate(documentId=new_id, body={'requests': requests}).execute()
    return new_id
python
def create_doc_from_template(drive, docs, template_id, replacements, dest_folder_id=None):
    """Clone a template Google Doc and fill in placeholders."""
    body = {'name': replacements.get('{{title}}', 'New Document')}
    if dest_folder_id:
        body['parents'] = [dest_folder_id]
    copy = drive.files().copy(fileId=template_id, body=body).execute()
    new_id = copy['id']
    requests = [
        {'replaceAllText': {'containsText': {'text': k, 'matchCase': False}, 'replaceText': v}}
        for k, v in replacements.items()
    ]
    if requests:
        docs.documents().batchUpdate(documentId=new_id, body={'requests': requests}).execute()
    return new_id

Pattern 2: Bulk Append to Spreadsheet

模式2:批量追加数据到电子表格

python
def bulk_append_rows(sheets, spreadsheet_id, sheet_name, rows):
    """Append multiple rows to a sheet in one API call."""
    sheets.spreadsheets().values().append(
        spreadsheetId=spreadsheet_id,
        range=f'{sheet_name}!A1',
        valueInputOption='USER_ENTERED',
        insertDataOption='INSERT_ROWS',
        body={'values': rows}
    ).execute()
python
def bulk_append_rows(sheets, spreadsheet_id, sheet_name, rows):
    """Append multiple rows to a sheet in one API call."""
    sheets.spreadsheets().values().append(
        spreadsheetId=spreadsheet_id,
        range=f'{sheet_name}!A1',
        valueInputOption='USER_ENTERED',
        insertDataOption='INSERT_ROWS',
        body={'values': rows}
    ).execute()

Pattern 3: Create Meeting Notes Document

模式3:创建会议纪要文档

python
def create_meeting_notes(calendar, drive, docs, event_id):
    """Create a Google Doc for meeting notes and share with attendees."""
    event = calendar.events().get(calendarId='primary', eventId=event_id).execute()
    attendees = [a['email'] for a in event.get('attendees', [])]
    title = f"Meeting Notes: {event['summary']}{event['start'].get('dateTime', event['start'].get('date'))}"
    doc = docs.documents().create(body={'title': title}).execute()
    doc_id = doc['documentId']
    for email in attendees:
        drive.permissions().create(
            fileId=doc_id,
            body={'type': 'user', 'role': 'writer', 'emailAddress': email},
            sendNotificationEmail=True
        ).execute()
    return doc_id
python
def create_meeting_notes(calendar, drive, docs, event_id):
    """Create a Google Doc for meeting notes and share with attendees."""
    event = calendar.events().get(calendarId='primary', eventId=event_id).execute()
    attendees = [a['email'] for a in event.get('attendees', [])]
    title = f"Meeting Notes: {event['summary']}{event['start'].get('dateTime', event['start'].get('date'))}"
    doc = docs.documents().create(body={'title': title}).execute()
    doc_id = doc['documentId']
    for email in attendees:
        drive.permissions().create(
            fileId=doc_id,
            body={'type': 'user', 'role': 'writer', 'emailAddress': email},
            sendNotificationEmail=True
        ).execute()
    return doc_id

Pattern 4: Form Response to Sheet

模式4:表单响应同步到电子表格

python
def sync_form_to_sheet(forms, sheets, form_id, spreadsheet_id):
    """Sync all form responses to a Google Sheet."""
    responses = forms.forms().responses().list(formId=form_id).execute()
    form_data = forms.forms().get(formId=form_id).execute()
    questions = {
        item['itemId']: item.get('title', '')
        for item in form_data.get('items', [])
        if 'questionItem' in item
    }
    headers = ['Timestamp'] + list(questions.values())
    rows = [headers]
    for resp in responses.get('responses', []):
        row = [resp.get('createTime', '')]
        for qid in questions:
            ans = resp.get('answers', {}).get(qid, {})
            text_ans = ans.get('textAnswers', {}).get('answers', [{}])
            row.append(text_ans[0].get('value', '') if text_ans else '')
        rows.append(row)
    sheets.spreadsheets().values().update(
        spreadsheetId=spreadsheet_id,
        range='Sheet1!A1',
        valueInputOption='USER_ENTERED',
        body={'values': rows}
    ).execute()

python
def sync_form_to_sheet(forms, sheets, form_id, spreadsheet_id):
    """Sync all form responses to a Google Sheet."""
    responses = forms.forms().responses().list(formId=form_id).execute()
    form_data = forms.forms().get(formId=form_id).execute()
    questions = {
        item['itemId']: item.get('title', '')
        for item in form_data.get('items', [])
        if 'questionItem' in item
    }
    headers = ['Timestamp'] + list(questions.values())
    rows = [headers]
    for resp in responses.get('responses', []):
        row = [resp.get('createTime', '')]
        for qid in questions:
            ans = resp.get('answers', {}).get(qid, {})
            text_ans = ans.get('textAnswers', {}).get('answers', [{}])
            row.append(text_ans[0].get('value', '') if text_ans else '')
        rows.append(row)
    sheets.spreadsheets().values().update(
        spreadsheetId=spreadsheet_id,
        range='Sheet1!A1',
        valueInputOption='USER_ENTERED',
        body={'values': rows}
    ).execute()

Rate Limits & Best Practices

速率限制与最佳实践

APIQuotaRetry Strategy
Docs API300 req/min/userExponential backoff on 429
Sheets API300 req/minBatch operations reduce quota usage
Drive API1,000 req/100 secUse
fields
param to reduce payload
Gmail API250 quota units/user/sec
batchModify
for bulk operations
Calendar API1,000,000 req/dayUse
timeMin
/
timeMax
to limit list results
Admin SDK10 user creates/domain/secAdd
time.sleep(0.15)
between creates
python
import time
from googleapiclient.errors import HttpError

def api_call_with_retry(func, *args, max_retries=5, **kwargs):
    """Wrapper that retries on 429/503 with exponential backoff."""
    for attempt in range(max_retries):
        try:
            return func(*args, **kwargs).execute()
        except HttpError as e:
            if e.resp.status in (429, 503) and attempt < max_retries - 1:
                wait = (2 ** attempt) + 0.1
                print(f"Rate limit hit, waiting {wait:.1f}s...")
                time.sleep(wait)
            else:
                raise

API配额重试策略
Docs API300次请求/分钟/用户遇到429错误时使用指数退避重试
Sheets API300次请求/分钟批量操作可减少配额消耗
Drive API1000次请求/100秒使用
fields
参数减小返回负载
Gmail API250配额单位/用户/秒批量操作使用
batchModify
接口
Calendar API1,000,000次请求/天使用
timeMin
/
timeMax
限制列表返回结果
Admin SDK10个用户创建/域/秒创建用户之间添加
time.sleep(0.15)
延迟
python
import time
from googleapiclient.errors import HttpError

def api_call_with_retry(func, *args, max_retries=5, **kwargs):
    """Wrapper that retries on 429/503 with exponential backoff."""
    for attempt in range(max_retries):
        try:
            return func(*args, **kwargs).execute()
        except HttpError as e:
            if e.resp.status in (429, 503) and attempt < max_retries - 1:
                wait = (2 ** attempt) + 0.1
                print(f"Rate limit hit, waiting {wait:.1f}s...")
                time.sleep(wait)
            else:
                raise

Scopes Reference

权限范围参考

ProductRead ScopeWrite Scope
Docs
auth/documents.readonly
auth/documents
Sheets
auth/spreadsheets.readonly
auth/spreadsheets
Slides
auth/presentations.readonly
auth/presentations
Drive
auth/drive.readonly
auth/drive
Gmail
auth/gmail.readonly
auth/gmail.modify
Calendar
auth/calendar.readonly
auth/calendar
Chat
auth/chat.messages.readonly
auth/chat.messages
Forms
auth/forms.body.readonly
auth/forms.body
Admin SDK
auth/admin.directory.user.readonly
auth/admin.directory.user

产品只读权限读写权限
Docs
auth/documents.readonly
auth/documents
Sheets
auth/spreadsheets.readonly
auth/spreadsheets
Slides
auth/presentations.readonly
auth/presentations
Drive
auth/drive.readonly
auth/drive
Gmail
auth/gmail.readonly
auth/gmail.modify
Calendar
auth/calendar.readonly
auth/calendar
Chat
auth/chat.messages.readonly
auth/chat.messages
Forms
auth/forms.body.readonly
auth/forms.body
Admin SDK
auth/admin.directory.user.readonly
auth/admin.directory.user

References

参考资料