googleapis giving back bad request - google-api

Having implemented oauth2.0 and done a handshake using the scopes:
"https://www.googleapis.com/auth/userinfo.email ",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/admin.directory.user ",
"https://www.googleapis.com/auth/admin.directory.group ",
"https://www.googleapis.com/auth/admin.directory.orgunit ",
I get back a token
the request
$ curl -X GET https://www.googleapis.com/oauth2/v1/userinfo?access_token=<Token>
{
"id": "{id}",
"email": "{email}",
"verified_email": true,
"name": "{name}",
...
}
as it should.
however a requst to the admin.directory.user namespace does not succeed:
$ curl -X GET https://www.googleapis.com/admin/directory/v1/users?access_token=<Token>
{
"error": {
"errors": [
{
"domain": "global",
"reason": "badRequest",
"message": "Bad Request"
}
],
"code": 400,
"message": "Bad Request"
}
}
Any good ideas to why this is?
The request to admin.directory.users is constructed from https://developers.google.com/admin-sdk/directory/v1/reference/#Users

I had the same problem retrieving all users through https://www.googleapis.com/auth/admin.directory.user endpoint. According to the documentation, you could do that in a specific domain by passing the domain as a parameter or get all existing users by passing the customer=my_customer parameter as follows:
Retrieve all users in a domain doc: https://www.googleapis.com/auth/admin.directory.user?domain=example.com
or
Retrieve all account users doc: https://www.googleapis.com/auth/admin.directory.user?customer=my_customer
In google playground oauth2 also you can test the above stuff by selecting Admin SDK API directory_v1 and auth/admin.directory.user.readonly to authorize the respective scope, then call the above requests.
Note that, you may need to get access to google playground within your google admin dashboard under the security apps section.

You need to specify either the domain (to get fields from only one domain) or the customer (to return all domains for a customer account).
I filed a bug to make more clear that is required to provide one of the two parameters.

At the very least, you need to include the Content-Type header:
curl -X GET -H "Content-Type: application/json" https://www.googleapis.com/admin/directory/v1/users?customer=my_customer&access_token=<Token>
For a full script that implements this API with CURL and BASH see this answer.
Note that the documentation is currently incorrect because it lists customer as an optional parameter when it is in fact required.

Related

Google Speech API: the requested URL was not found on this server

I am attempting some simple tests on the Google Speech API, and when my server makes a request to this url (below), I get the 404. that's an error response. Not sure why.
https://speech.googleapis.com/v1/speech:recognize?key=[MY_API_KEY]
The body of my request looks like this:
{
"config": {
"languageCode": "en-US",
"encoding": "LINEAR16",
"sampleRateHertz": 16000,
"enableWordTimeOffsets": true,
"speechContexts": [{
"phrases": ["Some", "Helpful", "Phrases"]
}]
},
"audio":{
"uri":"gs://mydomain.com/my_file.mp3"
}
}
And here is the response:
As you can see, that is a valid resource path, unless I'm totally mistaken about something (I'm sure I am): https://cloud.google.com/speech-to-text/docs/reference/rest/v1/speech/recognize
Update 1:, Whenever I try this with the Google API explorer tool, I get this quota exceeded message (even though I have not yet issued a successful request to the API).
{
"error": {
"code": 429,
"message": "Quota exceeded for quota metric 'speech.googleapis.com/default_requests' and limit 'DefaultRequestsPerMinutePerProject' of service 'speech.googleapis.com' for consumer '[MY_API_KEY]'.",
"status": "RESOURCE_EXHAUSTED",
"details": [
{
"#type": "type.googleapis.com/google.rpc.Help",
"links": [
{
"description": "Google developer console API key",
"url": "https://console.developers.google.com/project/[my_project_id]/apiui/credential"
}
]
}
]
}
}
Update 2: Interestingly, I was able to get some 200 ok's using the Restlet client, but even in those cases, the response body is empty (see screenshot below)
I have made a test by using the exact URL and Body content you added to the post, however, I was able to execute the API call correctly.
I noticed that if I add some extra character to the URL, it fails with the same 400 error since it doesn't exist. I would suggest you to verify that the URL of your request doesn't contain a typo and that the client you use is executing the API call correctly. Also, ensure that your calling code is not encoding the url, which could cause issues given the colon : that appears in the url.
I recommend you to perform this test by using the Try this API tool directly or Restlet client which are the ones that I used to replicate this scenario.

