Hi there,
Sometimes, applications can be written to be too demanding of an API. If one application is using too many resources, it may accidentally cause a denial of service for other applications by making the API slow or unusable. The OneNote API protects itself against accidental denial of service in the form of preventing requests and returning a “429” HTTP response code when we detect too many – this is known as throttling.
Before I start talking about recommendations for production apps – if you’re running into throttling (429’s) during development, you can simply change your user or your app (this does require giving permissions again) and keep coding/testing against the API.
Throttling is something you definitely want your app to avoid – here’s a couple of best practices to achieve this:
Best practice 1 – Reduce network roundtrips, especially when retrieving metadata:
Suppose you want to retrieve all of the user’s notebooks, sections, and section groups in a hierarchical view.
Bad practice –Â It can be tempting to do the following:
- Call GET ~/api/v1.0/me/notes/notebooks to get the list of notebooks
- For every retrieved notebook, call GET ~/api/v1.0/me/notes/notebooks/{notebookId}/sections to retrieve the list of sections
- For every retrieved notebook, call GET ~/api/v1.0/me/notes/notebooks/{notebookId}/sectionGroups to retrieve the list of section groups
- … optionally recursively iterate through section groups
While this will work (with a few extra sequential roundtrips to our service), there is a much better alternative. See our blog post about expand for a more details.
Best practice –Â One step!
- Call GET ~/api/v1.0/me/notes/notebooks?$expand=sections,sectionGroups($expand=sections)
This will yield the same results in one network roundtrip with way better performance – yay!
Best practice 2Â –Â Don’t retry requests to the APIÂ indefinitely, especially without inspecting the HTTP status code or OneNote API error information
Suppose you are creating some UI that will give you a string which will then be the name for a new notebook. You’ll use the POST ~/me/notes/notebooks API to create a new notebook with that name.
Bad practice – Infinitely retrying without inspecting API errors
// Pseudocode!
bool apiSucceeded = false;
while(!apiSucceeded){
try{
createNotebookApiRequest.Execute();
apiSucceeded = true;
//Â ^_^
}
catch(Exception ex){
// The API request failed! ???? Retrying.
}
}
Tip – If our API responds with an HTTP Status Code 4xx (like 404, 400, 409), there is something wrong with the request and retrying won’t help!
Best practice – Inspect and handle errors, starting with the HTTP response code (also, we might want to set a limit on retry loops ???? ). An example error in this category could be an invalid notebook name (which will result in an HTTP status code “400” and the OneNote API error “NotebookNameInvalidChar”. When this happens, you might want to prompt your user for a different name or trim certain characters off the notebook name.
You can check out Nick’s blog post on OneNote API errors to see details about how we return specific errors. Also, the list of OneNote API errors is kept up to date in our docs!
As we aim to provide a responsive, stable service for all of our users and developers, we will be enabling throttling in our API on 01/29/2016. Here’s how it will work:
- Limits will be based on the number requests classified by App and User – This means if your app is not following our best practices and ends up issuing too many requests to the OneNote API in a short period of time, it might be throttled for some time.
- The limits are time based, so simply waiting will eventually reset the limit.
- If you follow the best practices above, you are very unlikely to get throttled!
- Since the limits are scoped per app and user, your app will not get throttled if it gets a lot of users. It will only get throttled if it issues a huge amount of requests in a short period of time for a particular user.
Happy coding, Jorge