From f28ab7dd48399d8bc069ae39e7e6c49d888fc8d2 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 30 Sep 2025 11:03:27 -0500 Subject: [PATCH 1/3] Adds Get-VerkadaAccessEvents function Adds a new function to retrieve Verkada Access Control events. This function allows users to query access events within a specified time range and for specific event types, sites, devices, or users. It leverages the Verkada API to fetch the events and returns them as PowerShell objects. The function includes error handling and the option to write errors to a file. Also updates the module manifest to include the new function and its alias. --- .../Public/Get-VerkadaAccessEvents.ps1 | 116 ++++++++++++++++++ verkadaModule/verkadaModule.psd1 | 15 +-- 2 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 verkadaModule/Public/Get-VerkadaAccessEvents.ps1 diff --git a/verkadaModule/Public/Get-VerkadaAccessEvents.ps1 b/verkadaModule/Public/Get-VerkadaAccessEvents.ps1 new file mode 100644 index 0000000..528ed83 --- /dev/null +++ b/verkadaModule/Public/Get-VerkadaAccessEvents.ps1 @@ -0,0 +1,116 @@ +function Get-VerkadaAccessEvents{ + <# + .SYNOPSIS + Returns Verkada Access Control events using https://apidocs.verkada.com/reference/geteventsviewv1 + + .DESCRIPTION + Returns events for an organization within a specified time range. + The org_id and reqired token can be directly submitted as parameters, but is much easier to use Connect-Verkada to cache this information ahead of time and for subsequent commands. + + .LINK + https://github.com/bepsoccer/verkadaModule/blob/master/docs/function-documentation/Get-VerkadaAccessEvents.md + + .EXAMPLE + Get-VerkadaAccessEvents + This will return all the access events from 1 hour in the past until present. The org_id and token will be populated from the cached created by Connect-Verkada. + + .EXAMPLE + Get-VerkadaAccessEvents -start_time 'January 1, 2025 9:00:00AM' -end_time 'February 8, 2025 10:30:00PM' -org_id '7cd47706-f51b-4419-8675-3b9f0ce7c12d' -x_verkada_auth_api 'sd78ds-uuid-of-verkada-token' + This will return all the access events from Jan 1 at 9am to Feb 8 at 10:30pm. The org_id and token are submitted as parameters in the call. + #> + [CmdletBinding(PositionalBinding = $true)] + [Alias("Get-VrkdaAcEvnts","gt-VrkdaAcEvnts")] + param ( + #The UUID of the organization the user belongs to + [Parameter(ValueFromPipelineByPropertyName = $true)] + [ValidateNotNullOrEmpty()] + [ValidatePattern('^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$')] + [String]$org_id = $Global:verkadaConnection.org_id, + #The public API token obatined via the Login endpoint to be used for calls that hit the public API gateway + [Parameter()] + [ValidateNotNullOrEmpty()] + [String]$x_verkada_auth_api = $Global:verkadaConnection.x_verkada_auth_api, + #The region of the public API to be used + [Parameter()] + [ValidateSet('api','api.eu','api.au')] + [String]$region='api', + #The optional start time for the date range of events + [Parameter()] + [datetime]$start_time, + #The optional end time for the date range of events + [Parameter()] + [datetime]$end_time, + #The optional event type/s for the events + [Parameter()] + [string[]]$event_type, + #The optional site_id/s for the events + [Parameter()] + [string[]]$side_id, + #The optional device_id/s for the events + [Parameter()] + [string[]]$device_id, + #The optional user_id/s for the events + [Parameter()] + [string[]]$user_id, + #Switch to write errors to file + [Parameter()] + [switch]$errorsToFile + ) + + begin { + $url = "https://$($region).verkada.com/events/v1/access" + #parameter validation + if ([string]::IsNullOrEmpty($org_id)) {throw "org_id is missing but is required!"} + if ([string]::IsNullOrEmpty($x_verkada_auth_api)) {throw "x_verkada_auth_api is missing but is required!"} + $myErrors = @() + } #end begin + + process { + $body_params = @{} + $query_params = @{} + + if (!([string]::IsNullOrEmpty($start_time))){ + $start_time_epoch = (New-TimeSpan -Start (Get-Date "01/01/1970") -End $start_time).TotalSeconds + $query_params.start_time = $start_time_epoch + } + if (!([string]::IsNullOrEmpty($end_time))){ + $end_time_epoch = (New-TimeSpan -Start (Get-Date "01/01/1970") -End $end_time).TotalSeconds + $query_params.end_time = $end_time_epoch + } + if (!([string]::IsNullOrEmpty($event_type))){$query_params.event_type = $event_type -join ','} + if (!([string]::IsNullOrEmpty($site_id))){$query_params.site_ide = $site_id -join ','} + if (!([string]::IsNullOrEmpty($device_id))){$query_params.device_id = $device_id -join ','} + if (!([string]::IsNullOrEmpty($user_id))){$query_params.user_id = $user_id -join ','} + + try { + $response = Invoke-VerkadaRestMethod $url $org_id $x_verkada_auth_api $query_params -body_params $body_params -method GET -pagination -page_size 200 -propertyName 'events' + return $response.events + } + catch [Microsoft.PowerShell.Commands.HttpResponseException] { + $err = $_.ErrorDetails | ConvertFrom-Json + $errorMes = $_ | Convertto-Json -WarningAction SilentlyContinue + $err | Add-Member -NotePropertyName StatusCode -NotePropertyValue (($errorMes | ConvertFrom-Json -Depth 100 -WarningAction SilentlyContinue).Exception.Response.StatusCode) -Force + $msg = "$($err.StatusCode) - $($err.message)" + $msg += ": $(($query_params + $body_params) | ConvertTo-Json -Compress)" + Write-Error $msg + $myErrors += $msg + $msg = $null + } + catch [VerkadaRestMethodException] { + $msg = $_.ToString() + $msg += ": $(($query_params + $body_params) | ConvertTo-Json -Compress)" + Write-Error $msg + $myErrors += $msg + $msg = $null + } + } #end process + + end { + if ($errorsToFile.IsPresent){ + if (![string]::IsNullOrEmpty($myErrors)){ + Get-Date | Out-File ./errors.txt -Append + $myErrors | Out-File ./errors.txt -Append + } + } + } #end end +} #end function \ No newline at end of file diff --git a/verkadaModule/verkadaModule.psd1 b/verkadaModule/verkadaModule.psd1 index 62d1fee..4d9969b 100644 --- a/verkadaModule/verkadaModule.psd1 +++ b/verkadaModule/verkadaModule.psd1 @@ -3,7 +3,7 @@ # # Generated by: Verkada SE Community # -# Generated on: 05/14/2025 +# Generated on: 9/30/2025 # @{ @@ -80,9 +80,10 @@ FunctionsToExport = 'Add-VerkadaAccessGroup', 'Add-VerkadaAccessSiteAdmin', 'Enable-VerkadaAccessUserLicensePlate', 'Find-VerkadaCommandUser', 'Find-VerkadaUserId', 'Get-Otp', 'Get-VerkadaAccessCredential', 'Get-VerkadaAccessDoorConfigReport', 'Get-VerkadaAccessDoors', - 'Get-VerkadaAccessDoorSchedules', 'Get-VerkadaAccessGroup', - 'Get-VerkadaAccessLevels', 'Get-VerkadaAccessSite', - 'Get-VerkadaAccessUser', 'Get-VerkadaAccessUserProfilePicture', + 'Get-VerkadaAccessDoorSchedules', 'Get-VerkadaAccessEvents', + 'Get-VerkadaAccessGroup', 'Get-VerkadaAccessLevels', + 'Get-VerkadaAccessSite', 'Get-VerkadaAccessUser', + 'Get-VerkadaAccessUserProfilePicture', 'Get-VerkadaAccessUserReport', 'Get-VerkadaAccessUserViaGraphql', 'Get-VerkadaAlarmsDevices', 'Get-VerkadaAlarmsSiteConfig', 'Get-VerkadaAlarmsSiteContacts', 'Get-VerkadaCameraConfig', @@ -133,9 +134,9 @@ AliasesToExport = 'a-VrkdaAcGrp', 'Add-VrkdaAcGrp', 'a-VrkdaAcUsrCrd', 'Add-VrkdaWrkEmp', 'd-VrkdaAcUsrCrd', 'Disable-VrkdaAcUsrCrd', 'd-VrkdaAcUsrLPR', 'Disable-VrkdaAcUsrLPR', 'e-VrkdaAcUsrCrd', 'Enable-VrkdaAcUsrCrd', 'e-VrkdaAcUsrLPR', 'Enable-VrkdaAcUsrLPR', - 'otp', 'Get-VrkdaAcGrp', 'gt-VrkdaAcGrp', 'Get-VrkdaAcUsr', - 'gt-VrkdaAcUsr', 'ep-VrkdaAcUsrPrflPic', - 'Export-VerkadaAccessUserProfilePicture', + 'otp', 'Get-VrkdaAcEvnts', 'gt-VrkdaAcEvnts', 'Get-VrkdaAcGrp', + 'gt-VrkdaAcGrp', 'Get-VrkdaAcUsr', 'gt-VrkdaAcUsr', + 'ep-VrkdaAcUsrPrflPic', 'Export-VerkadaAccessUserProfilePicture', 'Export-VrkdaAcUsrPrflPic', 'g-VrkdaAcUsrPrflPic', 'Get-VrkdaAcUsrPrflPic', 'g-VrkdAlrmDevs', 'Get-VrkdAlrmDevs', 'Get-VerkadaCameraSite', 'Get-VrkdaCmdUsr', 'gt-VrkdaCmdUsr', From 1772897b83081eadda0f0d578df470a8e9005a44 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 30 Sep 2025 11:12:17 -0500 Subject: [PATCH 2/3] Returns full response from access events Updates the function to return the entire response object instead of just the 'events' property. This provides more flexibility for users who need access to other metadata included in the response. --- verkadaModule/Public/Get-VerkadaAccessEvents.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verkadaModule/Public/Get-VerkadaAccessEvents.ps1 b/verkadaModule/Public/Get-VerkadaAccessEvents.ps1 index 528ed83..9a74f51 100644 --- a/verkadaModule/Public/Get-VerkadaAccessEvents.ps1 +++ b/verkadaModule/Public/Get-VerkadaAccessEvents.ps1 @@ -84,7 +84,7 @@ function Get-VerkadaAccessEvents{ try { $response = Invoke-VerkadaRestMethod $url $org_id $x_verkada_auth_api $query_params -body_params $body_params -method GET -pagination -page_size 200 -propertyName 'events' - return $response.events + return $response } catch [Microsoft.PowerShell.Commands.HttpResponseException] { $err = $_.ErrorDetails | ConvertFrom-Json From a1a8e6f621a3b1dc0cf7319d23d76cc4522e4d47 Mon Sep 17 00:00:00 2001 From: bepsoccer <26012546+bepsoccer@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:35:43 +0000 Subject: [PATCH 3/3] Bumping release to 0.9.6 --- .../Get-VerkadaAccessEvents.md | 219 ++++++++++++++++++ docs/reference.md | 1 + verkadaModule/verkadaModule.psd1 | 4 +- 3 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 docs/function-documentation/Get-VerkadaAccessEvents.md diff --git a/docs/function-documentation/Get-VerkadaAccessEvents.md b/docs/function-documentation/Get-VerkadaAccessEvents.md new file mode 100644 index 0000000..a15bf20 --- /dev/null +++ b/docs/function-documentation/Get-VerkadaAccessEvents.md @@ -0,0 +1,219 @@ +--- +external help file: verkadaModule-help.xml +Module Name: verkadaModule +online version: https://github.com/bepsoccer/verkadaModule/blob/master/docs/function-documentation/Get-VerkadaAccessEvents.md +schema: 2.0.0 +--- + +# Get-VerkadaAccessEvents + +## SYNOPSIS +Returns Verkada Access Control events using https://apidocs.verkada.com/reference/geteventsviewv1 + +## SYNTAX + +``` +Get-VerkadaAccessEvents [[-org_id] ] [[-x_verkada_auth_api] ] [[-region] ] + [[-start_time] ] [[-end_time] ] [[-event_type] ] [[-side_id] ] + [[-device_id] ] [[-user_id] ] [-errorsToFile] [-ProgressAction ] + [] +``` + +## DESCRIPTION +Returns events for an organization within a specified time range. +The org_id and reqired token can be directly submitted as parameters, but is much easier to use Connect-Verkada to cache this information ahead of time and for subsequent commands. + +## EXAMPLES + +### EXAMPLE 1 +``` +Get-VerkadaAccessEvents +This will return all the access events from 1 hour in the past until present. The org_id and token will be populated from the cached created by Connect-Verkada. +``` + +### EXAMPLE 2 +``` +Get-VerkadaAccessEvents -start_time 'January 1, 2025 9:00:00AM' -end_time 'February 8, 2025 10:30:00PM' -org_id '7cd47706-f51b-4419-8675-3b9f0ce7c12d' -x_verkada_auth_api 'sd78ds-uuid-of-verkada-token' +This will return all the access events from Jan 1 at 9am to Feb 8 at 10:30pm. The org_id and token are submitted as parameters in the call. +``` + +## PARAMETERS + +### -org_id +The UUID of the organization the user belongs to + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: $Global:verkadaConnection.org_id +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -x_verkada_auth_api +The public API token obatined via the Login endpoint to be used for calls that hit the public API gateway + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: $Global:verkadaConnection.x_verkada_auth_api +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -region +The region of the public API to be used + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: Api +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -start_time +The optional start time for the date range of events + +```yaml +Type: DateTime +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -end_time +The optional end time for the date range of events + +```yaml +Type: DateTime +Parameter Sets: (All) +Aliases: + +Required: False +Position: 5 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -event_type +The optional event type/s for the events + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 6 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -side_id +The optional site_id/s for the events + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 7 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -device_id +The optional device_id/s for the events + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 8 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -user_id +The optional user_id/s for the events + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 9 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -errorsToFile +Switch to write errors to file + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction +{{ Fill ProgressAction Description }} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS + +[https://github.com/bepsoccer/verkadaModule/blob/master/docs/function-documentation/Get-VerkadaAccessEvents.md](https://github.com/bepsoccer/verkadaModule/blob/master/docs/function-documentation/Get-VerkadaAccessEvents.md) + diff --git a/docs/reference.md b/docs/reference.md index 99735ca..e9ee569 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -22,6 +22,7 @@ * [Get-VerkadaAccessDoorConfigReport](function-documentation/Get-VerkadaAccessDoorConfigReport.md) * [Get-VerkadaAccessDoors](function-documentation/Get-VerkadaAccessDoors.md) * [Get-VerkadaAccessDoorSchedules](function-documentation/Get-VerkadaAccessDoorSchedules.md) +* [Get-VerkadaAccessEvents](function-documentation/Get-VerkadaAccessEvents.md) * [Get-VerkadaAccessGroup](function-documentation/Get-VerkadaAccessGroup.md) * [Get-VerkadaAccessLevels](function-documentation/Get-VerkadaAccessLevels.md) * [Get-VerkadaAccessSite](function-documentation/Get-VerkadaAccessSite.md) diff --git a/verkadaModule/verkadaModule.psd1 b/verkadaModule/verkadaModule.psd1 index 42893df..eca287b 100644 --- a/verkadaModule/verkadaModule.psd1 +++ b/verkadaModule/verkadaModule.psd1 @@ -3,7 +3,7 @@ # # Generated by: Verkada SE Community # -# Generated on: 9/30/2025 +# Generated on: 09/30/2025 # @{ @@ -12,7 +12,7 @@ RootModule = 'verkadaModule.psm1' # Version number of this module. -ModuleVersion = '0.9.5' +ModuleVersion = '0.9.6' # Supported PSEditions CompatiblePSEditions = 'Desktop', 'Core'