12

I am working on a project where we want to collect data on GMB performance through the GMB API. This entails capturing many of the reportInsights results. We are not creating or updating any records for this account. I tried the Oauth2 approach however, that required me to provide permission and since we are not accessing or updating any user data I would like to avoid Oauth.

From the documentation and for this use case, I believe a service account is the best approach and I have created that credential in the Google API console.

I can create credentials, however, when I run the process I get the following error:

googleapiclient.errors.HttpError: <HttpError 403 when requesting https://mybusiness.googleapis.com/$discovery/rest?version=v3 returned "The request is missing a valid API key.">

This seems odd since I have a valid set of Service Account credentials. I did include a valid API key from the Google API console but I get the same error.

Here is my Python code:

import os
import httplib2
import json
import argparse
import apiclient.discovery

from oauth2client.service_account import ServiceAccountCredentials

from apiclient.discovery import build

api_name = 'mybusiness'
api_version = 'v3'
api_key = '<my valid api key from google api console that has permission for this GMB project>'

discovery_uri = 'https://mybusiness.googleapis.com/$discovery/rest?version={}'.format(api_version)

flow_scope='https://www.googleapis.com/auth/plus.business.manage'

credentials_file = '/Google_My_Business-service_account.json' # the service account credentials from the Google API console that have permission for this GMB project 

credentials = ServiceAccountCredentials.from_json_keyfile_name(credentials_file, scopes=flow_scope)

print("credentials: ", credentials)

http = credentials.authorize(httplib2.Http())
print("http: ", http)

# Build the service object
service = build(api_name, api_version, http=http, developerKey=api_key, discoveryServiceUrl=discovery_uri)

The error is thrown from the last line. Any help is appreciated.

analyticsPierce
  • 2,979
  • 9
  • 57
  • 81
  • Have you tried to regenerate key? Sometimes they expire, or have restrictions which you can check in [Developer Console](https://console.developers.google.com/apis/credentials) – zipa Sep 09 '17 at 20:46
  • The various credentials are all recent and have the highest levels of permissions possible. Do you have guidelines on what I should have set for the Service Account and API Key? – analyticsPierce Sep 09 '17 at 20:49
  • There is an email address that google provides for each project, a long one, and I switched my address for that one and it solved it for my Google Analytics API project. – zipa Sep 09 '17 at 20:54
  • @zipa Yes, I have that in the Service Account credentials. You switched that for what when you connected to the API? Can you give me some details on what I should try? – analyticsPierce Sep 09 '17 at 20:55
  • *This is just a guess* but try editing you `json` by changing your email to that one :) – zipa Sep 09 '17 at 21:01
  • @zipa Yes, the json comes from Google API console and already has that long project-specific email address in it. Good to check! – analyticsPierce Sep 09 '17 at 21:02

2 Answers2

2

Try changing your code to the following

from oauth2client.client import AccessTokenCredentials
credentials = AccessTokenCredentials('<an access token>', 'my-user-agent/1.0')
http = httplib2.Http() 
http = credentials.authorize(http)

Then if that works try the following to get credentials from JSON file

from oauth2client.client import AccessTokenCredentials
credentials = AccessTokenCredentials.from_json(credentials_file)
http = httplib2.Http()
http = credentials.authorize(http)
James
  • 1,928
  • 3
  • 13
  • 30
  • your two lines look exactly the same. I have an API key, its showing in the code. I'll check it again but it should not have any issues. – analyticsPierce Sep 12 '17 at 22:19
  • Opps your right I will change it. You want to change developerkey to key – James Sep 13 '17 at 16:36
  • When I tried your suggestion I got: TypeError: build() got an unexpected keyword argument 'key' – analyticsPierce Sep 14 '17 at 05:23
  • @analyticsPierce I just changed my answer. Try it. I got that from the Google API Documentation https://developers.google.com/api-client-library/python/reference/pydoc – James Sep 14 '17 at 17:48
  • 1
    Were you able to build a service object and get the response? I am able to get the credentials, however, it fails when I try to build the service object. That is the last line of my code above. I'm trying these solutions but think this answer is off topic as it does not address Google My Business access. – analyticsPierce Sep 15 '17 at 23:34
  • My answer if off topic? It fixes the credentials issue. Why dont you accept mine as correct since it worked, create a new question, and I will answer that – James Sep 16 '17 at 01:27
  • If you read my question again, the problem I had was with the service = build() part of my code. I state that "I can create credentials". Your suggestion may be helpful but you are not building the service to show that these credentials will actually work. – analyticsPierce Sep 16 '17 at 05:38
  • @analyticsPierce Try following this format https://google.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build – James Sep 16 '17 at 15:49
  • @analyticsPierce Developer key should be key obtained from https://code.google.com/apis/console and you should add credentials= which is the oauth2 credentials. discoveryServiceURl should have two parameters, api and apiVersion. – James Sep 16 '17 at 15:52
  • You were the only person who answered so I'll give you the points. Even though your solution doesn't work for the question I do appreciate the effort. – analyticsPierce Sep 16 '17 at 23:14
  • Thanks. Take a look at https://google.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build also. – James Sep 16 '17 at 23:40
  • If you need anything else let me know – James Sep 16 '17 at 23:40
1

The problem is with the discovery service url. It seems that private apis can't be accessed via discovery api service (even when you use apikeys). As such, the resolution is to change discovery service url to a valid json file displaying mybusiness service.

discovery_uri = "https://developers.google.com/my-business/samples/mybusiness_google_rest_v3p3.json"
stupidbodo
  • 466
  • 1
  • 5
  • 14
  • 1
    How did you find the path directly to the `JSON` file? When I try to use `https://developers.google.com/my-business/samples/mybusiness_google_rest_v3p3.json` I get a `404` error. Looks like it's no longer available. And when I try to use `https://mybusiness.googleapis.com/$discovery/rest?version=v4` as suggested by [Google's own documentation](https://developers.google.com/my-business/reference/rest), I get the same `403` error as OP ("The request is missing a valid API key") even though I'm using a valid Credentials object/token. – leifericf Mar 22 '22 at 12:08
  • I was also getting a 403 error when using the URL from the Google docs. This URL worked for me: `https://developers.google.com/my-business/samples/mybusiness_google_rest_v4p9.json`. I found it in a SO comment: `https://stackoverflow.com/q/70080214` – RonquilloAeon Jul 29 '22 at 18:40