Send message from Postman to Microsoft Bot

I am trying to send a message to a bot I created and published to azure services so that the bot can then start messaging some of its users.
I am trying to make the requests on Postman first so that then I can build a controller for that interaction.
I am doing the following request:
POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
Body:
grant_type:client_credentials
client_id: my_ms_app_id
client_secret: my_ms_app_secret
scope: https://api.botframework.com/.default
from this I get in the response the Bearer Authorization:
{
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 0,
"access_token": "eyJ0eXA..."
}
Then I proceed with the following request:
POST https://skype.botframework.com/v3/conversations
Content-Type: application/json
Authorization: Bearer eyJ0eXAi....
{
"bot": {
"id": "i don't have this id so i pass some string",
"name": "connector controller"
},
"isGroup": false,
"members": [
{
"id": "28:...", //ID of the bot I want to send the message to
"name": "Sp Bot"//Name of the bot I want to talk to
},
{
"id": "i don't have this id so i pass some string",
"name": "connector controller"
}
],
"topicName": "News Alert"
}
in response i get the conversation id which matches "id": "i don't have this id so i pass some string":
{
"id": "i don't have this id so i pass some string"
}
Then I proceed with the following POST request:
POST. https://skype.botframework.com/v3/conversations/i don't have this id so i pass some string/activities
Authorization: Bearer eyJ0...
Content-Type:application/json
I get the following response:
400 Bad Request
{
"error": {
"code": "ServiceError",
"message": "The conversationId 29... and bot .... doesn't match a known conversation"
}
}
It looks like the problem occurs between the second and the 3 post method. It looks like that the https://skype.botframework.com/v3/conversations does not generate a conversation with the bot with Id I entered.
So when I make the final call to the bot: https://skype.botframework.com/v3/conversations/.../activities I always get the serviceError message.
Based on your comments you are trying to create a custom "channel/client" to talk with the bot.
For doing that, I would recommend taking a look to Direct Line which seems the way to go for achieving your requirement.
I'm not sure which language are you using, so I will send you pointers to both C# and Node.
These are samples that will show you how to create custom client using Direct Line to interact with your bot:
C#
Basic Direct Line sample
Direct Line sample using Web Sockets
Node.js
Basic Direct Line sample
Direct Line sample using Web Sockets
All the samples are using a console app as the "custom channel".
Since you're going to make an app talk to your bot and most likely be using DirectLine after you and Ezequiel chatted, I created a series of screencaps on connecting to the DirectLine endpoint through Potsman. I'm going to assume that you know how to use environmental and global variables in Postman, here are Postman's documentation for other people's benefit. Also, the DirectLine v3.0 docs are here.
Below is a capture of the directline endpoint you would request a token from, {{DLsecret}}'s guts looks like this, Bearer <your-dl-secret>:
Here is an example of the response body you would receive on a valid call:
You may have noticed that I have some test results, in the screenshow below it has five (vs four) tests because I added the test verifying that the conversationId was set in the environment variables:
Here's the second query sent, which contains an actual message:
This is the request body which has the message:
And here is the response body:

Adsense API getting 'Error: Login Required'

