Smartsheet API Best Practices
Published on 02 October 2015
In the midst designing and building an API integration, it’s easy to become so focused on the details of operations, attributes, and parameters that you fail to consider factors that could significantly impact the performance, stability, and maintainability of your integration. Giving such factors the attention they deserve can mean the difference between an unreliable integration and a rock-solid integration.
This post highlights the following 4 Smartsheet API best practices:
-
Be efficient: Use “bulk”-enabled operations
-
Be practical: Adhere to rate limiting guidelines
-
Be smart: Handle errors appropriately
-
Be diligent: Implement logging
We strongly recommend that you design your integration with these guidelines in mind.
Be efficient: Use “bulk”-enabled operations
For maximum efficiency, we recommend that you use bulk-enabled API operations whenever possible. A bulk-enabled API operation allows you to add, update, or delete multiple items using a single API request. For example, if you need to update 10 rows within a sheet, do so using a single Update Row(s) request, rather than executing 10 separate requests - one for each row.
Bulk-enabled operations improve efficiency by dramatically reducing the number of outbound calls you have to make, reducing your chances of hitting the rate limit (since each bulk operation counts as only one request toward the limit), and lightening the load on our systems, making your requests more likely to complete in a timely manner.
The following API operations currently allow you to do things in bulk:
We’ll be adding more “bulk”-enabled operations in the future, so be on the lookout for those additional opportunities to improve efficiency, and always do things in bulk whenever possible.
Be practical: Adhere to rate limiting guidelines
Handle "Rate Limit Exceeded" error
The Smartsheet API currently imposes a rate limit of 300 requests per minute per Access Token. (We reserve the right to change this limit at any time.) Certain resource-intensive operations, such as attaching a file or getting cell history, count as 10 requests toward the rate limit. If you exceed this rate limit, subsequent API requests (within a one-minute period) will return a 429 HTTP status code, along with the following JSON response body:
{
“errorCode”: 4003,
“message”: “Rate limit exceeded.”
}
Note: API 2.0 returns HTTP status code 429 for this rate limit error. In API 1.1, it was returned as HTTP status code 503.
We recommend that you design your integration to gracefully handle this rate limit error. One way of doing that would be to have your integration sleep for 60 seconds when this error is encountered, and then subsequently retry the request. Alternatively, you might choose to implement exponential backoff (an error handling strategy whereby you periodically retry a failed request with progressively longer wait times between retries, until either the request succeeds or the certain number of retry attempts is reached).
IMPORTANT: Avoid executing "rapid fire" updates
Additionally, we strongly recommend that you avoid executing API requests in rapid-fire succession to update a specific Smartsheet object over and over again within a very short period of time. For example, if the only thing your integration does is execute an Update Row(s) request once every second for the same sheet, that would only amount to a total of 60 requests per minute -- well within rate limiting guidelines. However, updating the same object in such rapid succession could result in save errors that negatively impact both your integration as well as user experience within the Smartsheet app. To avoid this scenario, design your integration such that API requests are never executed with rapid-fire succession against the same Smartsheet object. For maximum efficiency, consider batching up changes and submitting them in a single request using a “bulk”-enabled operation (for example, Update Row(s) or Add Column(s)).
IMPORTANT: Execute requests serially
We also strongly advise against executing multiple API requests in parallel to update a specific Smartsheet object. Doing so will certainly result in reduced performance and will most likely result in errors due to save collisions. To avoid this scenario, design your integration such that API requests to update a specific Smartsheet object are always executed serially (i.e., execute one request at time, not beginning the next request until the previous request has completed).
Be smart: Handle errors appropriately
It’s common knowledge that a successful API request will result in a 200 HTTP status code, along with data in the body of the response according to the operation performed. But what happens if something goes wrong and you get back something other than a 200 response? The ability to handle errors appropriately is a critical component of a quality API integration.
If a Smartsheet API request is not successful, the API returns a 4xx or 5xx HTTP status code, along with a JSON response body that specifies details about the error that occurred. For example, if you execute a GET Sheet request using an invalid (nonexistent) sheet Id, the response will return an HTTP status code of 404 with the following JSON response body:
{
“errorCode”: 1006,
“message”: “Not Found”
}
To Retry or Not to Retry?
A successful error handling strategy requires that your integration recognize the difference between errors that can potentially be resolved by retrying the request and errors that should never be retried automatically.
The HTTP status code that’s returned with a response is your first indication as to the outcome of the request.
HTTP status code | Meaning | To Retry or Not to Retry? |
---|---|---|
2xx | Request was successful. | -- |
4xx | A problem with the request prevented it from executing successfully. Examples: * 400 Bad Request * 401 Not Authorized * 403 Forbidden * 404 Not Found * 405 Method Not Supported * 406 Not Acceptable * 415 Unsupported Media Type * 429 Too Many Requests |
Never automatically retry the request. If the error code indicates a problem that can be fixed, fix the problem and then retry the request. See the API documentation for Error Handling Recommendations by error code. |
5xx | The request was properly formatted, but the operation failed on Smartsheet’s end. Examples: * 500 Internal Server Error * 503 Service Unavailable |
In some scenarios, requests should be automatically retried using exponential backoff. In other cases, requests should not be retried. See the API documentation for Error Handling Recommendations by error code. |
Error Handling Recommendations
In addition to the HTTP status code, you should also evaluate the Smartsheet-specific error code that’s returned in the response body for any unsuccessful request. For example:
{
“errorCode”: 1006,
“message”: “Not Found”
}
The API documentation specifies error handling recommendations for each Smartsheet-specific error code. We recommend that you use that information to implement error handling logic according to the following guidelines:
-
If the error code indicates a permanent error condition, do not retry the request.
-
If the error code indicates a problem that can be fixed, do not retry the request until the problem has been fixed.
-
If the error code indicates a problem that could be overcome by retrying the request after a period of time, retry the request using exponential backoff.
Be diligent: Implement logging
Finally, a few words about logging. In an ideal world, your integration would function seamlessly from day one, and there would never be a need to troubleshoot issues of any kind. Unfortunately, that’s rarely the case. When issues do arise, it’s important that your integration be capable of logging API requests and responses. Having access to the raw requests and responses (including detailed error codes and error messages) when API issues emerge will streamline troubleshooting and accelerate time to resolution.
The following examples show the type of information that your application should log for API requests and responses.
Request: verb, URI, header(s), request body
POST https://api.smartsheet.com/2.0/sheets/4098273196697476/columns
Authorization: Bearer MY_TOKEN
Content-Type: application/json
Request body:
[
{
"title": "FIRST COLUMN \- My New Column",
"index": 0,
"type": "TEXT\_NUMBER"
},
{
"title": "FIRST COLUMN \- My New Column",
"index": 1,
"type": "TEXT\_NUMBER"
}
]
Response: HTTP status code, response body
HTTP status: 400 Bad Request
Response body:
{
"errorCode": 1133,
"message": "Column titles are not unique among input columns.",
"detail": {
"columnTitle": "FIRST COLUMN \- My New Column"
}
}
Often times, having access to this information will enable you to identify and resolve the issue on your own. On occasions where that’s not the case and you reach out to devrel@smartsheet.com for help, you can expect us to ask for the request/response information as described above. So, save yourself some headaches down the road by implementing API request and response logging from day 1.
Final words
Whether you’re currently in the process of designing and building an integration with Smartsheet, or have built an integration previously, there’s no time like the present to incorporate the best practices that we’ve covered in this post:
-
Be efficient: Use “bulk”-enabled operations
-
Be practical: Adhere to rate limiting guidelines
-
Be smart: Handle errors appropriately
-
Be diligent: Implement logging
Capitalize on the opportunity to improve the performance, stability, and maintainability of your integration by giving these factors the attention they deserve.