REST API 400 Bad Request for Aggregated Activity Segments on Empty Data - google-fit

We’re requesting activity data aggregated by segments for our users via REST interface.
But for some users (not all), retrieving this data fails with a 400 Bad Request despite sharing the same request format.
An example request JSON to aggregate by segments is:
{
"aggregateBy": [
{
"dataTypeName": "com.google.activity.segment"
},
{
"dataTypeName": "com.google.calories.expended"
},
{
"dataTypeName": "com.google.step_count.delta"
}
],
"bucketByActivitySegment": {
"minDurationMillis": 60000
},
"startTimeMillis": 1627182120000,
"endTimeMillis": 1627268520000
}
For all users with recorded activity data, we receive successful responses with data points, like for example:
{
"bucket": [
{
"startTimeMillis": "1627180684015",
"endTimeMillis": "1627182139339",
"dataset": [
{
"dataSourceId": "derived:com.google.activity.summary:com.google.android.gms:aggregated",
"point": [
{
"startTimeNanos": "1627180684015000000",
"endTimeNanos": "1627182139339000000",
"dataTypeName": "com.google.activity.summary",
"originDataSourceId": "derived:com.google.activity.segment:com.google.android.gms:merge_activity_segments",
"value": [
{
"intVal": 7,
"mapVal": []
},
{
"intVal": 1455324,
"mapVal": []
},
{
"intVal": 1,
"mapVal": []
}
]
}
]
},
[...]
But for users with no recorded activity data, we always receive 400 Bad Request responses, like:
{
"error": {
"code": 400,
"message": "unknown datasource: derived:com.google.activity.segment:com.google.android.gms:merge_activity_segments",
"errors": [
{
"message": "unknown datasource: derived:com.google.activity.segment:com.google.android.gms:merge_activity_segments",
"domain": "global",
"reason": "invalidArgument"
}
],
"status": "INVALID_ARGUMENT"
}
}
We confirmed that there is no recorded activity data by aggregating activity data by time, e.g. the request
{
"aggregateBy": [
{
"dataTypeName": "com.google.activity.segment"
}
],
"bucketByTime": {
"durationMillis": 60000
},
"startTimeMillis": 1627182120000,
"endTimeMillis": 1627268520000
}
leads to a successful response with completely empty data points, like:
{
"bucket": [
{
"startTimeMillis": "1627182120000",
"endTimeMillis": "1627182180000",
"dataset": [
{
"dataSourceId": "derived:com.google.activity.summary:com.google.android.gms:aggregated",
"point": []
}
]
},
[...]
"dataset": [
{
"dataSourceId": "derived:com.google.activity.summary:com.google.android.gms:aggregated",
"point": []
}
]
}
]
}
Our questions are:
Is the 400 Bad Request response actually avoidable for users with empty data?
Or should this be considered a bug in the Google Fit API? We don't see a reason to respond with a 400 Bad Request instead of empty data when aggregating empty data by segments.

It was confirmed to us by the Google Fit team that this response behavior is not going to change, as users might already rely on it. We need to work around this, e.g. handle this error response separately, check if data is empty or something like this.

Related

How can I create an activity for data conversion in Design Automation API?

I'm prototyping a web service to convert data using Design Automation API in Autodesk Forge.
My approach is to invoke an activity that executes a script to import a target data file (such as STEP, IGES format).
As an example, I created an activity to convert a STEP file to DWG as follows:
{
"HostApplication": "",
"RequiredEngineVersion": "22.0",
"Parameters": {
"InputParameters": [{
"Name": "Source",
"LocalFileName": "input.stp"
}, {
"Name": "HostDwg",
"LocalFileName": "$(HostDwg)"
}],
"OutputParameters": [{
"Name": "Result",
"LocalFileName": "output.dwg"
}]
},
"Instruction": {
"CommandLineParameters": null,
"Script": "import\ninput.stp\nsaveas\n\noutput.dwg\n"
},
"Version": 1,
"Id": "Step2Dwg"
}
The workitem to invoke this activity was executed without errors, but the output file (output.dwg) had nothing imported from the input file (input.stp).
Perhaps this is because some fields (e.g., AllowedChildProcess) were missing in the definition of the activity "Step2Dwg", but I do not know how to fix it.
My questions are:
How to fix the definition of the activity "Step2Dwg" to convert data successfully?
Is there any other approach to create an activity to convert data successfully?
You can use the Activity “Translate-STEP2DWG". It takes a .stp file as input and generate result.dwg as output. This is a public activity that anybody can send workitems against to it.
The activity is defined like this:
{
"Id": "Translate-STEP2DWG",
"AppPackages": [],
"HostApplication": "AcTranslators.exe",
"RequiredEngineVersion": "22.0",
"Parameters": {
"InputParameters": [
{
"Name": "HostDwg",
"LocalFileName": "source.stp"
}
],
"OutputParameters": [
{
"Name": "Result",
"LocalFileName": "result.dwg"
}
]
},
"Instruction": {
"CommandLineParameters": "-i source.stp -o result.dwg",
"Script": ""
},
"AllowedChildProcesses": [
],
"IsPublic": true,
"Version": 1,
"Description": ""
}
Here is a sample workitem request body:
{
"ActivityId": "Translate-STEP2DWG",
"Arguments": {
"InputArguments": [
{
"Resource": "https://s3.amazonaws.com/AutoCAD-Core-Engine-Services/TestDwg/3DStep.stp",
"Name": "HostDwg"
}
],
"OutputArguments": [
{
"Name": "Result",
"HttpVerb": "POST"
}
]
}
}

206 partial Content and a bucket for error ids or json element with 404 and overall 200 OK

We have a requirement where we want to hit the apis for a list of ids as async requests.
If the id is not found we receive a 404 for the specific request.
I want to know out of the two options which is a better way to handle with situation where partial content returns 200 and 404 for some of the ids.
I have evaluated two approaches.
a.
HTML Response code: 200
{
"12": {
"Response": "Success",
"StatusCode": 200,
"content": {
"title": "Shipping",
"body": ""
}
},
"13": {
"Response": "Success",
"StatusCode": 200,
"content": {
"title": "Shippin11",
"body": " "
}
},
"14": {
"Response": "Error",
"StatusCode": 404,
"ErrorMessage": "Content Not Found"
}
}
b.HTML Response code: 206
{
"data": {
"12": {
"Response": "Success",
"StatusCode": 200,
"content": {
"title": "Shipping",
"body": ""
}
}
},
"error": {
"Response": "Error",
"StatusCode": 404,
"ids": [12, 13]
}
}
Please share your thoughts.
thanks, aakash
I think it's better to use HTTP 207 Multi-Status respoince (see https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success). It's better sute for you task. More details in rfc: https://www.rfc-editor.org/rfc/rfc4918#page-78 (and chapter "13. Multi-Status Response").
Main idea is wrapp all requests in single "main". Main responce return HTTP 200 Ok status. Response body contain list of request's responses and some meta information about whole request: count of successed/error requests. Every single response (inside main) contein their response HTTP code (200/204/404/...) and data.
For you case it may look like:
{
"data": [
{
"content": {
"id": 12,
"title": "Shipping",
"body": ""
},
"status": 200
},
{
"resource": null,
"status": 404
},
{
"content": {
"id": 13,
"title": "Shippin11",
"body": ""
},
"status": 200
}
],
"metadata": {
"failure": 1,
"success": 2,
"total": 3
}
}
You can watch to drupal developer's inplementation:
https://gist.github.com/e0ipso/732712c3e573a6af1d83b25b9f0269c8
Another example for json-api: https://developers.getbase.com/docs/rest/articles/search/samples/batch
There is no single common perfect format, but all implementations are similar in general, but differ in detail.

Use Apps Script URLFetchApp to access Google Datastore Data

I want to experiment with Google Datastore via Apps Script because I have a current solution based on Google sheets that runs into timeout issues inherent in constantly transacting with Drive files. I've created a test project in Google cloud with a service account and enabled library MZx5DzNPsYjVyZaR67xXJQai_d-phDA33
(cGoa) to handle the Oauth2 work. I followed the guide to start it up here and got all the pertinent confirmation that it works with my token (and that removing the token throws an 'authentication failed prompt').
Now I want to start with a basic query to display the one entity I already put in. I can use the API Explorer here and run this query body:
{
"query": {}
}
and get this result:
{
"batch": {
"entityResultType": "FULL",
"entityResults": [
{
"entity": {
"key": {
"partitionId": {
"projectId": "project-id-5200707333336492774"
},
"path": [
{
"kind": "Transaction",
"id": "5629499534213120"
}
]
},
"properties": {
"CommentIn": {
"stringValue": "My First Test Transaction"
},
"Status": {
"stringValue": "Closed"
},
"auditStatus": {
"stringValue": "Logged"
},
"User": {
"stringValue": "John Doe"
},
"Start": {
"timestampValue": "2017-08-17T18:07:04.681Z"
},
"CommentOut": {
"stringValue": "Done for today!"
},
"End": {
"timestampValue": "2017-08-17T20:07:38.058Z"
},
"Period": {
"stringValue": "08/16/2017-08/31/2017"
}
}
},
"cursor": "CkISPGogc35whh9qZWN0LWlkLTUyMDA3MDcwODA1MDY0OTI3NzRyGAsSC1RyYW5zYWN0aW9uGICAgICAgIAKDBgAIAA=",
"version": "1503004124243000"
}
],
"endCursor": "CkISPGogc35wcm9qZWN0LWlkLTUyMDAxxDcwODA1MDY0OTI3NzRyGAsSC1RyYW5zYWN0aW9uGICAgICAgIAKDBgAIAA=",
"moreResults": "NO_MORE_RESULTS"
}
}
I try to do the same thing with this code:
function doGet(e)
{
var goa = cGoa.GoaApp.createGoa('Oauth2-Service-Account',
PropertiesService.getScriptProperties()).execute(e);
if(goa.hasToken()) {var token = goa.getToken();}
var payload = {"query":{}}
;
var result = UrlFetchApp.fetch('https://datastore.googleapis.com/v1/projects/project-id-5200707333336492774:runQuery',
{
method: "POST",
headers: {authorization: "Bearer " + goa.getToken()},
muteHttpExceptions : true,
payload: payload
});
Logger.log(result.getBlob().getDataAsString());
}
and get this error in the logger:
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"query\": Cannot bind query parameter. 'query' is a message type. Parameters can only be bound to primitive types.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"query\": Cannot bind query parameter. 'query' is a message type. Parameters can only be bound to primitive types."
}
]
}
]
}
}
If I try to use another word such as 'resource' or 'GqlQuery', I get this error:
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"GqlQuery\": Cannot bind query parameter. Field 'GqlQuery' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"GqlQuery\": Cannot bind query parameter. Field 'GqlQuery' could not be found in request message."
}
]
}
]
}
}
I can't tell from the API Documentation what my syntax is supposed to be. Can anyone tell me how to compile a functional request body from Apps Script to Datastore?
You need to set the contentType of your payload as well as stringify your JSON payload as follows:
var result = UrlFetchApp.fetch(
'https://datastore.googleapis.com/v1/projects/project-id-5200707333336492774:runQuery',
{
'method':'post',
'contentType':'application/json',
'headers': {authorization: "Bearer " + goa.getToken()},
'payload':JSON.stringify(payload)
}
);

