Events
Retrieving Events via API
Rubrik events can be retrieved via API query for use in automation or reporting. Rubrik stores 90 days of events in Rubrik Security Cloud. If retention requirements are greater than 90 days, events can be pulled via API or pushed via webhooks to an external system. When querying for events, it's best to limit the time range and query as frequently as needed. Depending on the size of the environment, the queries can result in a very long running query due to the volume of events.
Workload Events
query {
activitySeriesConnection(filters: {
#lastUpdatedTimeGt: "2025-02-22T00:00:00Z"
#orgIds: ["288970b2-16a0-4c65-a5fa-b0c86f5af337"]
#lastActivityType: [BACKUP]
#objectType: [VMWARE_VM,LINUX_FILESET]
#severity: [SEVERITY_CRITICAL,SEVERITY_WARNING,SEVERITY_INFO]
#lastActivityStatus: [SUCCESS,PARTIAL_SUCCESS,FAILURE,CANCELED]
}) {
nodes {
fid
id
objectName
objectType
lastActivityType
lastActivityMessage
severity
lastUpdated
objectId
location
progress
failureReason
causeErrorCode
causeErrorMessage
causeErrorReason
causeErrorRemedy
activityConnection(first: 1) { # Gets the last activity in the activitySeries
nodes {
objectId
objectType
type
status
message
errorInfo
time
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
query="query { activitySeriesConnection(filters: { }) { nodes { fid id objectName objectType lastActivityType lastActivityMessage severity lastUpdated objectId location progress failureReason causeErrorCode causeErrorMessage causeErrorReason causeErrorRemedy activityConnection(first: 1) { nodes { objectId objectType type status message errorInfo time } } } pageInfo { hasNextPage endCursor } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
Audit Events
query {
userAuditConnection(
filters: {
timeGt: "1970-01-01T00:00:00Z"
#timeLt: "1970-01-01T00:00:00Z"
#auditType: [SLA_MODIFICATION]
#auditStatus: [SUCCESS]
#auditSeverity: [CRITICAL]
#auditObjectType: [VMWARE_VM]
}
) {
nodes {
auditType
cluster {
name
id
}
userName
ipAddress
message
objectName
objectId
objectType
orgName
orgId
severity
status
time
}
}
}
$query = New-RscQuery -GqlQuery userAuditConnection
$query.Var.filters = Get-RscType -Name UserAuditFilter
$query.Var.filters.timeGt = "2025-09-16T00:00:00Z"
#$query.Var.filters.auditType = @([RubrikSecurityCloud.Types.AuditType]::SLA_MODIFICATION)
#$query.Var.filters.auditStatus = @([RubrikSecurityCloud.Types.AuditStatus]::SUCCESS)
#$query.Var.filters.auditSeverity = @([RubrikSecurityCloud.Types.AuditSeverity]::CRITICAL)
#$query.Var.filters.auditObjectType = @([RubrikSecurityCloud.Types.AuditObjectType]::VMWARE_VM)
$query.Field.nodes = Get-RscType -Name UserAudit -InitialProperties `
auditType,`
cluster.name,cluster.id,`
userName,`
ipAddress,`
message,`
objectName,`
objectId,`
objectType,`
orgName,`
orgId,`
severity,`
status,`
time
$query.Invoke().nodes
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
query="query { userAuditConnection( filters: { timeGt: \\\"1970-01-01T00:00:00Z\\\" } ) { nodes { auditType cluster { name id } userName ipAddress message objectName objectId objectType orgName orgId severity status time } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
Pushing Events Using Webhooks
Webhooks provide a mechanism to push events via HTTP to an external system. Webhooks contain a JSON payload with details about the event. The default payload format is PagerDuty Common Event Format (PD-CEF). Custom JSON templates can also be created to meet the requirements of external systems that have specific payload requirements.
The webhook retry/backoff policy is as follows:
| Retry Count | Backoff Time |
|---|---|
| 1 | 1 second |
| 2 | 5 seconds |
| 3 | 10 seconds |
After 3 attempts, the event will be removed from the queue. The webhook will be auto-disabled if there are 25 consecutive failures.
Webhooks Overview Video
Default Webhook Payload Format
The following is an example webhook of a Rubrik event in the default format. For more detailed information on Rubrik webhooks, see the RSC User Guide
{
"summary":"Failed backup of vSphere VM 'sh1-EncryptMe-05-Group1'.",
"source":"Rubrik Security Cloud",
"severity":"critical",
"timestamp":"2024-07-18T06:39:40.46Z",
"class":"Backup",
"custom_details":{
"seriesId":"ccd7a8a5-4c58-4c88-bff9-7bdffddb6099",
"id":"c2b47274-6323-4025-b307-afed1cfb7574",
"type":"Event",
"objectId":"83c4a80a-4a57-5699-b399-651089135586",
"objectName":"sh1-EncryptMe-05-Group1",
"objectType":"VmwareVm",
"status":"Failure",
"clusterId":"6a271636-9392-4cba-90c5-bdbe227854ab",
"clusterName":"sh1-PaloAlto",
"eventName":"Snapshot.BackupFailed",
"errorId":"Snapshot.VmwareSnapshotError",
"errorCode":"",
"errorRemedy":"",
"errorReason":"",
"auditUserName":"",
"auditUserId":"",
"location":"sh1-paloalto-vcsa.rubrikdemo.com",
"url":"",
"customerID":"rubrik-gaia",
"logicalSizeInBytes":"",
"dataTransferredInBytes":"",
"effectiveThroughput":""
}
}
Building a Custom Webhook Payload Template
Custom Webhook templates are freeform JSON documents that can contain any variables that are available in the webhook payload. External systems may have specific payload requirements that require a custom template. Click the annotation icons in the code below for various ways to customize the webhook payload.
{
"customTitle": "{{.ActivityType}} - {{.Status}}", //(1)!
"message": "{{.Message}}",
"severity": "1", //(2)!
"timestamp": "{{.Time.UTC.Format \"2006-01-02T15:04:05Z07:00\"}}", //(3)!
"class": "{{.Class}}",
"aggregationKey": "{{.ActivitySeriesID}}",
"id": "{{.UUID}}",
"type": "{{.ActivityType}}",
"object": { //(4)!
"name": "{{.ObjectName}}",
"id": "{{.ObjectID}}",
"type": "{{.ObjectType}}",
"location": "{{.Location}}",
"cluster": {
"name": "{{.ClusterName}}",
"id": "{{.ClusterUUID}}"
}
},
"ErrorMessage": "{{.Error.Message}}" //(5)!
}
- Combine multiple variables and static text
- Static values can be included
- Custom time formats are supported
- JSON can be nested for complex payloads
- Accessing nested variable data
Event Webhook Payload Variables
The following variables are available for use in the webhook payload.
| Field | Description | Example | Variable |
|---|---|---|---|
| Message | The message of the event | "Failed backup of vSphere VM 'sh1-EncryptMe-05-Group1'." | {{.Message}} |
| Severity | The severity of the event | "critical" | {{.Severity}} |
| Time UTC | The time the event occurred | "2025-02-05 23:13:20.916705803 +0000 UTC" | {{.Time}} |
| Time RFC3339 | The time the event occurred | "2025-02-05T23:13:20Z" | {{.Time.UTC.Format "2006-01-02T15:04:05Z07:00"}} |
| Time RFC1123 | The time the event occurred | "Wed, 05 Feb 2025 23:13:20 GMT" | {{.Time.UTC.Format "Mon, 02 Jan 2006 15:04:05 GMT"}} |
| Time Unix | The time the event occurred | 1716051580 | {{.Time.Unix}} |
| Time Unix Milliseconds | The time the event occurred | 1716051580000 | {{.Time.UnixMilli}} |
| Class | The class of the event | "Backup" | {{.Class}} |
| Activity Series ID | The ID of the activity series. Use this for aggregation of related events. | "ccd7a8a5-4c58-4c88-bff9-7bdffddb6099" | {{.ActivitySeriesID}} |
| Activity ID | The ID of the activity | "c2b47274-6323-4025-b307-afed1cfb7574" | {{.UUID}} |
| Activity Type | The type of the activity | "Event" | {{.ActivityType}} |
| Status | The status of the activity | "Failure" | {{.Status}} |
| Object ID | The ID of the object | "83c4a80a-4a57-5699-b399-651089135586" | {{.ObjectID}} |
| Object Name | The name of the object | "sh1-EncryptMe-05-Group1" | {{.ObjectName}} |
| Object Type | The type of the object | "VmwareVm" | {{.ObjectType}} |
| Cluster ID | The ID of the cluster | "6a271636-9392-4cba-90c5-bdbe227854ab" | {{.ClusterUUID}} |
| Cluster Name | The name of the cluster | "sh1-PaloAlto" | {{.ClusterName}} |
| Location | The location of the object | "sh1-paloalto-vcsa.rubrikdemo.com" | {{.Location}} |
| URL | The URL for a restored file download for cloud native workloads | "https://example.com/" | {{.URL}} |
Audit Specific Webhook Payload Variables
Rubrik audit events have additional fields that are specific to audits.
| Field | Description | Example | Variable |
|---|---|---|---|
| Audit Type | The type of the audit | "User" | {{.AuditType}} |
| Audit Series ID | The ID of the audit series | "ccd7a8a5-4c58-4c88-bff9-7bdffddb6099" | {{.AuditSeriesID}} |
| UserName | The name of the user | "admin" | {{.UserName}} |
| UserID | The ID of the user | "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6" | {{.UserID}} |
| IPAddress | The IP address of the user | "192.168.1.1" | {{.IPAddress}} |
| UserNote | The note of the user | "This is a note" | {{.UserNote}} |
| OrgID | The ID of the organization | "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6" | {{.OrgID}} |
| AuditInfo | Audit Information in JSON Format | {"auditKey":"auditValue","details":{"action":"create"}} | {{.AuditInfo}} |
Formatting Dates and Times
Webhook templates format times using a reference timestamp rather than
placeholder tokens such as YYYY-MM-DD. To build a custom format, write out
this one specific moment in the layout you want, and Rubrik renders the event's
actual time in the same shape:
Each part of that reference timestamp is a marker for one component of the date.
The values are fixed, so 2006 always means the year and 15 always means the
24-hour hour, no matter where you place them.
| Component | Marker | Renders as |
|---|---|---|
| Year, four digit | 2006 |
2025 |
| Year, two digit | 06 |
25 |
| Month, number | 01 |
02 |
| Month, number without leading zero | 1 |
2 |
| Month, short name | Jan |
Feb |
| Month, full name | January |
February |
| Day, number | 02 |
05 |
| Day, number without leading zero | 2 |
5 |
| Weekday, short name | Mon |
Wed |
| Weekday, full name | Monday |
Wednesday |
| Hour, 24 hour clock | 15 |
23 |
| Hour, 12 hour clock | 03 |
11 |
| Minute | 04 |
13 |
| Second | 05 |
20 |
| Fractional seconds, three digits | .000 |
.916 |
| AM or PM | PM |
PM |
| Time zone name | MST |
UTC |
| Time zone offset | Z07:00 |
Z |
Anything in the layout that is not one of these markers is copied through as
literal text, which is how separators such as -, :, T and / work.
Using the event time 2025-02-05 23:13:20.916705803 +0000 UTC, these layouts
produce:
| Layout | Result |
|---|---|
{{.Time.UTC.Format "2006-01-02T15:04:05Z07:00"}} |
2025-02-05T23:13:20Z |
{{.Time.UTC.Format "2006-01-02T15:04:05.000Z07:00"}} |
2025-02-05T23:13:20.916Z |
{{.Time.UTC.Format "Mon, 02 Jan 2006 15:04:05 GMT"}} |
Wed, 05 Feb 2025 23:13:20 GMT |
{{.Time.UTC.Format "2006-01-02"}} |
2025-02-05 |
{{.Time.UTC.Format "01/02/2006 03:04:05 PM"}} |
02/05/2025 11:13:20 PM |
{{.Time.UTC.Format "Monday, January 2, 2006 at 15:04"}} |
Wednesday, February 5, 2025 at 23:13 |
Use the reference values exactly
The layout is not an example timestamp. Substituting a different date will
not produce an error, it will produce a wrong result. A layout of
"1970-01-01T00:00:00Z" renders as 9970-09-09T00:00:00Z, because the 1
in 1970 is read as the month marker. If a custom time format is producing
unexpected values, check it against the marker table above before anything
else.
Time zones
{{.Time}} is already UTC. Adding .UTC before .Format makes that
explicit and is recommended. The MST marker renders the zone name, which
for a UTC time is the literal text UTC. If the receiving system expects
GMT, write GMT directly into the layout as literal text, as in the
RFC 1123 example above.
Using Conditionals
Templates can include conditional logic, which is useful when the receiving system expects its own severity scale, or when a field should only appear on certain events.
A conditional opens with {{if}} and closes with {{end}}, with optional
{{else if}} and {{else}} branches:
Comparisons are written with the operator first, followed by the two values:
| Test | Syntax | Meaning |
|---|---|---|
| Equal | {{if eq .Status "Failure"}} |
Status is exactly Failure |
| Not equal | {{if ne .Status "Success"}} |
Status is anything but Success |
| Less than | {{if lt .Value 5}} |
Value is below 5 |
| Greater than | {{if gt .Value 5}} |
Value is above 5 |
| Not empty | {{if .ClusterName}} |
The field has a value |
| All must be true | {{if and (eq .Severity "critical") (eq .Status "Failure")}} |
Both conditions hold |
| Any may be true | {{if or (eq .Status "Failure") (eq .Status "PartialSuccess")}} |
Either condition holds |
| Negate | {{if not (eq .Status "Success")}} |
The condition does not hold |
Values being compared are case sensitive, and string values must be quoted.
Wrap each condition in parentheses when combining them with and, or or
not.
{
"title": "{{.ActivityType}} - {{.Status}}",
"message": "{{.Message}}",
"priority": "{{if eq .Severity \"critical\"}}P1{{else if eq .Severity \"warning\"}}P3{{else}}P5{{end}}", //(1)!
"pageOnCall": "{{if and (eq .Severity \"critical\") (eq .Status \"Failure\")}}yes{{else}}no{{end}}", //(2)!
"objectName": "{{.ObjectName}}",
"cluster": "{{if .ClusterName}}{{.ClusterName}}{{else}}Rubrik Security Cloud{{end}}" //(3)!
{{if .Error.Message}}, //(4)!
"error": {
"code": "{{.Error.ErrorCode}}",
"reason": "{{.Error.Reason}}",
"remedy": "{{.Error.Remedy}}"
}
{{end}}
}
- Map Rubrik severity onto the priority scale the receiving system expects
- Conditions can be combined with
and,orandnot - Supply a fallback when a field may be empty
- Include an entire block only when it is relevant
Keep the JSON valid
A conditional that adds or removes a whole field has to account for the comma that separates it from the previous field. Put the comma inside the conditional, as in annotation 4 above, so that it disappears along with the field. A trailing comma left behind by an omitted block is the most common reason a custom template is rejected by the receiving system.
Use the preview in the webhook configuration to confirm the rendered payload is valid JSON before saving.
Pre-Built Webhook Templates
Ready-made templates and setup guides for specific tools, such as ServiceNow and Datadog, are under Send Events to Third-Party Tools. That section also covers which events to subscribe to and how to tell a real problem from routine activity, which applies to any destination.
Managing Webhook Subscriptions
Webhook subscriptions can be managed manually via the RSC console, or automatically via RSC API.
Retrieving Webhook Subscriptions via API
query {
allWebhooksV2 {
name
id
status
authType
createdBy
createdAt
updatedAt
url
subscriptionType {
auditSubscription {
auditTypes
isSubscribedToAllAudits
isSubscribedToAllObjectTypes
objectTypes
severities
templateInfo {
customTemplate
templateId
}
}
eventSubscription {
eventTypes
isSubscribedToAllEvents
isSubscribedToAllObjectTypes
objectTypes
severities
templateInfo {
customTemplate
templateId
}
}
}
description
id
lastFailedErrorInfo {
errorMessage
statusCode
}
}
}
$query = New-RscQuery -GqlQuery allWebhooksV2
$query.field = Get-RscType -Name WebhookV2 -InitialProperties `
Name, `
Id, `
Status, `
AuthType, `
ProviderType, `
CreatedAt, `
CreatedBy, `
Description, `
UpdatedAt, `
Url, `
LastFailedErrorInfo, `
SubscriptionType.eventSubscription.objectTypes, `
SubscriptionType.eventSubscription.severities, `
SubscriptionType.eventSubscription.eventTypes, `
SubscriptionType.eventSubscription.isSubscribedToAllEvents, `
SubscriptionType.eventSubscription.isSubscribedToAllObjectTypes, `
SubscriptionType.eventSubscription.templateInfo.customTemplate, `
SubscriptionType.eventSubscription.templateInfo.templateId, `
SubscriptionType.auditSubscription.objectTypes, `
SubscriptionType.auditSubscription.auditTypes, `
SubscriptionType.auditSubscription.severities, `
SubscriptionType.auditSubscription.isSubscribedToAllAudits, `
SubscriptionType.auditSubscription.isSubscribedToAllObjectTypes, `
SubscriptionType.auditSubscription.templateInfo.customTemplate, `
SubscriptionType.auditSubscription.templateInfo.templateId
$query.Invoke()
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
query="query { allWebhooksV2 { name id status authType createdBy createdAt updatedAt url subscriptionType { auditSubscription { auditTypes isSubscribedToAllAudits isSubscribedToAllObjectTypes objectTypes severities templateInfo { customTemplate templateId } } eventSubscription { eventTypes isSubscribedToAllEvents isSubscribedToAllObjectTypes objectTypes severities templateInfo { customTemplate templateId } } } description id lastFailedErrorInfo { errorMessage statusCode } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql
Creating a Webhook Subscription via API
mutation {
createWebhookV2(input: {
payload: {
name: "example"
description: "example with custom template and auth"
url: "https://example.com"
subscriptionType: {
eventSubscription: {
objectTypes: []
isSubscribedToAllObjectTypes: true
eventTypes: [BACKUP,ANOMALY]
severities: [SEVERITY_CRITICAL]
templateInfo: {
customTemplate: "{ \n \"custom_key\": \"{{.Message}}\" \n }"
}
}
}
providerType: CUSTOM
authInfo: {
authType: CUSTOM_HEADER
customHeaders: {
headerKey: "Authorization"
headerValue: "Bearer Example123"
}
}
}
}) {
webhook {
name
id
status
}
errorInfo {
errorMessage
statusCode
}
}
}
$query = New-RscMutation -GqlMutation createWebhookV2
$query.var.input = Get-RscType -name CreateWebhookV2Input
$query.var.input.payload = Get-RscType -name WebhookPayload
$query.var.input.payload.name = "example"
$query.var.input.payload.description = "example with custom template and auth"
$query.var.input.payload.url = "https://example.com"
$query.var.input.payload.subscriptionType = Get-RscType -name WebhookSubscriptionTypeV2Input
$query.var.input.payload.subscriptionType.eventSubscription = Get-RscType -name WebhookEventSubscriptionInput
$query.var.input.payload.subscriptionType.eventSubscription.objectTypes = @()
$query.var.input.payload.subscriptionType.eventSubscription.isSubscribedToAllObjectTypes = $true
$query.var.input.payload.subscriptionType.eventSubscription.eventTypes = @([RubrikSecurityCloud.Types.EventType]::BACKUP, [RubrikSecurityCloud.Types.EventType]::ANOMALY)
$query.var.input.payload.subscriptionType.eventSubscription.severities = @([RubrikSecurityCloud.Types.EventSeverity]::SEVERITY_CRITICAL)
$query.var.input.payload.subscriptionType.eventSubscription.templateInfo = Get-RscType -name WebhookTemplateInfoInput
$query.var.input.payload.subscriptionType.eventSubscription.templateInfo.customTemplate = "{ `n `"custom_key`": `"{{.Message}}`" `n }"
$query.var.input.payload.providerType = [RubrikSecurityCloud.Types.ProviderTypeV2]::CUSTOM
$query.var.input.payload.authInfo = Get-RscType -name WebhookAuthInfoV2Input
$query.var.input.payload.authInfo.authType = [RubrikSecurityCloud.Types.AuthenticationTypeV2]::CUSTOM_HEADER
$query.var.input.payload.authInfo.customHeaders = Get-RscType -name CustomHeaderInput
$query.var.input.payload.authInfo.customHeaders.headerKey = "Authorization"
$query.var.input.payload.authInfo.customHeaders.headerValue = "Bearer Example123"
$query.Invoke()
#!/bin/bash
# RSC_TOKEN="YOUR_RSC_ACCESS_TOKEN"
query="mutation { createWebhookV2(input: { payload: { name: \\\"example\\\" description: \\\"example with custom template and auth\\\" url: \\\"https://example.com\\\" subscriptionType: { eventSubscription: { objectTypes: [] isSubscribedToAllObjectTypes: true eventTypes: [BACKUP,ANOMALY] severities: [SEVERITY_CRITICAL] templateInfo: { customTemplate: \\\"{ \n \\\\"custom_key\\\\": \\\\"{{.Message}}\\\\" \n }\\\" } } } providerType: CUSTOM authInfo: { authType: CUSTOM_HEADER customHeaders: { headerKey: \\\"Authorization\\\" headerValue: \\\"Bearer Example123\\\" } } } }) { webhook { name id status } errorInfo { errorMessage statusCode } } }"
# Execute the GraphQL query with curl
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $RSC_TOKEN" \
-d "{\"query\": \"$query\"}" \
https://example.my.rubrik.com/api/graphql