Skip to content

Getting started

Overview

The Account Health Check API allow you to get a health report for your Sophos Central account. This shows whether you're making the best use of your Sophos security products. See Account Health Check.

Pre-requisites

You must have a set of API credentials (service principal) to be able to call the Account Health Check API. For more information refer to the appropriate quick start guide:

Making API requests

You can make the API calls in the next few sections using cURL. Follow the instructions on cURL's website to install this tool.

When using curl, a request to the Account Health Check API has the following general form:

curl -X<method> -H "Authorization: Bearer <jwt>" -H "X-Tenant-ID: <tenant-id>" <data-region>/<path>

The command includes the following placeholders:

  • <method>: The request method. For the account health check operation, this is GET, while for the snooze operation it is POST.
  • <tenant-id>: The ID of the tenant you want to query.
  • <jwt>: The JWT access token returned when the IDP authenticates the service principal.
  • <data-region>: The regional API host in the data region where the tenant data is located.
  • <path>: The request path for the API operation, for example, account-health-check/v1/health-check.

For brevity, the API descriptions in this guide only specify the request method and path. For example:

GET /account-health-check/v1/health-check

To make an actual API request, you must expand this to the full form shown above.

All API requests return HTTP status code 200 or 201 when successful.

Terminology

Sophos Central performs the following checks on your account to determine its health:

  • Protection check: Checks if all your licensed protection software is installed on computers and servers.
  • Policy check: Checks if your Threat Protection and Server Threat Protection policies use the recommended settings.
  • Exclusions check: Checks if over-permissive exclusions in your global exclusions and your Threat Protection or Server Threat Protection policy exclusions pose a security risk.
  • Tamper protection check: Checks if tamper protection is turned on for your computers and servers.

Get account health check report

Call this API to get a health report for the tenant.

GET /account-health-check/v1/health-check

Response: This returns a full health report for the tenant as below (JavaScript-style comments added for annotation).

{
  "tenant": {
    "id": "fd16b47f-31b7-4633-95a4-90dff5a35c29"
  },
  "endpoint": {
    "protection": {                 // Protection check
      "computer": {
        "score": 88,
        "total": 100,
        "notFullyProtected": 12,
        "snoozed": false
      },
      "server": {
        "score": 94,
        "total": 50,
        "notFullyProtected": 3,
        "snoozed": false
      }
    },
    "policy": {                     // Policy check
      "computer": {
        "threat-protection": {      // Policy type. Only Threat Protection policies are assessed
          "score": 50,
          "total": 2,               // Total count of policies of this type
          "notOnRecommended": 1,    // Count of policies with settings which are not as recommended
          "snoozed": false,
          "policies": [             // Only includes policies with settings that are not as recommended
            {
              "id": "56756263-42ef-4ac6-99a5-5e007084122a",
              "name": "My custom TP policy",
              "lockedByManagingAccount": false, // Whether the policy is managed by a partner or organization
              "notOnRecommended": 1             // Count of settings in the policy that are not as recommended
            }
          ]
        }
      },
      "server": {
        "server-threat-protection": {
          // Same as for computer/threat-protection
        }
      }
    },
    "exclusions": {                 // Exclusions check
      "policy": {
        "computer": {
          "score": 100,
          "total": 6,
          "numberOfSecurityRisks": 0,
          "snoozed": false
        },
        "server": {
          "score": 90,
          "total": 10,
          "numberOfSecurityRisks": 1,
          "snoozed": false,
          "exclusions": [           // Only includes exclusions that pose a security risk
            {
              "policyName": "Base Policy",
              "policyId": "56756263-42ef-4ac6-99a5-5e007084122a",
              "lockedByManagingAccount": true,
              "scanningExclusions": [
                {
                  "value": "C:\\",
                  "scanMode": "onDemandAndOnAccess",
                  "type": "pua",
                  "securityReasonCode": "A_REASON_CODE"
                }
              ]
            }
          ]
        }
      },
      "global": {
        "score": 90,
        "total": 10,
        "numberOfSecurityRisks": 1,
        "lockedByManagingAccount": true, // Whether the settings are managed by a partner or organization
        "snoozed": false,
        "scanningExclusions": [
          {
            "value": "C:\\",
            "scanMode": "onDemandAndOnAccess",
            "type": "web",
            "securityReasonCode": "A_REASON_CODE"
          }
        ]
      }
    },
    "tamperProtection": {           // Tamper protection check
      "computer": {
        "score": 88,
        "total": 100,
        "disabled": 12,
        "snoozed": false
      },
      "server": {
        "score": 96,
        "total": 50,
        "disabled": 3,
        "snoozed": false
      },
      "global": false,              // Whether global tamper protection is turned on or off
      "globalDetail": {
        "score": 0,
        "enabled": false,
        "snoozed": false
        }
      }
    }
  }
}