I'm using the API Explorer tool to create some request urls for google adsense. Here is the request url that the explorer tool generated that gives a response of today's earnings: https://www.googleapis.com/adsense/v1.4/reports?startDate=today&endDate=today&accountId=MY_ACCOUNT_ID&metric=EARNINGS&key=MY_API_KEY
However, when I try to use this url in the browser or in my code it gives this response:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}
I am not sure what I am missing it use this url. I have activated adsense apis on my google developer console.
The key parameter is the public API key for accessing public data.
The access_token parameter is used for accessing private user data.
In your case you are trying to access your private account and should be using an access token.
To obtain an access token you need to authentication your application using either Oauth2 or a service account. Once you have obtained an access token and send that with your request as so:
https://www.googleapis.com/adsense/v1.4/reports?startDate=today&endDate=today&accountId=MY_ACCOUNT_ID&metric=EARNINGS&access_token=YourAccessToken
You need to replace MY_API_KEY with your API key, and MY_ACCOUNT_ID in same fashion.

Using the insert method of the Google Data Transfer API to start a transfer

I am trying to use the transfers:insert method of the Google Admin SDK Data Transfer API. I am performing this API call as the super admin account of my domain. I have verified that API access is enabled for our domain, and that the Super Admin admin role has permission to use the Data Transfer API.
I am testing this in the APIs Explorer on this page.
55656082996 is the ID string that I got for Google Drive from the applications:list APIs Explorer.
Request:
POST https://www.googleapis.com/admin/datatransfer/v1/transfers?key={YOUR_API_KEY}
{
"oldOwnerUserId": "olduser#ourdomain.com",
"newOwnerUserId": "newuser#ourdomain.com",
"applicationDataTransfers": [
{
"applicationId": "55656082996"
}
]
}
Response:
400 OK
- SHOW HEADERS -
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalid",
"message": "Invalid value for: Invalid oldOwnerUserId."
}
],
"code": 400,
"message": "Invalid value for: Invalid oldOwnerUserId."
}
}
I get the same "Invalid value for: Invalid oldOwnerUserId." response no matter if I use email addresses or usernames. I also tried excluding the applicationDataTransfers array from the response, but that also didn't work.
The documentation does not say this, but the Id cannot be the user's email address, like in all of the other Google APIs, but rather it needs to be a numeric ID for the user that you can get using the Users:get Directory API method.
I figured this out by Google searching and coming across this documentation, where they elaborate upon oldOwnerUserId by saying "# ID"
In addition to the answer above.
Here is how you can get the employee' IDs from Gsuite API in Python 3.*
def create_directory_service():
credentials = cls.get_credentials(scopes=['https://www.googleapis.com/auth/admin.directory.user'])
return build('admin', 'directory_v1', credentials=credentials, cache_discovery=Fals
service = create_directory_service()
old_owner_google_id = service.users().get(userKey=old_owner).execute()['id']
new_owner_google_id = service.users().get(userKey=new_owner).execute()['id']

Google Simple API Access - Authorization required, but how?

I'm trying write a standalone perl app that list all my tasks stored in Google Tasks. I'm led to believe I can use what Google call "Simple API Access" because it's just my tasks and it's read only.
So I did the following:
#!perl
use LWP;
my $browser = LWP::UserAgent->new;
my $list = "Iyrhxu8sRTVOhE4hUBr4W1kwNTI6MDow";
my $key = "<api key removed>";
my $url = "https://www.googleapis.com/tasks/v1/lists/$list/tasks?pp=1&key=$key";
print $browser->get($url)->content;
In return, I get:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}
Unfortunately I've no idea what authorization it wants at this point. I tried replacing the last line with:
my $auth = "...";
print $browser->get($url, "Authorization", $auth)->content;
and using the Google listed Client ID, Email address and Client Secret listed in the API Console - but they all gave Invalid Credentials.
Can anyone help?
Doesn't seem to work, they seem to have disabled it in favor of oauth2, and just haven't updated the apply-for-an-api-key page. Use Oauth2 instead:
https://developers.google.com/oauthplayground/
If you need an api key, you can get it here:
https://code.google.com/apis/console

Resources