Public/Get-CopilotInteractionHistory.ps1
function Get-CopilotInteractionHistory { <# .SYNOPSIS Get a users ineraction history with Microsoft 365 Copilot. .DESCRIPTION Get all Microsoft 365 Copilot interaction data, including user prompts to Copilot and Copilot responses. .PARAMETER UserId Specifies the ID of the user whose interaction history you want to retrieve. .PARAMETER Source Get the interaction history from a specific source. Valid values include: Word, Excel, Loop, M365App, Bing, Forms, OneNote, Outlook, PowerPoint, TeamsAiNotes, Channel, Chat, Meeting, WebChat, or Whiteboard. .PARAMETER StartDate Specifies the start date for the interaction history. Must be in ISO 8601 format: "YYYY-MM-DDThh:mm:ssZ" (e.g., "2024-09-09T16:48:35Z") .PARAMETER EndDate Specifies the end date for the interaction history. Must be in ISO 8601 format: "YYYY-MM-DDThh:mm:ssZ" (e.g., "2024-09-09T16:48:35Z") .EXAMPLE Get-aiInteractionHistory -UserId "user@contoso.com" -source Word -StartDate "2025-01-01" -EndDate "2025-01-31" Returns the Copilot interaction history for the specified user, filtered by the specified source and date range. .LINK https://learn.microsoft.com/en-us/graph/api/aiinteractionhistory-getallenterpriseinteractions?view=graph-rest-beta&tabs=http .OUTPUTS PSCustomObject #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$UserId, [Parameter(Mandatory = $false)] [ValidateSet("Word", "Excel", "Loop", "M365App", "Bing", "Forms", "OneNote", "Outlook", "PowerPoint", "TeamsAiNotes", "Channel", "Chat", "Meeting", "WebChat", "Whiteboard")] [string]$Source, [Parameter(Mandatory = $false)] [ValidatePattern("^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$")] [string]$StartDate, [Parameter(Mandatory = $false)] [ValidatePattern("^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$")] [string]$EndDate ) # Validate date parameters must be used together if (($PSBoundParameters.ContainsKey('StartDate') -and -not $PSBoundParameters.ContainsKey('EndDate')) -or ($PSBoundParameters.ContainsKey('EndDate') -and -not $PSBoundParameters.ContainsKey('StartDate'))) { throw "StartDate and EndDate parameters must be used together." } # Validate StartDate is before EndDate if ($PSBoundParameters.ContainsKey('StartDate') -and $PSBoundParameters.ContainsKey('EndDate')) { $startDateObj = [DateTime]::Parse($StartDate) $endDateObj = [DateTime]::Parse($EndDate) if ($startDateObj -ge $endDateObj) { throw "StartDate must be earlier than EndDate." } } # Define the mapping of source names to their corresponding values $sources = @{ Word = "IPM.SkypeTeams.Message.Copilot.Word" Excel = "IPM.SkypeTeams.Message.Copilot.Excel" Loop = "IPM.SkypeTeams.Message.Copilot.Loop" M365App = "IPM.SkypeTeams.Message.Copilot.M365App" Bing = "IPM.SkypeTeams.Message.Copilot.BizChat" Forms = "IPM.SkypeTeams.Message.Copilot.Forms" OneNote = "IPM.SkypeTeams.Message.Copilot.OneNote" Outlook = "IPM.SkypeTeams.Message.Copilot.Outlook" PowerPoint = "IPM.SkypeTeams.Message.Copilot.PowerPoint" TeamsAiNotes = "IPM.SkypeTeams.Message.TeamsCopilot.AiNotes.Teams" Channel = "IPM.SkypeTeams.Message.Copilot.Teams" Chat = "IPM.SkypeTeams.Message.Copilot.Teams" Meeting = "IPM.SkypeTeams.Message.Copilot.Teams" WebChat = "IPM.SkypeTeams.Message.Copilot.WebChat" Whiteboard = "IPM.SkypeTeams.Message.Copilot.Whiteboard" } # Only try to convert the source if it was provided if ($PSBoundParameters.ContainsKey('Source')) { try { $sourceValue = $sources[$Source] Write-Verbose "Source '$Source' mapped to value: $sourceValue" } catch { Write-Error "Invalid source specified. Valid sources are: $($sources.Keys -join ', ')" return } } # Check if none of the filter parameters are used if (-not $PSBoundParameters.ContainsKey('Source') -and -not $PSBoundParameters.ContainsKey('StartDate') -and -not $PSBoundParameters.ContainsKey('EndDate')) { } else { # create the filter string $filterParts = @() if ($PSBoundParameters.ContainsKey('Source')) { $filterParts += "appClass eq '$sourceValue'" } if ($PSBoundParameters.ContainsKey('StartDate')) { $filterParts += "createdDateTime gt $StartDate" } if ($PSBoundParameters.ContainsKey('EndDate')) { $filterParts += "createdDateTime lt $EndDate" } # Join all filter parts with 'and' operator $filterString = "?`$filter = " + ($filterParts -join " and ") Write-Verbose "Filter string: $filterString" } try { Write-Verbose "Retrieving Microsoft Copilot interaction history for user $UserId..." $uri = "/beta/copilot/users/$UserId/interactionHistory/getAllEnterpriseInteractions$filterString" $response = Invoke-MgGraphRequest -Method GET -uri $uri -OutputType PSObject | Select -ExpandProperty Value return $response } catch { if ($_.Exception.Message -match "403" -or $_.Exception.Message -match "Forbidden") { Write-Error "Access Forbidden: The Graph API permission Organization.Read.All is required. Make sure you have the appropriate administrator role and permissions. Error: $($_.Exception.Message)" } else { Write-Error $_ } return $null } } |