Parameters

Checks

Call this API with the checks parameter to get a health report only for the specified checks.

GET /account-health-check/v1/health-check?checks=exclusions,protection

Response: This returns a health report containing results only for the checks listed in the parameter for the tenant as below (JavaScript-style comments added for annotation).

{
  "endpoint": {
    "protection": {
      // Protection check report
    },
    "exclusions": {
      // Exclusions check report
    }
  }
}

Products

Call this API with the products parameter to get a health report only for the specified products.

GET /account-health-check/v1/health-check?products=endpoint

Response: This returns a health report containing results only for all checks contained in the products requested in the parameter for the tenant as below (JavaScript-style comments added for annotation).

{
  "endpoint": {
    "protection": {
      // Protection check report
    },
    "tamperProtection": {
      // Tamper Protection check report
    },
    "policy": {
      // Policy check report
    },
    "exclusions": {
      // Exclusions check report
    }
  }
}

Calling this API with both the products parameter and the checks parameter is invalid.

Scores for each check

We calculate a score for each check, which is based on the number of devices or settings that comply with our recommendations.

  • Scores can range from 0 to 100.
  • Any score less than 100 indicates that you can improve security.
  • Snoozing a check doesn't affect your scores.

Here's how we calculate the scores for each type of health check.

Protection installed score calculation

For example, if you have 1000 devices and 900 have all the protection you're licensed for, you see a score of 90.

Tamper protection score calculation

Global tamper protection is either turned on (score 100) or turned off (score 0).

If global tamper protection is off, no devices have this protection. The endpoint and server checks show a score of 0. When you turn global tamper protection on, those checks show the percentage of devices with protection turned on locally.

Threat Protection policy settings score calculation

In each policy, we deduct 10 from the score for each setting that doesn't match our recommended setting. So if a policy has two of these settings, we deduct 20, and the score is 80.

If you have multiple policies of the same type (for example, endpoint threat protection policy), we take the average score of those policies.

Some policy options don't have a recommended setting. We ignore those in our checks.

Exclusions score calculation

In each policy, we deduct 20 from the score for each insecure exclusion. So if a policy has two insecure exclusions, we deduct 40, and the score is 60.

If you have multiple policies of the same type (for example, endpoint exclusions), we take the average score of those policies.

For Global exclusions, we calculate the score as follows:

We deduct 20 from the score for each insecure exclusion. So if you have two insecure exclusions, we deduct 40, and the score is 60.

Note: We only check for exclusions that are a significant security risk. Even if your exclusions health checks show a high score, regularly check that your exclusions are necessary and safe.

Score comparisons

Call this API to see how your scores compare with other organizations.

GET /account-health-check/v1/scores/regional

Response: This returns a list of bands (where upper and lower bound is the total number of devices) containing the average score for each check within that band, as found in the account health check results we have for your data region (JavaScript-style comments added for annotation).