Python3 google spreadsheet api batchUpdate Json formatting

I want to use google spreadsheet api batchUpdate to update different values with the same request.
In the documentation examples they use a dict to store the Json request but I need to set the same attribute (insertDimension) multiple times.
Here Google expected request
{
"requests": [
{
"insertDimension": {
"range": {
"sheetId": sheetId,
"dimension": "COLUMNS",
"startIndex": 2,
"endIndex": 4
},
"inheritBefore": true
}
},
{
"insertDimension": {
"range": {
"sheetId": sheetId,
"dimension": "ROWS",
"startIndex": 0,
"endIndex": 3
},
"inheritBefore": false
}
},
],
}
I tried using json.dumps
mydata = json.dumps('''
"requests": [{{"updateDimensionProperties": {"range": {"sheetId": 0,"dimension": "ROWS","startIndex": 0
"endIndex": 50
},
"properties": {
"pixelSize": 10
},
"fields": "pixelSize"
}
}
} ] ''')
but I receive this error message
"Invalid JSON payload received. Unknown name "": Root element must be a message."
Your request is invalid because it never says what kind of request it is: the insertDimension request. The correct form is
{
"requests": [
{
"insertDimension": {
# required fields at https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertDimensionRequest
}
},
{
"insertDimension": {
# required fields at https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertDimensionRequest
}
}]
}
By the way, one of the fields is inheritFromBefore, not inheritBefore

facebook graph explorer returns empty data array using marketing api

I have an issue with the graph explorer when I try to test for insights data.
When I do
act_XXX/?fields=campaigns
It returns
{
"campaigns": {
"data": [
{
"id": "XXXX"
},
{
"id": "XXXX"
}
],
"paging": {
"cursors": {
"before": "MjM4NDI1MTI2NzQ3NzAxMzEZD",
"after": "MjM4NDI1MTI2NzQxNTAxMzEZD"
}
}
},
"id": "act_XXXX"
}
But when I do
act_XXX/insights
I returns an empty data array
{
"data": [
]
}
It looks like I have set the correct permission, but I must be missing something?
probably doesn't have any insight data for previous month as it only fetches last month insights
try using
act_XXX?fields=insights.time_range({"since":"2018-03-03","until":"2019-03-03"})