What are Insights?
In Microsoft Graph API, Insights refers to a set of APIs that provide intelligent, personalized information derived from user activity and relationships within Microsoft 365. Insights are relationships calculated using advanced analytics and machine learning techniques
There are three main types of insights.
Trending Insights
Trending insights are document that are trending around the user, meaning files that are being accessed or edited frequently by people in their network. This helps users discover relevant content they might not be aware of.
Use the /v1.0/users/{user_id}/insights/trending
endpoint to retrieve trending insights for a specific user.
The response contains reference properties of the trending document, properties that you can use to visualize the document and value indicating how much the document is currently trending around the user.
Used Insights
Used insights are documents that the user has recently viewed or edited. It's useful for building "recently used" lists or dashboards.
Use the /v1.0/users/{user_id}/insights/used
endpoint to retrieve used insights for a specific user.
The response contains reference properties of the trending document, properties that you can use to visualize the document and information about the last time the user interacted with the document, such as when it was last viewed or edited.
Shared Insights
Shared insights are documents that others have shared with the user, which helps users quickly find content that is relevant to them without having to search through emails or chats.
Use the /v1.0/users/{user_id}/insights/shared
endpoint to retrieve shared insights for a specific user.
The response contains reference properties of the shared document, properties that you can use to visualize the document and information about the user who shared the document and the way how it was shared.
Filtering Insights
The common properties across all three types of insights are resourceReference and resourceVisualization. The resourceReference contains the URL and type of the referenced item.
Much more interesting is the resourceVisualization property, which contains additional information about the document, such as:
- containerType: where the document is located. Possible values are
OneDriveBusiness
,Site
,Mail
,DropBox
,Box
, andGDrive
- type: the media type of the document. Possible values are
PowerPoint
,Word
,Excel
,Pdf
,OneNote
,OneNotePage
,InfoPath
,Visio
,Publisher
,Project
,Access
,Mail
,Csv
,Archive
,Xps
,Audio
,Video
,Image
,Web
,Text
,Xml
,Story
,ExternalContent
,Folder
,Spsite
, andOther
You can filter insights based on these properties like
$filter=resourceVisualization/type eq '{type}'
$filter=resourceVisualization/containerType eq '{containerType}'
You can filter multiple type
or containerType
values by using the or
operator. The in
operator is not supported for filtering.
$filter=resourceVisualization/type eq 'Word' or resourceVisualization/type eq 'Excel'
For Trending Insights, you can filter by the value indicating how much the document is currently trending around the user.
$filter=weight ge 0.5
$filter=weight ge 0.1 and weight le 0.3
For Shared Insights, you can also filter by the user who shared the document using the sharedBy
property.
$filter=lastShared/sharedBy/id eq '{user_id}'
$filter=lastShared/sharedBy/address eq '{user_mail}'
For Used Insights, you can filter by the last time the user interacted with the document using the lastUsed
property.
$filter=lastUsed/lastAccessedDateTime ge 2025-08-01T00:00:00Z and lastUsed/lastAccessedDateTime le 2025-08-31T00:00:00Z
$filter=lastUsed/lastModifiedDateTime ge 2025-07-01T00:00:00Z and lastUsed/lastModifiedDateTime le 2025-07-31T00:00:00Z
Retrieve related resource
You can retrieve the related resource by using the resource
property. The resource can be driveItem
, fileAttachment
, or site
.
GET /v1.0/users/{user_id}/insights/trending/{insight_id}/resource
GET /v1.0/users/{user_id}/insights/used/{insight_id}/resource
GET /v1.0/users/{user_id}/insights/shared/{insight_id}/resource
Permissions
According the documentation, all insights endpoints require Sites.Read.All
. Only delegated permissions are supported. Insights can be read only for the signed-in user.
Read insights via Microsoft Graph .NET SDK
How to read insights using the Microsoft Graph .NET SDK? The following code snippets demonstrate how to read trending, used, and shared insights for a specific user.
Let's start by creating the InsightService
class that will encapsulate the logic for reading insights. The class will have the CreateCommonFilter
method to create a common filter for media types and container types, and methods to read trending, used, and shared insights.
private string CreateCommonFilter(List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes)
{
var filters = new List<string>();
if (mediaTypes.Count > 0)
{
var mediaTypeFilter = string.Join(" or ", mediaTypes.Select(mt => $"resourceVisualization/type eq '{mt}'"));
filters.Add($"({mediaTypeFilter})");
}
if (containerTypes.Count > 0)
{
var containerTypeFilter = string.Join(" or ", containerTypes.Select(ct => $"resourceVisualization/containerType eq '{ct}'"));
filters.Add($"({containerTypeFilter})");
}
return string.Join(" and ", filters);
}
public async Task<List<Trending>> GetTrendingInsightAsync(GraphServiceClient graphClient, string userId,
List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, double? minWeight, double? maxWeight)
{
}
public async Task<List<UsedInsight>> GetUsedInsightsAsync(GraphServiceClient graphClient, string userId,
List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, DateTime? minLastAccessed, DateTime? maxLastAccessed,
DateTime? minLastModified, DateTime? maxLastModified)
{
}
public async Task<List<SharedInsight>> GetSharedInsightAsync(GraphServiceClient graphClient, string userId,
List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, string sharedById, string sharedByAddress)
{
}
As you can see, the CreateCommonFilter
method constructs a filter string based on the provided media types and container types. The GetTrendingInsightAsync
, GetSharedInsightAsync
, and GetUsedInsightsAsync
methods will use this filter to retrieve insights from the Microsoft Graph API. All methods accept parameter for the graph client and user id.
The enums MediaTypes
and ContainerTypes
are defined as follows:
public enum ContainerTypes
{
None,
OneDriveBusiness,
Site,
Mail,
DropBox,
Box,
GDrive
}
public enum MediaTypes
{
None,
PowerPoint,
Word,
Excel,
Pdf,
OneNote,
OneNotePage,
InfoPath,
Visio,
Publisher,
Project,
Access,
Mail,
Csv,
Archive,
Xps,
Audio,
Video,
Image,
Web,
Text,
Xml,
Story,
ExternalContent,
Folder,
Spsite,
Other
}
Read trending insights via .NET SDK
The GetTrendingInsightAsync
accepts parameters for media types, container types, and optional weight filters. It constructs the filter string and retrieves trending insights for the specified user.
public async Task<List<Trending>> GetTrendingInsightAsync(GraphServiceClient graphClient, string userId,
List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, double? minWeight, double? maxWeight)
{
var trending = await graphClient.Users[userId].Insights.Trending.GetAsync(rc =>
{
var allFilters = new List<string>();
var filter = CreateCommonFilter(mediaTypes, containerTypes);
if (!string.IsNullOrEmpty(filter))
{
allFilters.Add(filter);
}
if (minWeight.HasValue)
{
var weightFilter = $"weight ge {minWeight.Value}";
allFilters.Add(weightFilter);
}
if (maxWeight.HasValue)
{
var maxWeightFilter = $"weight le {maxWeight.Value}";
allFilters.Add(maxWeightFilter);
}
filter = string.Join(" and ", allFilters);
if (!string.IsNullOrEmpty(filter))
{
rc.QueryParameters.Filter = filter;
}
});
var trendingItems = new List<Trending>();
var pageIterator = PageIterator<Trending, TrendingCollectionResponse>.CreatePageIterator(graphClient, trending, x =>
{
trendingItems.Add(x);
return true;
});
await pageIterator.IterateAsync();
foreach (var item in trendingItems)
{
var entity = await graphClient.Users[userId].Insights.Trending[item.Id].Resource.GetAsync(rc=>
{
rc.Headers.Add("accept", "application/json;odata.metadata=full");
});
item.Resource = entity;
}
return trendingItems;
}
Reading trending insights it's really straightforward. The most complicated part is constructing the filter based on the parameters.
The method uses the PageIterator
to retrieve all trending items. For each trending item, it retrieves the related resource using the Resource
property.
When retrieving the resource, I'm adding the accept: application/json;odata.metadata=full
header to get the full metadata of the resource. By default, the Microsoft Graph API returns null for the @odata.type
property and the SDK is not able to deserialize the resource to the correct type. By adding the accept
header, it ensures that the full metadata is returned, allowing the SDK to deserialize the resource correctly.
Read used insights via .NET SDK
The GetUsedInsightsAsync
method retrieves used insights for the specified user. It accepts parameters for media types, container types, and optional date filters for last accessed and last modified dates.
public async Task<List<UsedInsight>> GetUsedInsightsAsync(GraphServiceClient graphClient, string userId,
List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, DateTime? minLastAccessed, DateTime? maxLastAccessed,
DateTime? minLastModified, DateTime? maxLastModified)
{
var used = await graphClient.Users[userId].Insights.Used.GetAsync(rc =>
{
var allFilters = new List<string>();
var filter = CreateCommonFilter(mediaTypes, containerTypes);
if (!string.IsNullOrEmpty(filter))
{
allFilters.Add(filter);
}
if (minLastAccessed.HasValue)
{
var lastAccessedFilter = $"lastUsed/lastAccessedDateTime ge {minLastAccessed.Value.ToString("o")}";
allFilters.Add(lastAccessedFilter);
}
if (maxLastAccessed.HasValue)
{
var maxLastAccessedFilter = $"lastUsed/lastAccessedDateTime le {maxLastAccessed.Value.ToString("o")}";
allFilters.Add(maxLastAccessedFilter);
}
if (minLastModified.HasValue)
{
var lastModifiedFilter = $"lastUsed/lastModifiedDateTime ge {minLastModified.Value.ToString("o")}";
allFilters.Add(lastModifiedFilter);
}
if (maxLastModified.HasValue)
{
var maxLastModifiedFilter = $"lastUsed/lastModifiedDateTime le {maxLastModified.Value.ToString("o")}";
allFilters.Add(maxLastModifiedFilter);
}
filter = string.Join(" and ", allFilters);
if (!string.IsNullOrEmpty(filter))
{
rc.QueryParameters.Filter = filter;
}
});
var usedItems = new List<UsedInsight>();
var pageIterator = PageIterator<UsedInsight, UsedInsightCollectionResponse>.CreatePageIterator(graphClient, used, x =>
{
usedItems.Add(x);
return true;
});
await pageIterator.IterateAsync();
foreach (var item in usedItems)
{
var entity = await graphClient.Users[userId].Insights.Used[item.Id].Resource.GetAsync(rc =>
{
rc.Headers.Add("accept", "application/json;odata.metadata=full");
});
item.Resource = entity;
}
return usedItems;
}
Reading used insights is similar to reading trending insights. The most complicated part is again constructing the filter based on the parameters.
The PageIterator
is used to retrieve all used items and related resource is retrieved for each used insight.
Read shared insights via .NET SDK
The GetSharedInsightAsync
method retrieves shared insights for the specified user. It accepts parameters for media types, container types, and optional filters for the user who shared the document.
public async Task<List<SharedInsight>> GetSharedInsightAsync(GraphServiceClient graphClient, string userId,
List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, string sharedById, string sharedByAddress)
{
var shared = await graphClient.Users[userId].Insights.Shared.GetAsync(rc =>
{
var filter = CreateCommonFilter(mediaTypes, containerTypes);
var sharedByFilter = string.Empty;
var sharedByIdFilter = string.Empty;
var sharedByAddressFilter = string.Empty;
if (!string.IsNullOrEmpty(sharedById))
{
sharedByIdFilter = $"lastShared/sharedBy/id eq '{sharedById}'";
}
if (!string.IsNullOrEmpty(sharedByAddress))
{
sharedByAddressFilter = $"lastShared/sharedBy/address eq '{sharedByAddress}'";
}
var allSharedFilters = new List<string> { sharedByIdFilter, sharedByAddressFilter };
sharedByFilter = string.Join(" or ", allSharedFilters.Where(f => !string.IsNullOrEmpty(f)));
var allFilters = new List<string> { filter, sharedByFilter };
filter = string.Join(" and ", allFilters.Where(f => !string.IsNullOrEmpty(f)));
if (!string.IsNullOrEmpty(filter))
{
rc.QueryParameters.Filter = filter;
}
});
var sharedItems = new List<SharedInsight>();
var pageIterator = PageIterator<SharedInsight, SharedInsightCollectionResponse>.CreatePageIterator(graphClient, shared, x =>
{
sharedItems.Add(x);
return true;
});
await pageIterator.IterateAsync();
foreach (var item in sharedItems)
{
var entity = await graphClient.Users[userId].Insights.Shared[item.Id].Resource.GetAsync(rc =>
{
rc.Headers.Add("accept", "application/json;odata.metadata=full");
});
item.Resource = entity;
}
return sharedItems;
}
Main program
Before calling the methods in the InsightService
, you need to create an instance of the GraphServiceClient
and authenticate it using your preferred authentication method (e.g., client credentials, delegated permissions).
Let's assume that you have already registered an app in the Entra ID and granted the necessary permissions to read insights.
Initialize the Graph client:
var userCredentials = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
{
ClientId = "<client_id>",
TenantId = "<tenant_id>"
});
var graphClient = new GraphServiceClient(userCredentials);
Read insights:
var insightService = new InsightService();
var trending = await insightService.GetTrendingInsightAsync(graphClient, "user_id",
[MediaTypes.Word, MediaTypes.Excel],
[ContainerTypes.OneDriveBusiness, ContainerTypes.Site], 0.1, 0.7);
Console.WriteLine("Trending Items:");
foreach (var item in trending)
{
PrintResourceInfo(item.Resource);
}
var used = await insightService.GetUsedInsightsAsync(graphClient, "user_id",
[], [], DateTime.UtcNow.AddDays(-30), DateTime.UtcNow, DateTime.UtcNow.AddDays(-30), DateTime.UtcNow);
Console.WriteLine("Used Items:");
foreach (var item in used)
{
PrintResourceInfo(item.Resource);
}
var shared = await insightService.GetSharedInsightAsync(graphClient, "user_id",
[MediaTypes.Word, MediaTypes.Excel],
[ContainerTypes.OneDriveBusiness, ContainerTypes.Site], string.Empty, string.Empty);
Console.WriteLine("Shared Items:");
foreach (var item in shared)
{
PrintResourceInfo(item.Resource);
Console.WriteLine($"Shared by: {item.LastShared?.SharedBy?.DisplayName} ({item.LastShared?.SharedBy?.Address})");
}
Where the PrintResourceInfo
method is a utility method to print the resource information:
void PrintResourceInfo(Entity entity)
{
if (entity is DriveItem driveItem)
{
Console.WriteLine($"Insight: {driveItem.Name} ({driveItem.WebUrl})");
}
else if (entity is Site site)
{
Console.WriteLine($"Insight: {site.DisplayName} ({site.Description})");
}
else if (entity is FileAttachment file)
{
Console.WriteLine($"Insight: {file.Name}");
}
else
{
Console.WriteLine($"Insight: {entity?.GetType().Name} - {entity?.Id}");
}
}
Conclusion
In this blog post, I explored how to read insights from the Microsoft Graph API using the .NET SDK.
I covered the different types of insights—trending, used, and shared—and how to filter them based on media types, container types, and other properties.
Don't forget that insights can be read only for the signed-in user.