{
    "bands": [
        {
            "lowerBound": 1,
            "upperBound": 49,
            "endpoint": {
                "protectionComputerScore": 92,
                "protectionServerScore": 92,
                "policyThreatProtectionComputerScore": 98,
                "policyThreatProtectionServerScore": 94,
                "exclusionsGlobalScore": 97,
                "exclusionsComputerScore": 98,
                "exclusionsServerScore": 99,
                "tamperProtectionGlobalScore": 95,
                "tamperProtectionComputerScore": 90,
                "tamperProtectionServerScore": 90
            }
        },
        {
            "lowerBound": 50,
            "upperBound": 249,
            "endpoint": {
                "protectionComputerScore": 93,
                "protectionServerScore": 93,
                "policyThreatProtectionComputerScore": 98,
                "policyThreatProtectionServerScore": 93,
                "exclusionsGlobalScore": 95,
                "exclusionsComputerScore": 98,
                "exclusionsServerScore": 98,
                "tamperProtectionGlobalScore": 95,
                "tamperProtectionComputerScore": 93,
                "tamperProtectionServerScore": 92
            }
        },
        {
            "lowerBound": 250,
            "upperBound": 999,
            "endpoint": {
                "protectionComputerScore": 95,
                "protectionServerScore": 96,
                "policyThreatProtectionComputerScore": 98,
                "policyThreatProtectionServerScore": 93,
                "exclusionsGlobalScore": 94,
                "exclusionsComputerScore": 97,
                "exclusionsServerScore": 98,
                "tamperProtectionGlobalScore": 96,
                "tamperProtectionComputerScore": 95,
                "tamperProtectionServerScore": 94
            }
        },
        {
            "lowerBound": 1000,
            "upperBound": 4999,
            "endpoint": {
                "protectionComputerScore": 94,
                "protectionServerScore": 94,
                "policyThreatProtectionComputerScore": 98,
                "policyThreatProtectionServerScore": 92,
                "exclusionsGlobalScore": 95,
                "exclusionsComputerScore": 96,
                "exclusionsServerScore": 97,
                "tamperProtectionGlobalScore": 96,
                "tamperProtectionComputerScore": 94,
                "tamperProtectionServerScore": 93
            }
        },
        {
            "lowerBound": 5000,
            "upperBound": 19999,
            "endpoint": {
                "protectionComputerScore": 94,
                "protectionServerScore": 93,
                "policyThreatProtectionComputerScore": 98,
                "policyThreatProtectionServerScore": 92,
                "exclusionsGlobalScore": 95,
                "exclusionsComputerScore": 96,
                "exclusionsServerScore": 96,
                "tamperProtectionGlobalScore": 96,
                "tamperProtectionComputerScore": 95,
                "tamperProtectionServerScore": 94
            }
        },
        {
            "lowerBound": 20000, // no upperBound indicates this is the highest band, e.g. 20000 and above
            "endpoint": {
                "protectionComputerScore": 99,
                "protectionServerScore": 94,
                "policyThreatProtectionComputerScore": 96,
                "policyThreatProtectionServerScore": 90,
                "exclusionsGlobalScore": 90,
                "exclusionsComputerScore": 97,
                "exclusionsServerScore": 98,
                "tamperProtectionGlobalScore": 91,
                "tamperProtectionComputerScore": 90,
                "tamperProtectionServerScore": 90
            }
        }
    ]
}

You can use this to see how your scores compare with other organisations. For example, if your current score (in endpoint/protection/computer/score in response to calling the GET Account health check API) is 62, and you have 150 devices in your estate, you can compare this with endpoint/protectionComputerScore in the band where lowerBound: 50 and upperBound: 249. In this case, the regional average score is 93, so you can see you are below the average in your data region for this check.

Historical scores

Call this API to get historical scores for your account, to see how your scores have changed over time.

GET /account-health-check/v1/scores/historical

Supported query parameters:

  • startDate: Start date to get scores for. The data points will include scores for a range inclusive of the start date.
  • endDate: End date to get scores for. The data points will include scores for a range inclusive of the end date.

The response includes a list of data points for the date range specified in the request:

  • The data points returned may be sparse - a data point only exists on a single date if a health score changed (in other words, at least one check was re-evaluated because the account configuration changed).
  • The data points returned are sorted by date, with the oldest first.
  • Historical data is available for 30 days. If older data is requested, the oldest data returned will be 30 days old.
  • If the account is new then there will be no historical score data, and so an empty data points array will be returned.

Response: (JavaScript-style comments added for annotation).

