Alerts & Errors
Panther API alert operations
Overview
The Panther API supports the following alerting operations:
Listing your alerts and errors with optional filters
Fetching the details of a particular alert
Updating the status of one or more alerts
Adding a comment to an alert
Assigning and un-assigning a user to one or more alerts, by providing:
A user's ID
A user's email address
You can invoke Panther's API by using your Console's API Playground, or the GraphQL-over-HTTP API. Learn more about these methods on Panther API.
See the sections below for GraphQL queries, mutations, and end-to-end workflow examples around core alert and error operations.
Common alert and error operations
Below are some of the most common GraphQL alert and error operations in Panther. These examples demonstrate the documents you have to send using a GraphQL client (or curl
) to make a call to Panther's GraphQL API.
Listing your Alerts
The alerts
query requires an input
object containing createdAtAfter
and createdAtBefore
.
# `FirstPageOfAllAlerts` is a nickname for the operation
query FirstPageOfAllAlerts {
alerts(input: {
createdAtAfter: "2022-01-01T00:00:00.000Z"
createdAtBefore: "2023-01-01T00:00:00.000Z"
}) {
edges {
node { # you can ask for more alert-related fields here
id
title
severity
status
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Describing an Alert
query AlertDetails {
alert(id: "FAKE_ALERT_ID") {
id
title
severity
status
}
}
Getting Detection or System Error information from an Alert
query AlertDetails {
alert(id: "FAKE_ALERT_ID") {
id
title
severity
origin {
... on Detection {
id
name
}
... on SystemError {
relatedComponent
type
}
}
}
}
Updating the status of one or more Alerts
mutation UpdateAlertStatus {
updateAlertStatusById(
input: {
ids: ["FAKE_ALERT_ID_1","FAKE_ALERT_ID_2"]
status: CLOSED # notice how this isn't a string when hardcoded (it's an `enum`)
}
) {
alerts {
id
status
}
}
}
Adding a comment to an alert
mutation CreateAlertComment {
createAlertComment(
input: {
alertId: "FAKE_ALERT_ID"
body: "<p>This is HTML</p>"
format: HTML # can also be PLAIN_TEXT if you want HTML parsing disabled
}
) {
comment {
id
}
}
Assigning and un-assigning a user to one or more alerts by supplying a user ID
mutation UpdateAlertsAssigneeById {
updateAlertsAssigneeById(
input: {
assigneeId: "FAKE_USER_ID"
ids: ["FAKE_ALERT_ID_1","FAKE_ALERT_ID_2"]
}
) {
alerts {
assignee {
email
givenName
familyName
id
}
}
}
}
Assigning and un-assigning a user to one or more alerts by supplying a user email address
mutation UpdateAlertsAssigneeByEmail {
updateAlertsAssigneeByEmail(
input: {
assigneeEmail: "fake@email.com"
ids: ["FAKE_ALERT_ID_1","FAKE_ALERT_ID_2"]
}
) {
alerts {
assignee {
email
givenName
familyName
id
}
}
}
}
End-to-end examples
Below, we will build on the Common Operations examples to showcase an end-to-end flow.
Find a particular set of alerts and mark them as Resolved:
// npm install graphql graphql-request
import { GraphQLClient, gql } from 'graphql-request';
const client = new GraphQLClient(
'YOUR_PANTHER_API_URL',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' }
});
// `FindAlerts` is a nickname for the query. You can fully omit it.
const findAlerts = gql`
query FindAlerts($input: AlertsInput!) {
alerts(input: $input) {
edges {
node {
id
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
// `UpdateAlerts` is a nickname for the query. You can fully omit it.
const updateAlerts = gql`
mutation UpdateAlerts($input: UpdateAlertStatusByIdInput!) {
updateAlertStatusById(input: $input) {
alerts {
id
}
}
}
`;
(async () => {
try {
// an accumulator that holds all alerts that we fetch all pages
let allAlerts = [];
// a helper to know when to exit the loop
let hasMore = true;
// the pagination cursor
let cursor = null;
// Keep fetching pages until there are no more left
do {
const queryData = await client.request(findAlerts, {
input: {
severities: ["LOW"],
createdAtAfter: "2022-02-01T00:00:00.000Z",
createdAtBefore: "2022-03-01T00:00:00.000Z",
cursor
}
});
allAlerts = [
...allAlerts,
...queryData.alerts.edges.map((edge) => edge.node)
];
hasMore = queryData.alerts.pageInfo.hasNextPage;
cursor = queryData.alerts.pageInfo.endCursor;
} while (hasMore);
// Now update the alerts
if (!allAlerts.length) {
console.log("Could not find any alerts to resolve");
return;
}
const mutationData = await client.request(updateAlerts, {
input: {
ids: allAlerts.map((alert) => alert.id),
status: "RESOLVED"
}
});
console.log(
`Resolved ${mutationData.updateAlertStatusById.alerts.length} alert(s)!`
);
} catch (err) {
console.error(err.response);
}
})();
Last updated
Was this helpful?