{"id":1269,"date":"2016-01-12T21:57:58","date_gmt":"2016-01-13T05:57:58","guid":{"rendered":"https:\/\/officedevblogs.wpengine.com\/?p=1269"},"modified":"2021-11-15T11:36:51","modified_gmt":"2021-11-15T19:36:51","slug":"onenote-api-throttling-and-how-to-avoid-it","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/onenote-api-throttling-and-how-to-avoid-it\/","title":{"rendered":"OneNote API throttling and how to avoid it"},"content":{"rendered":"<p>Hi there,<\/p>\n<p>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 &#8220;429&#8221; HTTP response code when we detect too many &#8211; this is known as throttling.<\/p>\n<p>Before I start talking about\u00a0recommendations for production apps &#8211;\u00a0<strong><em>if you&#8217;re running into throttling (429&#8217;s) during development<\/em><\/strong>, you can simply change your user or your app (this does require giving permissions again) and keep coding\/testing against the API.<\/p>\n<p>Throttling\u00a0is something you definitely want your app to avoid &#8211; here&#8217;s a couple of best practices to achieve this:<\/p>\n<p><strong>Best practice 1 &#8211; Reduce network roundtrips,<\/strong>\u00a0especially when retrieving metadata:<\/p>\n<p>Suppose you want to retrieve all of the user&#8217;s notebooks, sections, and section groups in a hierarchical view.<\/p>\n<p><strong>Bad practice &#8211;<\/strong>\u00a0It can be tempting to do the following:<\/p>\n<ol>\n<li>Call GET ~\/api\/v1.0\/me\/notes\/notebooks to get the list of notebooks<\/li>\n<li>For every retrieved notebook, call GET ~\/api\/v1.0\/me\/notes\/notebooks\/{notebookId}\/sections to retrieve the list of sections<\/li>\n<li>For every retrieved notebook, call GET ~\/api\/v1.0\/me\/notes\/notebooks\/{notebookId}\/sectionGroups to retrieve the list of section groups<\/li>\n<li>&#8230; optionally recursively iterate through section groups<\/li>\n<\/ol>\n<p>While this will work (with a few extra sequential roundtrips to our service), there is a much better alternative.\u00a0<a title=\"Expand blog post\" href=\"http:\/\/blogs.msdn.com\/b\/onenotedev\/archive\/2014\/06\/12\/create-page-in-specific-location-now-in-beta.aspx\">See our blog post about expand<\/a>\u00a0for a more details.<\/p>\n<p><strong>Best practice &#8211;<\/strong>\u00a0One step!<\/p>\n<ol>\n<li>Call GET ~\/api\/v1.0\/me\/notes\/notebooks?$expand=sections,sectionGroups($expand=sections)<\/li>\n<\/ol>\n<p>This will yield the same results in one network roundtrip with way better performance &#8211; yay!<\/p>\n<p><strong>Best practice 2<\/strong>\u00a0&#8211;\u00a0<strong>Don&#8217;t retry requests to the API\u00a0indefinitely<\/strong>, especially without inspecting the HTTP status code or OneNote API error information<\/p>\n<p>Suppose you are creating some UI that will give you a string which will then be the name for a new notebook. You&#8217;ll use the POST ~\/me\/notes\/notebooks API to create a new notebook with that name.<\/p>\n<p><strong>Bad practice\u00a0&#8211;\u00a0<\/strong>Infinitely retrying without inspecting API errors<strong>\n<\/strong><code class=\"csharp\">\n<\/code><code class=\"csharp\">\/\/ Pseudocode!\nbool apiSucceeded = false;\nwhile(!apiSucceeded){\ntry{\ncreateNotebookApiRequest.Execute();\napiSucceeded = true;\n\/\/\u00a0^_^\n}\ncatch(Exception ex){\n\/\/ The API request failed!\u00a0????\u00a0Retrying.\n}\n}<\/code><\/p>\n<p><strong>Tip\u00a0&#8211;\u00a0<\/strong>If our API responds with an HTTP Status Code 4xx (like 404, 400, 409), there is something wrong with the request and retrying won&#8217;t help!<\/p>\n<p><strong>Best practice &#8211;<\/strong>\u00a0Inspect and handle errors, starting with the HTTP response code (also, we might want to set a limit on\u00a0retry loops\u00a0????\u00a0).\nAn example error in this category could be an invalid notebook name (which will result in an HTTP status code &#8220;400&#8221; and the OneNote API error &#8220;NotebookNameInvalidChar&#8221;. When this happens, you might want to prompt your user for a different name or trim certain characters off the notebook name.<\/p>\n<p>You\u00a0can check out\u00a0<a title=\"Blog post on OneNote API errors\" href=\"http:\/\/blogs.msdn.com\/b\/onenotedev\/archive\/2014\/06\/18\/new-errors-and-warnings.aspx\">Nick&#8217;s blog post on OneNote API errors<\/a>\u00a0to see details about how we return specific errors. Also, the list of OneNote API errors is kept up to date\u00a0<a title=\"OneNote API errors\" href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/office\/dn750990.aspx\">in our docs<\/a>!<\/p>\n<p>As we aim to provide a responsive, stable service for all of our users and developers, we will be enabling\u00a0throttling in our API on\u00a0<strong>01\/29\/2016<\/strong>.\u00a0Here&#8217;s how it will work:<\/p>\n<ul>\n<li>Limits will be based on the number requests classified by\u00a0App and\u00a0User &#8211; 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.<\/li>\n<li>The limits are time based, so simply waiting will eventually reset the limit.<\/li>\n<li>If you follow the best practices above, you are very unlikely to get throttled!<\/li>\n<li>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.<\/li>\n<\/ul>\n<p>Happy coding,\nJorge<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":69223,"featured_media":25159,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[11],"tags":[71],"class_list":["post-1269","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-office-add-ins","tag-onenote"],"acf":[],"blog_post_summary":"<p>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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/1269","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/users\/69223"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/comments?post=1269"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/1269\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media\/25159"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media?parent=1269"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/categories?post=1269"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/tags?post=1269"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}