{
  "tenant": {
    "id": "498c2279-c361-46e0-9ca9-74ea6c468d46"
  },
  "datapoints": [
    {
      "date": "2024-04-17",
      "computerTotal": 25,
      "serverTotal": 15,
      "endpoint": {
        "protectionComputerScore": 4,
        "protectionServerScore": 26,
        "policyThreatProtectionComputerScore": 96,
        "policyThreatProtectionServerScore": 95,
        "exclusionsGlobalScore": 100,
        "exclusionsComputerScore": 93,
        "exclusionsServerScore": 100,
        "tamperProtectionGlobalScore": 100,
        "tamperProtectionComputerScore": 100,
        "tamperProtectionServerScore": 100
      }
    },
    {
      "date": "2024-04-24",
      "computerTotal": 25,
      "serverTotal": 15,
      "endpoint": {
        "protectionComputerScore": 4,
        "protectionServerScore": 26,
        "policyThreatProtectionComputerScore": 96,
        "policyThreatProtectionServerScore": 96,
        "exclusionsGlobalScore": 100,
        "exclusionsComputerScore": 93,
        "exclusionsServerScore": 100,
        "tamperProtectionGlobalScore": 100,
        "tamperProtectionComputerScore": 100,
        "tamperProtectionServerScore": 100
      }
    }
  ]
}

Fix account health issues

Fix protection

To fix issues reported under endpoint/protection/computer using Sophos Central Admin, see the product documentation.

To fix issues reported under endpoint/protection/server using Sophos Central Admin, see the product documentation.

You can't currently use the Sophos Central APIs to resolve protection issues.

Fix policies

To fix issues reported under endpoint/policy/computer:

To fix issues reported under endpoint/policy/server

Note: If your policy is lockedByManagingAccount you cannot fix the policy - your Sophos Partner or Enterprise Admin manages it.

Fix policy exclusions

To fix issues reported under endpoint/exclusions/policy/computer and endpoint/exclusions/policy/server:

Note: If your policy is lockedByManagingAccount you can't fix the policy. Your Sophos Partner or Enterprise Admin manages this.

Fix global exclusions

To fix issues reported under endpoint/exclusions/global:

Note: If your global exclusions are lockedByManagingAccount then you can't fix them. Your Sophos Partner or Enterprise Admin manages them.

Fix global tamper protection

To fix issues reported under endpoint/tamperProtection/global using Sophos Central Admin, see the product documentation.

You can't currently use the Sophos Central APIs to turn global tamper protection on or off.

Fix endpoint or server tamper protection

Note: You need to turn on global tamper protection (from Global Settings) before you can turn it on for individual computers or servers.

To fix issues reported under endpoint/tamperProtection/computer and endpoint/tamperProtection/server:

Snooze health issues

You can defer dealing with account health issues by invoking the "snooze" API operation. A section of the health report can be snoozed at a time. You can end a snooze manually or let the system expire it automatically after 6 months. You can add or update snooze comments.

NOTE: The rest of this discussion uses JSON path notation when referring to data within a JSON object. For example $.endpoint.protection refers to the "protection" sub-object inside the "endpoint" sub-object at the root of the JSON object.

{
  "endpoint": {      // This is `$.endpoint`
    "protection": {  // This is `$.endpoint.protection`
      "computer": {  // This is `$.endpoint.protection.computer`
        ...
      },
      "server": {    // This is `$.endpoint.protection.server`
        ...
      }
    }
  }
}

Snoozing/unsnoozing an issue

Call this API to snooze health check issues for the tenant:

POST /account-health-check/v1/snooze

The request body has a structure similar to the response returned by GET /health-check.

The example below shows the $.endpoint.protection.computer section being snoozed and the $.endpoint.tamperProtection.computer being unsnoozed.

{
  "endpoint": {
    "protection": {
        "computer": {
          "snoozed": true,          // Required
          "snoozeDetail": {         // Optional
            "comment": "Snoozing computer protection issues"
          }
        }
      }
    },
    "tamperProtection": {
        "computer": {
          "snoozed": false,         // Required
          "snoozeDetail": {         // Optional
            "comment": "Unsnoozing computer tamper-protection issues"
          }
        }
    }
  }
}

Snooze information can appear in all of the following JSON paths:

  • $.endpoint.protection.computer
  • $.endpoint.protection.server
  • $.endpoint.tamperProtection.computer
  • $.endpoint.tamperProtection.server
  • $.endpoint.tamperProtection.global
  • $.endpoint.policy.computer[*]
  • $.endpoint.policy.server[*]
  • $.endpoint.exclusions.policy.computer[*]
  • $.endpoint.exclusions.policy.server[*]
  • $.endpoint.exclusions.global

