Errors
Handling responses¶
Status codes¶
The HTTP standard allows for a lot of different status codes to be returned from API calls. However, our APIs stick to the following subset:
| Code | Usual meaning | What it means for our APIs | Can retry on error? |
|---|---|---|---|
| 200 | OK | The API call was successful. | Not applicable |
| 201 | Created | A new resource was successfully created via POST. | Not applicable |
| 202 | Accepted | An asynchronous PUT or POST call accepted the request but the server has deferred acting on it. | Not applicable |
| 304 | Not Modified | Indicates whether a resource has been modified. This is returned only when If-Modified-Since or If-None-Match headers have been supplied. Note: Our APIs currently don't support such checks. | Not applicable |
| 400 | Bad Request | The API client sent a malformed request. | No - this is a permanent error, and usually indicates a bug in the client code. |
| 401 | Unauthorized | The client needs to authenticate before making the API call. Either your credentials are invalid or blacklisted, or your JWT authorization token has expired. | No |
| 403 | Forbidden | The client has authenticated but doesn't have permission to perform the operation via the API. | No |
| 404 | Not Found | The requested resource wasn't found. The resource ID provided may be invalid, or the resource may have been deleted, or is no longer addressable. | No - this is a semi-permanent error, and usually indicates a bug in the client code. |
| 405 | Method Not Allowed | Returned when a client uses an HTTP method that is valid but not allowed. For example using DELETE on a resource that can't be deleted. | No - this is a permanent error, and usually indicates a bug in the client code. |
| 409 | Conflict | Returned when the API is asked to perform an action that can only be done once. For example, if a service requires user email addresses be unique, attempting to create a user with a given email address, when one already exists, results in a 409. Please check the API documentation or contact Support if this persists. | This is a semi-permanent error; you can retry after resolving the conflict some other way. |
| 413 | Request Entity Too Large | Returned when a request header or the request body exceeds the size limit. This is 30KB for request headers and 10MB for the request body. | No - this is a permanent error; you may need to change your client code. |
| 414 | Request URI Too Long | Returned when a request URI exceeds the 7KB size limit. Use the POST variant of the API, if one is available, or reduce the length of the URI. | No - this is a permanent error; you may need to change your client code. |
| 422 | Unprocessable Content | The operation requested by the client is invalid. For example, a request to create an object exceeds the maximum number of allowed objects. | No |
| 429 | Too Many Requests | The client exceeded the quota for making requests in a given time window. | Yes - see Rate-Limits and Retrying on error. |
| 451 | Unavailable for Legal Reasons | An example of a legal reason we can't serve an API is that the caller is located in a country where United States export control restrictions apply, and we are required by law not to handle such API calls. | No |
| 500 | Internal Server Error | There was an unknown error processing the API call. | Yes - see Retrying on error. |
| 502 | Bad Gateway | The service implementing the API is unavailable. This may be due to maintenance. If the issue persists, please check the status of the service or contact Support. | Yes - see Retrying on error. |
| 503 | Service Unavailable | The service implementing the API is unavailable. It could be a temporary error that resolves itself. See Retrying on error. | Yes - see Retrying on error. |
Error response object¶
Most API calls return a JSON error object to indicate errors, alongside one of the error response status codes above. This error object has the following structure.
| Field | Type | Always present? | Purpose |
|---|---|---|---|
| error | string | Yes | A camelCase identifier for the error condition. |
| message | string | No | An English string explaining the error condition. |
| correlationId | string | No | A unique identifier for debugging this request and other correlated ones across the system. |
| code | string | No | An implementation dependent code that captures the specific error. |
| createdAt | timestamp | No | ISO 8601 (UTC) timestamp for when the error happened. |
| requestId | string | No | A unique ID identifying the specific failed request. |
| docUrl | url | No | A link to the documentation for the error. |
For example: You may see the following object accompanying a 409 (Conflict) status code in response to an attempt to create two users with the same email address:
{
"error": "duplicateUserEmail",
"message": "A user with the given email already exists",
"correlationId": "59763C8E-B687-47D0-8F7B-88113425CE3B",
"code": "USR00004c5",
"createdAt": "2019-08-15T11:25:45.987Z",
"requestId": "6DB1D8AC-1BFA-448B-8439-5486E6D25A74",
"docUrl": "http://docs.sophos.com/central/api-docs/en-us/errors.html#duplicateUserEmail"
}
Note: The error above is an example and the link doesn't work.
Embedded error object¶
The API response may include an embedded error object.
The field is always named errors and its value is an object (not an array). The structure of the errors field is dependent upon an API's implementation and is generally documented in the API specification.
Partial responses¶
Most of our APIs can be configured to return only part of the JSON response. This reduces the amount of data returned. Sometimes, this can improve performance for clients on slow network links.
The syntax for requesting a selective response is simple: pass in a query parameter named fields with a comma-separated list of values that identify the parts of the JSON object to retain the response.
Example¶
The following API call returns a specific alert object by ID:
GET https://api-us01.central.sophos.com/common/v1/alerts/1E623A9B-A54D-432A-A514-02FEDDC080B5
This returns a JSON object that looks like:
{
"id": "1E623A9B-A54D-432A-A514-02FEDDC080B5",
"description": "Controlled application blocked: Quake (Game)",
"type": "Event::Endpoint::Application::Blocked",
"groupKey": "APPLICATION_CONTROL",
"severity": "medium",
"category": "applicationControl",
"product": "endpoint",
"tenant": {
"id": "26AE6B83-088F-4708-8103-BAA4E76B1048"
},
"managedAgent": {
"id": "6B64BFA4-A773-487B-B44F-8D635609A79A",
"type": "computer"
},
"person": {
"id": "4CC323EE-6D93-4CC5-AD3E-7AF5DC3B1AB9"
},
"raisedAt": "2019-05-22T13:49:11.000Z",
"allowedActions": ["acknowledge", "authPua", "contactSupport"]
}
You need the severity and the allowed actions to decide what do to with the alert. In this case, you can modify the call as follows:
GET https://api-us01.central.sophos.com/common/v1/alerts/1E623A9B-A54D-432A-A514-02FEDDC080B5?fields=severity,allowedActions
This returns a JSON object that looks like:
{
"id": "1E623A9B-A54D-432A-A514-02FEDDC080B5",
"severity": "medium",
"allowedActions": ["acknowledge", "authPua", "contactSupport"]
}
Note that the id field is always returned.
For nested objects, use dots to create a reference to an inner field. For instance, to get the type of the alert source ("computer"), you can modify the call to:
GET https://api-us01.central.sophos.com/common/v1/alerts/1E623A9B-A54D-432A-A514-02FEDDC080B5?fields=severity,allowedActions,managedAgent.type
This returns a JSON object that looks like:
{
"id": "1E623A9B-A54D-432A-A514-02FEDDC080B5",
"severity": "medium",
"managedAgent": {
"type": "computer"
},
"allowedActions": ["acknowledge", "authPua", "contactSupport"]
}
You can treat an array of objects in the same way as an object. Invalid field specifications are silently ignored. If fields is omitted or empty, the entire object is returned.