- Drop support for python 3.7
- Add
User.annotated_observations_count
field - Add
root_id
filter totaxon.make_tree()
to explicitly set the root taxon instead of determining it automatically - Fix
taxon.make_tree()
rank filtering to allow skipping any number of rank levels - Fix
taxon.make_tree()
rank filtering to handle all available ranks filtered out - Update
taxon.make_tree()
to return copies of original taxon objects instead of modifying them in-place - Update
Taxon.flatten(hide_root=True)
to only hide the root taxon if it was automatically inserted bymake_tree()
- Add shortcut properties to
Taxon
for ancestors of common ranks:Taxon.kingdom
,phylum
,class_
(note the_
; 'class' is a reserved keyword),order
,family
,genus
- Update
Observation.taxon.ancestors
based on identification data, if available
- Increase default request timeout from 10 to 20 seconds
- Add
validate_token()
function to manually check if an access token is valid - Support rate limits less than one request per second (example:
ClientSession(per_second=0.5)
) - Add error handling for file uploads over 20MB (not accepted by API)
- Allow setting lockfile path used for multiprocess rate limiting (example:
ClientSession(lock_path='/tmp/pyinat.lock')
)
- Fix
KeyError
when usingcreate_observation()
in dry-run mode
- Added new User endpoint:
get_current_user()
- Added new Taxon endpoint:
get_life_list_metadata()
Add support for searching observations by observation fields, using a new observation_fields
param for the following functions:
get_observations()
get_observation_histogram()
get_observation_identifiers()
get_observation_observers()
get_observation_popular_field_values()
get_observation_species_counts()
Observation:
- Add
Observation.ident_taxon_ids
dynamic property to get all identification taxon IDs (with ancestors) - Add
Observation.cumulative_ids
dynamic property to calculate agreements/total community identifications - Add
Application
model forObservation.application
(for v2 API) - Add
Fave
model forObservation.faves
- Add
Flag
model forObservation.flags
- Add
QualityMetric
model forObservation.quality_metrics
- Add
Sound
model forObservation.sounds
- Add
Vote
model forObservation.votes
Project:
- Add
Project.last_post_at
datetime attribute - Add
Project.observation_requirements_updated_at
datetime attribute
Taxon:
- Add
make_tree()
function to build a tree fromTaxon
objects or aLifeList
- Add
pprint_tree()
function to print a taxon tree on the console - Add
Taxon.flatten()
method to return a taxon and its descendants as a flat list - Fix initialization of
ListedTaxon.place
- Added support for python 3.12
get_observation()
is now deprecated, and will be removed in a future release- Please use
get_observations()
orget_observations_by_id()
instead
- Please use
- Remove redundant
Annotation.controlled_attribute_id
andcontrolled_value_id
attributes (These can still be used as init arguments)
- Added new Observation endpoint:
get_observations_by_id()
- Replaces
get_observation
- Accepts multiple IDs
- Uses a different endpoint (
GET /observations/{id}
instead ofGET /observations?id={id}
) - returns full term and value details for annotations
- Replaces
- Add some undocumented request params to
get_taxa_by_id()
:locale
preferred_place_id
all_names
- Add full mapping of conservation status codes for IUCN, NatureServe, Norma Oficial Mexicana, and other generic codes
- Translate
ConservationStatus.status_name
based on status code and authority for more consistent results - Add
ConservationStatus.display_name
property - Add
Observation.default_photo
property - Use taxon icon as placeholder for
Observation.default_photo
if observation has no photos - Update
Annotation
model to include controlled term and value details from updatedGET /observations/{id}
response format - Add
Annotation.term
andvalue
properties and init arguments for simpler initialization from term and value labels
- Add
cache_control
option toClientSession
to disable using Cache-Control headers for cache expiration (enabled by default) - Add
urls_expire_after
option toClientSession
to update default cache expiration URL patterns
- Fix error
413: Payload too large
when usingadd_project_users()
ordelete_project_users()
with a project with a large number of rules - Fix JWT caching
- Fix
ObservationFieldValue
conversions fordate
anddatetime
fields - Fix printing
Annotation
objects withrich
- Fix printing
Observation
tables when taxon is missing
- Added support for python 3.11
- All API functions that accept taxonomic rank parameters (
rank
,lrank
,observation_hrank
,etc.) now accept all rank variations that iNaturalist accepts (var
,spp
sub-species
, etc.) - Optionally use
ultrajson
instead of stdlibjson
, if installed - Add
loop
argument to iNatClient and Paginator classes to allow passing an async event loop to be used for async iteration - Add
Paginator.async_all()
method (async, non-blocking version of.all()
)
- Use a single data directory instead of separate 'cache' and 'user data' dirs
- Platform-dependent; on Linux, for example, this will be
~/.local/share/pyinaturalist
- Platform-dependent; on Linux, for example, this will be
- Add retries for requests that return invalid (truncated) JSON
max_retries
andbackoff_factor
arguments forClientSession
will apply to these retries (in addition to other request errors)
- Handle nested 'photo' dictionaries when loading
Taxon.taxon_photos
- Add model for
ListedTaxon.list
, and handle differences in format between/taxa
and/observations/{id}/taxon_summary
- Minor fixes and improvements for creating and converting
Observation
,Taxon
, and other model objects
- Fix pagination bug causing only the first two pages of results to be returned
- Add Photo.uuid, observation_id, and user_id fields (for compatibility with inaturalist-open-data)
- Handle errors in ObservationField type conversions
- Improve terminal output for nested model objects (like
Observation.taxon
,Taxon.ancestors
, etc.) - If
Taxon.ancestor_ids
is missing, populate from eitherancestry
string orancestor
objects, if possible
- Dropped support for python 3.6
- Added new Observation endpoint:
get_observation_popular_field_values()
- Added new Project endpoint and helper functions:
update_project()
add_project_users()
delete_project_users()
- Updated
get_projects_by_id()
to allow string values (URL slugs) forproject_id
- Updated
get_user_by_id()
to allow string values (usernames) foruser_id
- Added support for setting timeout for individual API requests (with
timeout
parameter) - Added support for setting cache timeout for individual API requests (with
expire_after
parameter) - Added support for bypassing the cache for individual API requests (with
refresh
parameter)
- Added support for JWT authentication, which will now be used by default
- To get an OAuth access token instead of a JWT, call
get_access_token(jwt=False)
- To get an OAuth access token instead of a JWT, call
- Added caching to
get_access_token()
. JWTs will be stored in the API response cache and reused until they expire.
- Remove default values from output when model objects are printed with
rich
- Add
ControlledTermCount
model for use with/observations/popular_field_values
Photo
: Addext
andmimetype
propertiesTaxon
: Use icon in place ofdefault_photo
if missing
- Add an optional, abbreviated namespace
pyinat
as an alias forpyinaturalist
- Updated rate limiting with a SQLite-based backend. This adds persistence for rate limit tracking across multiple threads, processes, and/or application restarts. See pyrate-limiter docs for more details.
- Add a
clear_cache()
function for clearing cached API responses - Misc improvements for response pretty-printing
- Removed
pyinaturalist.user_agent
global variable and API function keyword args, and recommend setting on session object instead - Removed
pyinaturalist.DRY_RUN*
global variables, and recommend setting in environment variables instead
- Added new Taxon endpoint:
get_taxa_map_layers()
- Added new Message endpoints:
get_messages()
get_message_by_id()
get_unread_message_count()
The following changes apply to upload()
, create_observation()
, and update_observation()
:
- Added support for uploading observation photo & sound files from URLs
- Added support for attaching previously uploaded photos to an observation by photo ID
- Added support for python 3.10
- Fixed
count_only=True
/per_page=0
to not run full query - Do not error on unrecognized
**kwargs
, for cases where the API may accept some additional undocumented parameters - Allow overriding default location for API request cache
- Added new functions for v1 Observation endpoints:
create_observation()
update_observation()
delete_observation()
upload()
(uploads both photos and sounds)- These are now preferred over the older v0 endpoints
- Added new functions for v1 Observation field value endpoints:
set_observation_field()
(creates and updates observation field values)delete_observation_field()
- Added new function for Observation taxon summary:
get_observation_taxon_summary()
- Added new functions for Project observation endpoints:
add_project_observation()
delete_project_observation()
- Added a
dry_run
argument to all API request functions to dry-run an individual request - Added a
reverse
argument to all paginated API request functions to reverse the sort order
- Added new data models:
- ListedTaxon
- TaxonSummary
- UserCounts
- Added a preview version of
iNatClient
, a higher-level interface for API requests, which returns model objects instead of JSON. See issues #163 and #217 for details.
- Added API request caching with requests-cache
- Updated rate-limiting not apply to cached requests
- Added custom
ClientSession
class to configure caching, rate-limiting, retries, and timeouts
- Improved logging output for dry-run mode: now shows formatted
PreparedRequest
details instead ofrequest()
keyword args - Added an
enable_logging()
function to optionally show prettier logs withrich
- Updated logging to redact all credentials from logged API requests
- Increased default timeout to 10 seconds to accommodate some longer-running queries
- Added
get_interval_ranges()
function to help with queries over a series of date/time intervals - Fixed bug with
rule_details
param forget_projects_by_id()
- Added more tutorial/example notebooks
- Added new function for Posts endpoint:
get_posts()
- Fixed broken
response_format
parameter inv0.get_observations()
- Deprecated
pyinaturalist.rest_api
module (moved topyinaturalist.v0
subpackage) - Deprecated
pyinaturalist.node_api
module (moved topyinaturalist.v1
subpackage) - Deprecated
get_geojson_observations()
(moved to join other observation conversion tools inpyinaturalist-convert
)
- Added new function for Observation sounds endpoint:
upload_sounds()
- Added new function for Life list endpoint:
get_observation_taxonomy()
- Added support for passing a
requests.Session
object to all API request functions - Added a
photos
parametercreate_observation()
andupdate_observation()
to upload photos - Added a
sounds
parametercreate_observation()
andupdate_observation()
to upload sounds - Renamed
add_photo_to_observation()
toupload_photos()
- The alias
rest_api.add_photo_to_observation()
is still available for backwards-compatibility
- The alias
- Updated
upload_photos()
to take accept either a single photo or a list of photos, and return a list of responses - Updated
upload_sounds()
to take accept either a single sound or a list of sounds, and return a list of responses - Added alias
observed_on
forobserved_on_string
increate_observation()
- Fixed conversion for datetime parameters in
create_observation()
andupdate_observation()
- Updated all requests to correctly convert
datetime
objects to strings - Moved API functions into separate modules by API version and resource type.
- All can still be imported via
from pyinaturalist import *
- Added aliases for backwards-compatibility, so imports from
pyinaturalist.rest_api
andpyinaturalist.node_api
will still work
- All can still be imported via
Added data models for all API response types, to support working with typed python objects instead of JSON.
Models:
- Comment
- ControlledTerm
- ControlledTermValue
- Annotation
- Identification
- LifeList
- LifeListTaxon
- Observation
- ObservationField
- ObservationFieldValue
- Photo
- Place
- Project
- ProjectObservation
- ProjectObservationField
- ProjectUser
- SearchResult
- Taxon
- ConservationStatus
- EstablishmentMeans
- TaxonCount
- TaxonCounts
- User
Model features:
- Type conversions
- Lazy initialization
- Basic formatters
- Table formatters
- Consolidated response formatting into a single
pprint()
function (instead of one per resource type) - Refactored and reorganized the following internal utility modules (see API docs for details):
converters
docs
formatters
request_params
- Added a default response timeout of 5 seconds
- Added an example (
examples/sample_responses.py
) containing response JSON, model objects, and tables of every type to experiment with - Added a tutorial notebook (
examples/Tutorial.ipynb
) - Set up pyinaturalist-notebook to be runnable with Binder
- The following methods are now deprecated. They are still functional, but will raise a
DeprecationWarning
, and will be removed in a future release:node_api.get_all_observations()
node_api.get_all_observation_species_counts()
rest_api.get_all_observation_fields()
- Removed
minify
option fromget_taxa_autocomplete
- Added new function for Search endpoint:
search()
(combined search for places, projects, taxa, and users) - Added new functions for Identifications endpoints:
get_identifications()
andget_identifications_by_id()
- Added new functions for Users endpoints:
get_user_by_id()
andget_users_autocomplete()
- Added undocumented
ident_user_id
parameter toget_observations()
- Added
count_only=True
as an alias forper_page=0
(to get only result counts). - Added generic auto-pagination that can apply to any endpoint that supports pagination.
- Added
page='all'
as a shortcut for auto-pagination - The above changes apply to all functions that support pagination:
node_api.get_identifications()
node_api.get_observations()
node_api.get_observation_species_counts()
node_api.get_observation_observers()
node_api.get_observation_identifiers()
node_api.get_places_autocomplete()
node_api.get_projects()
node_api.get_taxa()
rest_api.get_observations()
rest_api.get_observation_fields()
- Updated
rest_api.get_observation_fields()
to return a dict with'results'
for consistency with other endpoints
- Added response formatting functions to
pyinaturalist.formatters
- All API functions and formatters can now be imported from the top-level package, e.g.
from pyinaturalist import *
- Published pyinaturalist on conda-forge
- Added global rate-limiting to stay within the rates suggested in API Recommended Practices (per second, minute, and day)
- Moved
Dockerfile
anddocker-compose.yml
to a separate repo (pyinaturalist-notebook) and published on Docker Hub - Packaging is now handled with Poetry. For users, installation still works the same. For developers, see Contributing Guide for details.
- Add undocumented
ident_user_id
parameter toget_observations()
- Dropped support for python 3.5
- Removed request parameters that were deprecated in 0.11
- Added new function for Observation Histogram endpoint:
get_observation_histogram()
- Added new function for Observers endpoint:
get_observation_observers()
- Added new function for Identifiers endpoint:
get_observation_identifiers()
- Added new function for Controlled Terms endpoints:
get_controlled_terms()
- Wraps both
GET /controlled_terms
and/controlled_terms/for_taxon
endpoints
- Wraps both
- Added conversion from date/time strings to timezone-aware python
datetime
objects. This applies to the following functions:node_api.get_observation()
node_api.get_observations()
node_api.get_all_observation()
node_api.get_projects()
node_api.get_projects_by_id()
node_api.get_taxa()
node_api.get_taxa_by_id()
rest_api.get_observation()
rest_api.get_observation_fields()
rest_api.get_all_observation_fields()
- Added conversion for an additional
location
field in observation responses
- Added support for providing credentials via environment variables
- Added integration with system keyring for credentials storage
- Added documentation & examples for authentication options
- Added a
Dockerfile
anddocker-compose.yml
for a Jupyter notebook containing pyinaturalist + other relevant packages - Added some more detailed usage examples under
examples/
- Improved performance for large paginated queries
- Fixed bug that dropped request parameter values of
0
as if they wereNone
- Dropped support for python 3.4
- Using the
params
positional argument for the handful of functions that used it will raise aDeprecationWarning
, but will otherwise still be functional until0.12
- Using the
search_query
argument forrest_api.get_observation_fields()
andrest_api.get_all_observation_fields()
will raise aDeprecationWarning
, but will otherwise still be functional until0.12
- Added new functions for Node API Places endpoints:
get_places_by_id()
get_places_nearby()
get_places_autocomplete()
- Added new functions for Node API Projects endpoints:
get_projects()
get_projects_by_id()
- Added new function for an additional Node API Observation endpoint:
get_observation_species_counts()
get_all_observation_species_counts()
- Added support for simplified observation field syntax (
observation_fields={id: value}
) forcreate_observations()
andupdate_observation()
- Updated
node_api.get_taxa_by_id()
to accept multiple IDs - Updated
rest_api.get_observations()
with type conversion from strings to floats for response lat/long coordinates. Only applies to JSON response format. - Updated
node_api.get_taxa_autocomplete()
with optionalmin_rank
andmax_rank
parameters, for consistency withget_taxa()
- Renamed
search_query
argument toq
to be consistent with API request parameters - Renamed
create_observations()
tocreate_observation()
, as this only supports creating a single observation per call. This is aliased tocreate_observations()
for backwards-compatibility, but will raise aDeprecationWarning
.
- Added example response data to docs all endpoints
- Added links to official API reference to docs for all endpoints
- Added full API request parameters to all API functions, in the form of keyword arguments with type annotations and docstrings
- Added complete table of iNaturalist API endpoints and endpoints implemented by pyinaturalist
- Added and improved usage examples
- Numerous other documentation improvements
- Made all API function signatures consistent by taking request params as keyword arguments
- Added support for python 3.9
- Added parameter validation for multiple-choice request parameters
- Added new Observation endpoint:
rest_api.get_observations()
, with 6 additional observation response formats, including GeoJSON, Darwin Core, and others
- Added
minify
option tonode_api.get_taxa_autocomplete()
- Added more info & examples to README for taxa endpoints, and other documentation improvements
- Added conversion for all date and datetime parameters to timezone-aware ISO 8601 timestamps
- Added a dry-run mode to mock out API requests for testing
- Set up pre-release builds for latest development version
- Bugfix: proper support for boolean and integer list parameters (Issue #17)
-
Added new functions for Node API Taxa endpoints:
node_api.get_taxa()
node_api.get_taxa_autocomplete()
node_api.get_taxa_by_id()
- All functions now take an optional
user-agent <https://en.wikipedia.org/wiki/User_agent>
_ parameter in order to identify yourself to iNaturalist. If not set,Pyinaturalist/<VERSION>
will be used.
rest_api.delete_observation()
now raisesObservationNotFound
if the observation doesn't exist- minor dependencies update for security reasons
- New function:
rest_api.delete_observation()
- New function:
node_api.get_observation()
create_observation()
now raises exceptions in case of errors.
update_observation()
now raises exceptions in case of errors.
- Better infrastructure (type annotations, documentation, ...)
- Dropped support for Python 2.
- New function:
update_observation()
rest_api.AuthenticationError
is nowexceptions.AuthenticationError
- First release on PyPI.