Some things to keep in mind:

  • If there are no health issues for a section, or the request is the same as the current state, then the snooze request for the section is ignored and the API call succeeds.
  • Snooze information for a section is discarded once all health issues for that section have been fixed. A snooze request for a section is ignored if there are no health issues for that section.
  • Even when a health section is snoozed, up-to-date health issue information continues to be returned by GET /health-check.

You can request snoozing policy exclusions health issues at these JSON paths:

  • $.endpoint.exclusions.policy.computer[*].exclusions[*]
  • $.endpoint.exclusions.policy.server[*].exclusions[*]

Such snooze requests for exclusions look like this:

{
  ...
  "exclusions": [
    {
      "id": "56756263-42ef-4ac6-99a5-5e007084122a",
      "snoozeComment": "A helpful comment"
    }
  ]
  ...
}

See this section for more examples.

The response body is structured similar to the request body. In the example below you can see the snooze details for the $.endpoint.protection.computer and $.endpoint.tamperProtection.computer sections.

{
  "endpoint": {
    "protection": {
      "computer": {
        "snoozed": true,
        "snoozeDetail": {
          "start": "<date-time>",
          "end": "<date-time>",
          "expiry": "<date-time>",
          "expired": false,
          "reason": "Not Specified",
          "comment": "A helpful comment"
        }
      }
    },
    "tamperProtection": {
      "computer": {
        "snoozed": false,
      }
    }
  }
}

The reason property can only be set by from the Sophos Central Admin user interface and will otherwise be 'Not Specified'.

Snooze request and response examples

Example 1: Snooze computer endpoint protection health issues.

Example request body that snoozes computer endpoint protection health issues, or updates the comment if the section is already snoozed:

{
  "endpoint": {
    "protection": {
      "computer": {
        "snoozed": true,
        "snoozeDetail": {
          "comment": "Comment explaining why"
        }
      }
    }
  }
}

Corresponding response body:

{
  "endpoint": {
    "protection": {
      "computer": {
        "snoozed": true,
        "snoozeDetail": {
          "start": "<date-time>",
          "expiry": "<date-time>",
          "expired": false,
          "reason": "Not Specified",
          "comment": "Comment explaining why"
        }
      }
    }
  }
}

Example 2: Adds or updates a server policy exclusions comment

Example request body that adds or updates a comment for a particular policy for server policy exclusions:

{
  "endpoint": {
    "exclusions": {
      "policy": {
        "server": [
          {
            "policyType": "server-threat-protection",
            "snoozed": true,
            // missing snoozeDetail object indicates it is unchanged
            "exclusions": [
              {
                "id": "56756263-42ef-4ac6-99a5-5e007084122a",
                "snoozeComment": "Per-policy comment"
              }
            ]
          }
        ]
      }
    }
  }
}

Note the missing snooze object. If the section has previously been snoozed then the comment will be unchanged. Otherwise, the comment will be empty.

Corresponding response body:

{
  "endpoint": {
    "exclusions": {
      "policy": {
        "server": [
          {
            "policyType": "server-threat-protection",
            "snoozed": true,
            "snoozeDetail": {
              "start": "<date-time>",
              "expiry": "<date-time>",
              "expired": false,
              "reason": "Not Specified",
              "comment": "Work scheduled for Jan 2023"
            },
            "exclusions": [
              {
                "id": "56756263-42ef-4ac6-99a5-5e007084122a",
                "snoozeComment": "Per-policy comment"
              }
            ]
          }
        ]
      }
    }
  }
}

How snooze affects the health check report

Snooze information in the GET /health-check response is the same as information in the snooze response body, and appears in the same place in the corresponding sections.

If a section has never been snoozed, then there will be a snoozed property with value false. If a section has been snoozed, the following information will be included:

