google-workspace
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGoogle 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
undefinedbash
undefinedInstall 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
Or: curl https://sdk.cloud.google.com | bash
Or: curl https://sdk.cloud.google.com | bash
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
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
undefinedgcloud 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
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
undefinedStep 2: Install Python client library
步骤2:安装Python客户端库
bash
pip install --upgrade \
google-api-python-client \
google-auth-httplib2 \
google-auth-oauthlibbash
pip install --upgrade \
google-api-python-client \
google-auth-httplib2 \
google-auth-oauthlibStep 3: Authenticate
步骤3:身份验证
bash
undefinedbash
undefinedOAuth2 — 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:
Scope:
https://docs.googleapis.com/v1https://www.googleapis.com/auth/documentspython
from googleapiclient.discovery import build
docs = build('docs', 'v1', credentials=creds)接口地址:
权限范围:
https://docs.googleapis.com/v1https://www.googleapis.com/auth/documentspython
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:
Scope:
https://sheets.googleapis.com/v4https://www.googleapis.com/auth/spreadsheetspython
sheets = build('sheets', 'v4', credentials=creds)
ss = sheets.spreadsheets()接口地址:
权限范围:
https://sheets.googleapis.com/v4https://www.googleapis.com/auth/spreadsheetspython
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:
Scope:
https://slides.googleapis.com/v1https://www.googleapis.com/auth/presentationspython
slides = build('slides', 'v1', credentials=creds)接口地址:
权限范围:
https://slides.googleapis.com/v1https://www.googleapis.com/auth/presentationspython
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:
Scope:
https://www.googleapis.com/drive/v3https://www.googleapis.com/auth/drivepython
drive = build('drive', 'v3', credentials=creds)接口地址:
权限范围:
https://www.googleapis.com/drive/v3https://www.googleapis.com/auth/drivepython
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:
Scope:
https://gmail.googleapis.com/gmail/v1https://www.googleapis.com/auth/gmail.modifypython
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/v1https://www.googleapis.com/auth/gmail.modifypython
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:
Scope:
https://www.googleapis.com/calendar/v3https://www.googleapis.com/auth/calendarpython
from datetime import datetime, timedelta
import pytz
calendar = build('calendar', 'v3', credentials=creds)接口地址:
权限范围:
https://www.googleapis.com/calendar/v3https://www.googleapis.com/auth/calendarpython
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:
Scope:
https://chat.googleapis.com/v1https://www.googleapis.com/auth/chat.messagespython
chat = build('chat', 'v1', credentials=creds)接口地址:
权限范围:
https://chat.googleapis.com/v1https://www.googleapis.com/auth/chat.messagespython
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:
Scope:
https://forms.googleapis.com/v1https://www.googleapis.com/auth/forms.bodypython
forms = build('forms', 'v1', credentials=creds)接口地址:
权限范围:
https://forms.googleapis.com/v1https://www.googleapis.com/auth/forms.bodypython
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:
Scope:
Requires: Service account with domain-wide delegation
https://admin.googleapis.comhttps://www.googleapis.com/auth/admin.directory.userpython
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.comhttps://www.googleapis.com/auth/admin.directory.userpython
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:
Scope:
https://script.googleapis.com/v1https://www.googleapis.com/auth/script.projectspython
script = build('script', 'v1', credentials=creds)接口地址:
权限范围:
https://script.googleapis.com/v1https://www.googleapis.com/auth/script.projectspython
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_idpython
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_idPattern 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_idpython
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_idPattern 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
速率限制与最佳实践
| API | Quota | Retry Strategy |
|---|---|---|
| Docs API | 300 req/min/user | Exponential backoff on 429 |
| Sheets API | 300 req/min | Batch operations reduce quota usage |
| Drive API | 1,000 req/100 sec | Use |
| Gmail API | 250 quota units/user/sec | |
| Calendar API | 1,000,000 req/day | Use |
| Admin SDK | 10 user creates/domain/sec | Add |
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 API | 300次请求/分钟/用户 | 遇到429错误时使用指数退避重试 |
| Sheets API | 300次请求/分钟 | 批量操作可减少配额消耗 |
| Drive API | 1000次请求/100秒 | 使用 |
| Gmail API | 250配额单位/用户/秒 | 批量操作使用 |
| Calendar API | 1,000,000次请求/天 | 使用 |
| Admin SDK | 10个用户创建/域/秒 | 创建用户之间添加 |
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:
raiseScopes Reference
权限范围参考
| Product | Read Scope | Write Scope |
|---|---|---|
| Docs | | |
| Sheets | | |
| Slides | | |
| Drive | | |
| Gmail | | |
| Calendar | | |
| Chat | | |
| Forms | | |
| Admin SDK | | |
| 产品 | 只读权限 | 读写权限 |
|---|---|---|
| Docs | | |
| Sheets | | |
| Slides | | |
| Drive | | |
| Gmail | | |
| Calendar | | |
| Chat | | |
| Forms | | |
| Admin SDK | | |
References
参考资料
- Google Workspace Developer Hub
- Google Docs API Reference
- Google Sheets API Reference
- Google Slides API Reference
- Google Drive API v3 Reference
- Gmail API Reference
- Google Calendar API Reference
- Google Chat API Reference
- Google Forms API Reference
- Admin SDK Directory API Reference
- Apps Script REST API
- Auth Overview & Credentials Setup
- Enable APIs Guide
- Google Workspace Developer Hub
- Google Docs API Reference
- Google Sheets API Reference
- Google Slides API Reference
- Google Drive API v3 Reference
- Gmail API Reference
- Google Calendar API Reference
- Google Chat API Reference
- Google Forms API Reference
- Admin SDK Directory API Reference
- Apps Script REST API
- Auth Overview & Credentials Setup
- Enable APIs Guide