Discrepancy between documented rate limit & observed rate limit

I’m trying to make our Discord bot respect the documented rate limit at https://api.inaturalist.org/v1/docs/#terms-of-use but have run up against this discrepancy between the described behaviour and the observed behaviour. It says:

Please note that we throttle API usage to a max of 100 requests per minute, though we ask that you try to keep it to 60 requests per minute or lower, and to keep under 10,000 requests per day. If we notice usage that has serious impact on our performance we may institute blocks without notification.

We have a user list of around 200 users on iNat Discord. For the purpose of having moderators of our Discord server review the membership list and align the membership of the corresponding iNat project rules (iNat Discord 2019 Yearlist and Discord iNat Server) so that they only contain active users, the bot should have the user records for each member. Even if I fill the cache at a rate of 12 API calls per minute of /v1/users/{id}, after the 100th consecutive call, the bot is immediately rate-limited with:

[2019-12-13 06:16:19] [INFO] red.dronefly.inatcog:
  [429 Too Many Requests]>
<CIMultiDictProxy('Server': 'nginx', 'Date': 'Fri, 13 Dec 2019
  10:16:19 GMT', 'Content-Length': '337', 'Connection': 'keep-alive')>

This may be by design, but if it is, it is at the very least a bug in the API documentation, since 12 requests per minute is well below the requested “no more than 60 requests per minute” and the documented “we throttle …” limit of 100 per minute. Please advise as to how I should adjust my code to respect the actual limits if this is not a bug. Please also fix your documentation. Thanks.


This should be fixed now and the throttling rate for that endpoint should be in line with the documented rate. Thanks for bringing this to our attention


Thanks for the prompt attention to the issue.

I have tested the fix & it works. With a 60 request per minute rate limit, I can now succesfully run the command (takes approx 3 minutes to execute!)

I will be refining the caching & rate-limiting layer from here to make the thing actually usable. Apparently I’m up against Discord rate-limiting as well, though that appears to be handled transparently through the calls I’m currently using rather than triggering a hard failure.