{
   ...
    "snoozed": <true|false>,
    "snoozeDetail": { // Optional: if snoozed is false then snoozeDetail will only be present if the section has been snoozed/unsnoozed
        "start": "<date-time>",
        "end": "<date-time or missing if snooze has not been ended by user, or snooze has been ended then started again>",
        "expiry": "<date-time or missing if snooze was ended by user>",
        "expired": <true|false>,
        "reason": "Not Specified",
        "comment": "A helpful comment"
    }
  ...
}

Here is an example of a GET /health-check response with snooze information:

{
  "tenant": {
    "id": "fd16b47f-31b7-4633-95a4-90dff5a35c29"
  },
  "endpoint": {
    // Always present.
    "protection": {
      // Present if 'protection' is specified in 'checks', or if 'checks' is absent or empty
      "computer": {
        "total": 100,
        "notFullyProtected": 12,
        "snoozed": true,
        "snoozeDetail": {
          "start": "<date-time>",
          "expiry": "<date-time>",
          "expired": <true|false>,
          "reason": "Not Specified",
          "comment": "A helpful comment"
        }
      },
      "server": {
        "total": 50,
        "notFullyProtected": 3,
        "snoozed": false
      }
    },
    "policy": {
      // Present if 'policy' is specified in 'checks', or if 'checks' is absent or empty
      "computer": {
        "threat-protection": {   // Policy type
          "total": 2,            // Policies of this type
          "notOnRecommended": 1, // Policies with settings that deviate from recommended
          "snoozed": false,
          "policies": [          // Only policies where settings deviate from recommended
            {
              "id": "56756263-42ef-4ac6-99a5-5e007084122a",
              "name": "My custom TP policy",
              "lockedByManagingAccount": false,
              "notOnRecommended": 1 // Count of settings that deviate from recommended
            }
          ]
        }
      },
      "server": {
        "server-threat-protection": {
          // Same as for computer threat-protection
        }
      }
    },
    "exclusions": {
      // Present if 'exclusions' is specified in 'checks', or if 'checks' is absent or empty
      "policy": {
        "computer": {
          "total": 6,
          "numberOfSecurityRisks": 0,
          "snoozed": false
        },
        "server": {
          "total": 10,
          "numberOfSecurityRisks": 1,
          "snoozed": true,
          "snoozeDetail": {
            "start": "<date-time>",
            "expiry": "<date-time>",
            "expired": <true|false>,
            "reason": "Not Specified",
            "comment": "A helpful comment"
          },
          "exclusions": [  // Only exclusions which pose a security risk
            {
              "policyName": "My policy 1",
              "policyId": "56756263-42ef-4ac6-99a5-5e007084122a",
              "lockedByManagingAccount": false,
              "snoozeComment": "Per-policy comment",
              // Optional field
              "scanningExclusions": [
                {
                  "value": "C:\\",
                  "scanMode": "onDemandAndOnAccess",
                  "type": "pua",
                  "securityReasonCode": "REASON_CODE"
                }
              ]
            }
          ]
        }
      },
      "global": {
        "numberOfSecurityRisks": 1,
        "lockedByManagingAccount": false,
        "snoozed": true,
        "snoozeDetail": {
          "start": "<date-time>",
          "expiry": "<date-time>",
          "expired": <true|false>,
          "reason": "<reason>", // Selected in Sophos Central UI
          "comment": "A helpful comment"
        },
        "scanningExclusions": [
          {
            "value": "C:\\",
            "scanMode": "onDemandAndOnAccess",
            "type": "web",
            "securityReasonCode": "REASON_CODE"
          }
        ]
      }
    },
    "tamperProtection": {
      // Present if 'tamperProtection' is specified in 'checks', or if 'checks' is absent or empty
      "computer": {
        "total": 100,
        "disabled": 12,
        "snoozed": false
      },
      "server": {
        "total": 50,
        "disabled": 3
      },
      "global": false,
      "globalDetail": {
        "enabled": false,
        "snoozed": false,
        "snoozeDetail": {
          "start": "<date-time>",
          "end": "<date-time>", // Presence indicates the snooze was ended by the user
          "expired": false,
          "reason": "Not Specified",
          "comment": "A helpful comment"
        }
      }
    }
  }
}

Conclusion

After reading this guide, you should be able to use the Account Health Check API to check if your account has the best protection. You should also be able to selectively snooze or unsnooze issues in the health check report.