I'm coding a Python app to automatize invoices via a google docs API but I'm having errors with the code and I don't know how to solve it
# [START docs_quickstart]
from __future__ import print_function
import os.path
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/documents.readonly','https://www.googleapis.com/auth/documents','https://www.googleapis.com/auth/drive.file','https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.readonly']
def main():
"""Shows basic usage of the Docs API.
Prints the title of a sample document.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('docs', 'v1', credentials=creds)
title = 'My Document'
body = {
'title': title
}
document = service.documents().create(body=body).execute()
print('Created document with title: {0}'.format(
document.get('title')))
except HttpError as err:
print(err)
if __name__ == '__main__':
main()
# [END docs_quickstart]
and this is the error code that I'm having
PS D:\Universidad\Proyectos de Programacion Propia\python\googledocsinvoice.restapi> python quickstart.py
<HttpError 403 when requesting https://docs.googleapis.com/v1/documents?alt=json returned "Request had insufficient authentication scopes.". Details: "[{'#type': 'type.googleapis.com/google.rpc.ErrorInfo', 'reason': 'ACCESS_TOKEN_SCOPE_INSUFFICIENT', 'domain': 'googleapis.com', 'metadata': {'service': 'docs.googleapis.com', 'method': 'google.apps.docs.v1.DocumentsService.CreateDocument'}}]">
if you know some guide or complete tutorial to Automate Document Creation with the Google Docs API like invoices and replace encapsulation values like {{productID}} I will be very grateful
I saw the Automate document creation of google channel but it wasn't very helpful https://youtu.be/-dX-fWb3ogE
Best Regards
Make sure you also enable the Docs API in your Developers Console.
Delete the credential file ~/.credentials.json and token.json (if you ran the code before
Change the scope variable used for reading docs
var SCOPES = ['https://www.googleapis.com/auth/documents.readonly'];
to
var SCOPES = ['https://www.googleapis.com/auth/documents'];
Check more info on https://developers.google.com/docs/api/reference/rest/v1/documents/create#authorization-scopes and https://developers.google.com/docs/api/how-tos/authorizing
After the execution of code, API will authenticate again and then the issue should be resolved.
Related
I'm running the quickstart code from https://developers.google.com/people/quickstart/python in a colab notebook.
# \[START people_quickstart\]
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = \['https://www.googleapis.com/auth/contacts.readonly'\]
def main():
"""Shows basic usage of the People API.
Prints the name of the first 10 connections.
"""
creds = None
\# The file token.json stores the user's access and refresh tokens, and is
\# created automatically when the authorization flow completes for the first
\# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
\# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
\# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('people', 'v1', credentials=creds)
# Call the People API
print('List 10 connection names')
results = service.people().connections().list(
resourceName='people/me',
pageSize=10,
personFields='names,emailAddresses').execute()
connections = results.get('connections', [])
for person in connections:
names = person.get('names', [])
if names:
name = names[0].get('displayName')
print(name)
except HttpError as err:
print(err)
if __name__ == '__main__':
main()
# \[END people_quickstart\]
but it fails the authentication at this stage:
http://localhost:52591/?state=K8nzFjxOrWJkPEqjeG1AZiGpsT5DSx&code=4/0ARtbsJoAH2rD9UYgHOKJ__UdJcq87d2vuFjEAqcI3aKJpj1rLJ-93TXR0_v-LnBR4Fytsg&scope=https://www.googleapis.com/auth/gmail.readonly
why is it redirected to localhost?
There is a simple way to send e-mail at google colab? with or without using gmail?
i'm using the google colab at opera browser.
Can anyone help me how i can send a simple e-mail at google colab without lowing the gmail security level?
T.T
There is something wrong with the way you are loading the run_local_server if you are getting a 404 error.
The code below is my standard QuickStart for People api. I just tested it and it works fine. I am not getting a 404 error.
# To install the Google client library for Python, run the following command:
# pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
from __future__ import print_function
import os.path
import google.auth.exceptions
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/contacts']
def main():
"""Shows basic usage of the People API.
Prints a list of user contacts.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
try:
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
creds.refresh(Request())
except google.auth.exceptions.RefreshError as error:
# if refresh token fails, reset creds to none.
creds = None
print(f'An error occurred: {error}')
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'C:\YouTube\dev\credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('people', 'v1', credentials=creds)
# Call the People API
print('List 10 connection names')
results = service.people().connections().list(
resourceName='people/me',
pageSize=10,
personFields='names,emailAddresses').execute()
connections = results.get('connections', [])
for person in connections:
names = person.get('names', [])
if names:
name = names[0].get('displayName')
print(name)
except HttpError as err:
print(err)
if __name__ == '__main__':
main()
The official documentation shows how to create a spreadsheet, but I can't find how to create a sheet. How do I do it in Python?
#PCDSandwichMan's answer uses gspread, which is a very useful third-party library to simplify the Sheets API in Python. Not all of Google's APIs have libraries like this, though, so you may want to learn the regular way as well.
As an alternative in case that you want to use Google's API you can check out the documentation for Google's Python API libraries. Most direct changes to a spreadsheet's properties are done with spreadsheets().batchUpdate(). Here's a sample based on Google's Python Quickstart that adds a new sheet.
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
# The ID of the spreadsheet
YOUR_SPREADSHEET = 'some-id'
def main():
creds = None
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
sheetservice = build('sheets', 'v4', credentials=creds)
body = {
"requests":{
"addSheet":{
"properties":{
"title":"New Sheet"
}
}
}
}
sheetservice.spreadsheets().batchUpdate(spreadsheetId=YOUR_SPREADSHEET, body=body).execute()
except HttpError as err:
print(err)
Most of it is the authorization. The relevant part is within the try block. You pretty much just call the batchUpdate() method with the spreadsheet's ID and a body object with all the requests you want to make.
sheetservice = build('sheets', 'v4', credentials=creds)
body = {
"requests":[{
"addSheet":{
"properties":{
"title":"New Sheet"
}
}
}]
}
sheetservice.spreadsheets().batchUpdate(spreadsheetId=YOUR_SPREADSHEET, body=body).execute()
Sources:
Google Sheets API Python docs
General info on how to use batchUpdate
Google Python Quickstart
Could you do something like this?
import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = [
"https://spreadsheets.google.com/feeds",
"https://www.googleapis.com/auth/drive",
]
credentials = ServiceAccountCredentials.from_json_keyfile_name(
"client_secret.json", scope
)
gc = gspread.authorize(credentials)
def add_sheet(sheet_name):
wks = gc.add_worksheet(sheet_name, rows="1", cols="1")
return wks
I am using Google Analytics API to insert a custom dimension. I have set up the required Oauth2 credentials and obtained an access token and a refresh token. However, when I called my function that inserts a custom dimension to a specified Account and webProperty in Google Analytics, I get an error message that reads as follows:
<HttpError 403 when requesting: URL
returned "Request had insufficient authentication scopes.". Details: "[{'message': 'Insufficient Permission', 'domain': 'global', 'reason': 'insufficientPermissions'}]">
I opened the URL and got the following error message
Error message
Using the same code, I am able to fetch all accounts and webProperties in Google Analytics but apparently it can neither insert nor update custom dimensions and I don't know what I am missing in my code.
Here is my code:
from apiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient.errors import HttpError
import os
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
scope = ['https://www.googleapis.com/auth/analytics']
def get_service():
"""
authorises user to access GA resources and builds a service object
"""
creds = None
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', scopes=scope)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'client_secrets.json', scopes=scope)
creds = flow.run_local_server(port=80)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
# build a service object
service = build('analytics', 'v3', credentials=creds)
return service
def insert_customDimension(service):
# Inserts a custom Dimension at a specific index.
try:
service.management().customDimensions().insert(
accountId=ACCOUNT_ID,
webPropertyId=WEB_PROPERTY_ID,
body={'name': 'free to use',
'scope': 'HIT',
'active': False,
'index': 200
}
).execute()
except HttpError as error:
print(error)
except TypeError as er:
print(er)
def main():
# Authenticate and construct service.
service = get_service()
insert_customDimension(service)
if __name__ == '__main__':
main()
I would like to understand what am I doing wrong or what do I need to change in my code? I have deleted the token.json file and ran the code but I was unable to complete the authorization flow and not token.json was automatically created. I manually obtained the refresh and access token and created the file. I have admin privileges to the Google Analytics account I am trying to insert custom dimensions into.
I have tried access a Google ecosystem page after get credentials. My app will manage Calendar events, using python and Google api. I've got credentials, list events, read summaries, etc. But If I try to access a web page as (with AuthorizedSession class):
https://calendar.google.com
I notice that this page asks for login/password from Google.
Maybe this task is out of the specified scope. Ideas?
Thanks in advance!
Code:
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.auth.transport.requests import AuthorizedSession
import pickle
import os.path
import requests
from pathlib import Path
SCOPES = ['https://www.googleapis.com/auth/calendar']
CREDENTIALS_FILE = 'client_secret_123456ABCDEFG.apps.googleusercontent.com.json'
def get_credentials():
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
CREDENTIALS_FILE, SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
return creds
authed_session = AuthorizedSession(get_credentials())
response = authed_session.request(
'GET', 'https://calendar.google.com/')
print(response.status_code)
....
The url calendar.google.com is not in the same scope than the API.
Here's a part of the API doc :
Here's the OAuth 2.0 scope information for the Google Calendar API:
Scope Meaning https://www.googleapis.com/auth/calendar read/write
access to Calendars https://www.googleapis.com/auth/calendar.readonly
read-only access to Calendars
https://www.googleapis.com/auth/calendar.events read/write access to
Events https://www.googleapis.com/auth/calendar.events.readonly
read-only access to Events
https://www.googleapis.com/auth/calendar.settings.readonly read-only
access to Settings
https://www.googleapis.com/auth/calendar.addons.execute run as a
Calendar add-on
Edit: All actions for the Google calendar API are available in the endpoints described in the doc
I am trying to retreive the classwork of each course from Google Classroom API.I have succeeded in getting all the courses, but I am stuck on the course work: <HttpError 403 when requesting https://classroom.googleapis.com/v1/courses/167997334462/courseWork?alt=json returned "Request had insufficient authentication scopes.">.
This is the code I am using:
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/classroom.coursework.students.readonly']
def main():
"""Shows basic usage of the Classroom API.
Prints the names of the first 10 courses the user has access to.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
r"\test\credentials.json", SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('classroom', 'v1', credentials=creds)
# Call the Classroom API
course_work_results = service.courses().courseWork().list(courseId="167997334462").execute()
[...]
if __name__ == '__main__':
main()
I have generated the credidentials using admin account; I've also tried several different Scopes, but same error.
Could you guys please help me here?
I am using Python 3.9.
Thanks,
Alexandru
Since you are using the scope
https://www.googleapis.com/auth/classroom.coursework.students.readonly,
I assume you are a student.
Students are only allowed to access course work of the courses where they are accepted course participants.
Trying to retrieve the course work of another course will result in an 403 error.
If you are not a student, but an Admin of your Google Workspace domain, you should use a wider scope, e.g.
https://www.googleapis.com/auth/classroom.coursework.me.readonly.
Please mind that after changing the scopes in your source code you need to delete your token file to trigger new authentication flow.