Related
My goal is to display the 6 most recent items in the current users OneDrive.
Using https://graph.microsoft.com/v1.0/me/drive/recent?top=6 gives me the correct documents.
Some of these documents are OneNote Items.
At www.office.com the OneNote Items are displayed with the Notebook's displayname.
In the API response only the filename is contained.
Testing this is Microsoft's example data here:
https://developer.microsoft.com/en-us/graph/graph-explorer
Example response
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(driveItem)",
"#odata.nextLink": "https://graph.microsoft.com/v1.0/me/drive/recent?top=6&expand=section&$skiptoken=s!Njs3NGI0MzJjYS1mNmIzLTQ5YmQtOWIxMC02OTIyNjRlMTI3YTI",
"value": [
...
{
"#odata.type": "#microsoft.graph.driveItem",
"createdDateTime": "2017-08-07T16:08:45Z",
"id": "01BYE5RZ2IKLBQXYXELFD23BMJIB545TH6",
"lastModifiedDateTime": "2020-01-09T03:02:37Z",
"name": "Fabrikam.one",
"webUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7B0BC35248-E4E2-4759-AD85-89407BCECCFE%7D&file=Fabrikam.one&action=edit&mobileredirect=true&wdorigin=Sharepoint&DefaultItemOpen=1",
"size": 55782,
"createdBy": {
"user": {
"email": "MeganB#M365x214355.onmicrosoft.com",
"displayName": "Megan Bowen"
}
},
"lastModifiedBy": {
"user": {
"email": "",
"displayName": "System Account"
}
},
"file": {
"mimeType": "application/msonenote"
},
"fileSystemInfo": {
"createdDateTime": "2017-08-07T16:08:45Z",
"lastModifiedDateTime": "2020-01-09T03:02:37Z"
},
"remoteItem": {
"createdDateTime": "2017-08-07T16:08:45Z",
"id": "01BYE5RZ2IKLBQXYXELFD23BMJIB545TH6",
"lastModifiedDateTime": "2020-01-09T03:02:37Z",
"name": "Fabrikam.one",
"size": 55782,
"webDavUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/Documents/Fabrikam.one",
"webUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7B0BC35248-E4E2-4759-AD85-89407BCECCFE%7D&file=Fabrikam.one&action=edit&mobileredirect=true&wdorigin=Sharepoint&DefaultItemOpen=1",
"createdBy": {
"user": {
"email": "MeganB#M365x214355.onmicrosoft.com",
"displayName": "Megan Bowen"
}
},
"file": {
"mimeType": "application/msonenote"
},
"fileSystemInfo": {
"createdDateTime": "2017-08-07T16:08:45Z",
"lastModifiedDateTime": "2020-01-09T03:02:37Z"
},
"lastModifiedBy": {
"user": {
"email": "",
"displayName": "System Account"
}
},
"parentReference": {
"driveType": "business",
"driveId": "b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd",
"id": "01BYE5RZ56Y2GOVW7725BZO354PWSELRRZ"
},
"shared": {
"scope": "users"
},
"sharepointIds": {
"listId": "23f045a1-e6df-457c-8d95-a6ebd5feda5d",
"listItemId": "36",
"listItemUniqueId": "0bc35248-e4e2-4759-ad85-89407bceccfe",
"siteId": "d82312f9-b23b-4cbc-95d5-3e0d94e68c1e",
"siteUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com",
"webId": "2f91174f-f0c8-45c7-9540-aad4195c8e09"
}
}
},
...
]
}
Is there a way to retrieve the OneNote notebook's name from here?
The API provides a way to retrieve all notebooks like so:
https://graph.microsoft.com/v1.0/me/onenote/notebooks
However I do not see a connection between these responses.
Maybe relevant how to find OneNote Notebook object from driveItem with MS Graph? - this shows a workaround. I am curious if there is a better solution.
From yesterday I started receiving an error in my service (production environment) when trying to call Outlook Calendar REST API endpoint:
POST https://outlook.office.com/api/v2.0/me/findMeetingTimes
with following request body:
{
"Attendees": [
{
"Type": "optional",
"EmailAddress": {
"Address": "...",
"Name": null
}
},
{
"Type": "required",
"EmailAddress": {
"Address": "...",
"Name": null
}
}
],
"LocationConstraint": {
"IsRequired": true,
"SuggestLocation": false,
"Locations": [
{
"DisplayName": "..."
}
]
},
"TimeConstraint": {
"Timeslots": [
{
"Start": {
"DateTime": "2017-05-05T00:00:00",
"TimeZone": "UTC"
},
"End": {
"DateTime": "2017-05-05T21:59:59",
"TimeZone": "UTC"
}
}
]
},
"MaxCandidates": 1000,
"MeetingDuration": "PT30M",
"IsOrganizerOptional": true }
Here is the response I get:
{
"error": {
"code": "ErrorInternalServerError",
"message": "Invalid value for arg:Overlaps are not supported within TimeSlots, value:
{\"start\":2017-05-04T22:00:00Z,
\"min\":1440}
\r\nParameter name: Overlaps are not supported within TimeSlots"
}
}
Everything was working fine with until yesterday. There were no changes in my service codebase. It seems to be related with some changes in O365 API itself but there are no recent updates in documentation...
Any idea what might be wrong?
UPDATE: Without any modification in the request the server response is now:
{
"error": {
"code": "ErrorInternalServerError",
"message": "Index was outside the bounds of the array."
}
}
What is the best way to represent a generic response/payload object that has basic fields such as message, total elements, data, and status? Where the variability between each API is the data element. For instance, one API could be for permissions, so the data element would hold an array of permissions. But for another API, it would hold a different array of object types. My main goal is to have reuse with a payload object and to define the next "layer" of actual data.
I want to be able to define a data type that's generic - like a "response" that has basic fields but I want to be able to further define that content for each API (data containing permissions or roles or whatever).
Here are some JSON samples of what's been attempted but isn't rendering the way we would expect it to in Swagger UI (i.e. a flat structure of 4 elements with data defined per the API).
Example 1 - composition:
{
"swagger": "2.0",
"host": "localhost:8888",
"info": {
"version": "0.0.1",
"title": "API"
},
"paths": {
"/permissions": {
"get": {
"description": "Returns all permissions",
"operationId": "getPermissions",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "success",
"schema": {
"$ref": "#/definitions/permissionResponse"
}
}
}
}
}
},
"definitions": {
"response": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "A string indicating the response from the server."
},
"totalElements": {
"type": "integer",
"format": "int64",
"description": "The number of items retrieved."
},
"status": {
"type": "string",
"description": "A string indicating the response from the server."
}
}
},
"permissionResponse": {
"allOf": [
{
"$ref": "#/definitions/response"
}, {
"type": "object",
"properties": {
"data": {
"type": "array",
"description": "The collection of items returned from the API request.",
"items": {
"$ref": "#/definitions/permission"
}
}
}
}
]
},
"permission": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"description": "Unique identifier representing a specific permission."
},
"label": {
"type": "string",
"description": "The label of a permission."
},
"description": {
"type": "string",
"description": "A description of the permission."
},
"active": {
"type": "boolean",
"description": "A flag indicating whether a permission is active."
}
},
"required": [
"id",
"label",
"description",
"active"
]
}
}
}
Example 2 - composition variation:
{
"swagger": "2.0",
"host": "localhost:8888",
"info": {
"version": "0.0.1",
"title": "API"
},
"paths": {
"/permissions": {
"get": {
"description": "Returns all permissions",
"operationId": "getPermissions",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "success",
"schema": {
"$ref": "#/definitions/permissionResponse"
}
}
}
}
}
},
"definitions": {
"response": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "A string indicating the response from the server."
},
"totalElements": {
"type": "integer",
"format": "int64",
"description": "The number of items retrieved."
},
"status": {
"type": "string",
"description": "A string indicating the response from the server."
}
}
},
"permissionResponse": {
"allOf": [
{
"$ref": "#/definitions/response"
}],
"type": "object",
"properties": {
"data": {
"type": "array",
"description": "The collection of items returned from the API request.",
"items": {
"$ref": "#/definitions/permission"
}
}
}
},
"permission": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"description": "Unique identifier representing a specific permission."
},
"label": {
"type": "string",
"description": "The label of a permission."
},
"description": {
"type": "string",
"description": "A description of the permission."
},
"active": {
"type": "boolean",
"description": "A flag indicating whether a permission is active."
}
},
"required": [
"id",
"label",
"description",
"active"
]
}
}
Example 3 - additional properties:
{
"swagger": "2.0",
"host": "localhost:8888",
"info": {
"version": "0.0.1",
"title": "API"
},
"paths": {
"/permissions": {
"get": {
"description": "Returns all permissions",
"operationId": "getPermissions",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "success",
"schema": {
"$ref": "#/definitions/permissionResponse"
}
}
}
}
}
},
"definitions": {
"response": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "A string indicating the response from the server."
},
"totalElements": {
"type": "integer",
"format": "int64",
"description": "The number of items retrieved."
},
"status": {
"type": "string",
"description": "A string indicating the response from the server."
}
}
},
"permissionResponse": {
"type": "object",
"properties": {
"data": {
"type": "array",
"description": "The collection of items returned from the API request.",
"items": {
"$ref": "#/definitions/permission"
}
}
},
"additionalProperties": {
"$ref": "#/definitions/response"
}
},
"permission": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"description": "Unique identifier representing a specific permission."
},
"label": {
"type": "string",
"description": "The label of a permission."
},
"description": {
"type": "string",
"description": "A description of the permission."
},
"active": {
"type": "boolean",
"description": "A flag indicating whether a permission is active."
}
},
"required": [
"id",
"label",
"description",
"active"
]
}
}
Example 1 renders well with swagger2markup showing the consolidated view of the data with the other 3 elements and having a permission array. However, with Swagger UI, it renders it differently, separating the objects out.
Markup rendered:
Swagger UI rendered
Swagger UI rendered - expanded
I created a bill through the QuickBooks Online (QBO) web UI. Then I queried using the API (v3, documented here). The response:
{
"SyncToken": "16",
"domain": "QBO",
"VendorRef": {
"name": "MyVendor",
"value": "237"
},
"TxnDate": "2014-12-07",
"TotalAmt": 1.83,
"CurrencyRef": {
"name": "United States Dollar",
"value": "USD"
},
"PayType": "Check",
"PrivateNote": "test billpayment description (mod)",
"sparse": false,
"Line": [
{
"Amount": 1.22,
"LinkedTxn": [
{
"TxnId": "1412",
"TxnType": "Bill"
}
]
}
],
"Id": "1413",
"CheckPayment": {
"PrintStatus": "NeedToPrint",
"BankAccountRef": {
"name": "MyBankAcct#1234",
"value": "137"
}
},
"MetaData": {
"CreateTime": "2014-12-07T18:44:51-08:00",
"LastUpdatedTime": "2014-12-10T20:20:28-08:00"
}
}
As you can see, it has $0.61 of the TotalAmt unapplied to any Bills. (The other $1.22 is applied to Bill 1412.) Now, when I try to update this bill to change JUST the amount applied to the linked transaction, I get unexpected results.
Here's the update request body:
{
"SyncToken": "16",
"domain": "QBO",
"VendorRef": {
"name": "MyVendor",
"value": "237"
},
"TxnDate": "2014-12-07",
"TotalAmt": 1.83,
"CurrencyRef": {
"name": "United States Dollar",
"value": "USD"
},
"PayType": "Check",
"PrivateNote": "test billpayment description (mod)",
"sparse": false,
"Line": [
{
"Amount": 1.21,
"LinkedTxn": [
{
"TxnId": "1412",
"TxnType": "Bill"
}
]
}
],
"Id": "1413",
"CheckPayment": {
"PrintStatus": "NeedToPrint",
"BankAccountRef": {
"name": "MyBankAcct#1234",
"value": "137"
}
},
"MetaData": {
"CreateTime": "2014-12-07T18:44:51-08:00",
"LastUpdatedTime": "2014-12-10T20:20:28-08:00"
}
}
In the response, it appears that the API just basically can't handle the situation (even though it clearly existed when I created it in the web UI). Look what happens to the TotalAmt attribute! It's reduced to whatever the payment was in the LinkedTxn:
{
"BillPayment": {
"VendorRef": {
"value": "237",
"name": "MyVendor"
},
"PayType": "Check",
"CheckPayment": {
"BankAccountRef": {
"value": "137",
"name": "MyBankAcct#1234"
},
"PrintStatus": "NeedToPrint"
},
"TotalAmt": 1.21,
"domain": "QBO",
"sparse": false,
"Id": "1413",
"SyncToken": "17",
"MetaData": {
"CreateTime": "2014-12-07T18:44:51-08:00",
"LastUpdatedTime": "2014-12-10T20:25:02-08:00"
},
"TxnDate": "2014-12-07",
"CurrencyRef": {
"value": "USD",
"name": "United States Dollar"
},
"PrivateNote": "test billpayment description (mod)",
"Line": [
{
"Amount": 1.21,
"LinkedTxn": [
{
"TxnId": "1412",
"TxnType": "Bill"
}
]
}
]
},
"time": "2014-12-10T20:25:01.91-08:00"
}
I don't see discussion of this on the known issues page, so I'm pretty confused.
If you have any suggestions as to how to get this to do what I want it to, I thank you for your thoughts!
Can anyone tell me what the difference is between the status table and the stream table?
I am querying my own posts using the graph explorer and I find some status updates appear only in the status table, and others appear in both the stream and status table. When I go to my own Timeline I can see posts from both tables.
What is going on here? Why are some in the posts table only, but appear on my Timeline?!
I am trying to find a list of all my posts that are publicly visible, and it seems to do this I need to query both tables and end up with some duplicates. Is there a better way?
Here is an example:
graph.facebook.com/10150680671412355
{
"id": "10150680671412355",
"from": {
"name": "Alan Byrne",
"id": "509517354"
},
"message": "Beans on toast.",
"updated_time": "2012-03-14T10:53:01+0000",
"likes": {
"data": [
{
"id": "xxxxx",
"name": "xxxx"
}
],
"paging": {
"next": "https://graph.facebook.com/10150680671412355/likes?method=GET&metadata=true&format=json&callback=___GraphExplorerAsyncCallback___&access_token=AAACEdEose0cBAPjaO9gCyMZA2TT5hRE7iEkgmksfpNneFdtshFDfp0oM3hiX6I57vUkzGZAyXW5c9YaM1WQFUxt2zTZCden7zTAlbMSDAZDZD&limit=25&offset=25&__after_id=100001368900242"
}
},
"comments": {
"data": [
{
"id": "10150680671412355_31516486",
"from": {
"name": "xxxxx",
"id": "xxxxx"
},
"message": "Peasant. Baked beans on the other hand...",
"can_remove": true,
"created_time": "2012-03-14T11:20:35+0000"
}
],
"paging": {
"next": "https://graph.facebook.com/10150680671412355/comments?method=GET&metadata=true&format=json&callback=___GraphExplorerAsyncCallback___&access_token=AAACEdEose0cBAPjaO9gCyMZA2TT5hRE7iEkgmksfpNneFdtshFDfp0oM3hiX6I57vUkzGZAyXW5c9YaM1WQFUxt2zTZCden7zTAlbMSDAZDZD&limit=25&offset=25&__after_id=10150680671412355_31516486"
}
},
"type": "status"
}
Yet, when I scan for posts on the stream on that same day, this one does not come back
fql?q=select message,post_id,created_time from stream where source_id=509517354 and created_time > 1331596800 and created_time < 1331856000
{
"data": [
{
"message": "",
"post_id": "509517354_10150680640782355",
"created_time": 1331720877
},
{
"message": "",
"post_id": "509517354_10150680632467355",
"created_time": 1331720499
},
{
"message": "MY COMPUTER DOES NOT HAVE VIRUSES! STOP CALLING ME! ARGH!",
"post_id": "509517354_10150680618357355",
"created_time": 1331719866
},
{
"message": "",
"post_id": "509517354_10150680602327355",
"created_time": 1331719906
},
{
"message": "I did it!",
"post_id": "509517354_10150680491832355",
"created_time": 1331716355
},
{
"message": "",
"post_id": "509517354_10150680446052355",
"created_time": 1331714440
},
{
"message": "It got to Australia.\n",
"post_id": "509517354_365689393454249",
"created_time": 1331679835
},
{
"message": "",
"post_id": "509517354_107999992664739",
"created_time": 1331677643
},
{
"message": "",
"post_id": "509517354_10150678888762355",
"created_time": 1331671872
},
{
"message": "Booooo",
"post_id": "509517354_268316116580687",
"created_time": 1331632096
},
{
"message": "'spose I should wander into the office...",
"post_id": "509517354_10150678259167355",
"created_time": 1331625013
},
{
"message": "",
"post_id": "509517354_10150678258862355",
"created_time": 1331624991
},
{
"message": "",
"post_id": "509517354_10150678257547355",
"created_time": 1331624907
},
{
"message": "",
"post_id": "509517354_10150678250602355",
"created_time": 1331631742
}
]
}
The stream contains posts of various types - links, checkins, photos and status updates.
The status table only contains status updates - text with no additional links, photos etc.
If you're hoping to find the content similar to the timeline, you'll want to use the stream table.