Repository: niconoe/pyinaturalist
Pull request #15 (2020-04-22 19:58:03)

Add taxa endpoints
### New endpoints
This PR adds the [`/taxa` endpoints](https://api.inaturalist.org/v1/docs/#!/Taxa/) from the iNaturalist Node API:
* `/taxa`
* `/taxa/{id}`
* `/taxa/autocomplete`

### Rank ranges
In addition to the parameters exposed by  `/taxa`, this also adds support for searching taxa by a range of ranks, via `min_rank` and/or `max_rank`. This is intended to match the search features in the web UI:
![Annotation 2020-04-23 131251](https://user-images.githubusercontent.com/419936/80134457-653de380-8564-11ea-9b8d-69e2cf8563d9.png)

### Minor documentation, dependency, and config updates
* Add development packages to `[dev]` setuptools extra
   (e.g., for local testing, generating docs, etc. outside of tox environments)
* Add a couple more example commands to docs
* Bump pinned version of `requests-mock` to 1.7.0 for recent feature additions
* Bump pinned version of `pytest` to 4.6.9
  (the last release that still works under python3.4)
* Add `Sphinx` and `sphinx-autodoc-typehints` to `requirements.txt`

### Note on unit tests
`requests_mock` now provides a pytest fixture, which plays more nicely with pytest than the decorator. See:
* https://github.com/pytest-dev/pytest/issues/2749
* https://bugs.launchpad.net/requests-mock/+bug/1714756
* https://github.com/jamielennox/requests-mock/pull/51

### Checklist
- [x] Issue: #12
- [x] Docstrings (that render correctly in Sphinx)
- [x] Unit tests
- [x] Sample data
- [x] Type annotations
- [x] Black formatting

Please let me know if there is anything you'd like me to change in this PR, or if you have additional contribution guidelines to follow that I missed.

niconoe: Wow, thanks a lot for the contribution @JWCook! 

Sorry for my lack of responsiveness, I've been quite busy recently but I'll have a lok very soon and will let you know!
JWCook: @niconoe No worries, take your time!

It looks like I have a couple compatibility issues to fix for the older interpreters. I'll get those sorted out, but would you consider dropping support for Python <= 3.5 at some point in the future? [Python 3.4 reached EOL in March 2019](https://devguide.python.org/devcycle/#end-of-life-branches), and [3.5 will reach EOL this September](https://devguide.python.org/#status-of-python-branches).

Patch:
diff --git a/AUTHORS.rst b/AUTHORS.rst
index 85434d2..aa317d4 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -10,6 +10,7 @@ Development Lead
 Contributors
 ------------
 
+* Jordan Cook
 * Peter Desmet
 * Stijn Van Hoey
 
diff --git a/docs/infrastructure.rst b/docs/infrastructure.rst
index 5a01eb1..80c5714 100644
--- a/docs/infrastructure.rst
+++ b/docs/infrastructure.rst
@@ -12,6 +12,13 @@ To build the doc locally::
 
     $ tox -e docs
 
+To preview::
+
+    # MacOS:
+    $ open docs/_build/index.html
+    # Linux:
+    $ xdg-open docs/_build/index.html
+
 Hosted documentation (https://pyinaturalist.readthedocs.io/) is automatically updated when code gets pushed to GitHub.
 
 Testing
diff --git a/docs/installation.rst b/docs/installation.rst
index 4d40318..47da1ef 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -8,4 +8,10 @@ Simply use pip::
 
 Or if you prefer using the development version::
 
-    $ pip install git+https://github.com/niconoe/pyinaturalist.git
\ No newline at end of file
+    $ pip install git+https://github.com/niconoe/pyinaturalist.git
+
+Or, to set up for local development (preferably in a new virtualenv)::
+
+    $ git clone https://github.com/niconoe/pyinaturalist.git
+    $ cd pyinaturalist
+    $ pip install -Ue ".[dev]"
diff --git a/pyinaturalist/__init__.py b/pyinaturalist/__init__.py
index 2d47aa3..6d571c5 100644
--- a/pyinaturalist/__init__.py
+++ b/pyinaturalist/__init__.py
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+import logging
 
 __author__ = "Nicolas Noé"
 __email__ = "nicolas@niconoe.eu"
@@ -7,3 +7,6 @@ __version__ = "0.8.0"
 DEFAULT_USER_AGENT = "Pyinaturalist/{version}".format(version=__version__)
 
 user_agent = DEFAULT_USER_AGENT
+
+# Enable logging for urllib and other external loggers
+logging.basicConfig(level="DEBUG")
diff --git a/pyinaturalist/constants.py b/pyinaturalist/constants.py
index 89d76f4..971b3fb 100644
--- a/pyinaturalist/constants.py
+++ b/pyinaturalist/constants.py
@@ -2,3 +2,31 @@ INAT_NODE_API_BASE_URL = "https://api.inaturalist.org/v1/"
 INAT_BASE_URL = "https://www.inaturalist.org"
 
 THROTTLING_DELAY = 1  # In seconds, support <0 floats such as 0.1
+
+# Taxonomic ranks from Node API Swagger spec
+RANKS = [
+    "form",
+    "variety",
+    "subspecies",
+    "hybrid",
+    "species",
+    "genushybrid",
+    "genus",
+    "subtribe",
+    "tribe",
+    "supertribe",
+    "subfamily",
+    "family",
+    "epifamily",
+    "superfamily",
+    "infraorder",
+    "suborder",
+    "order",
+    "superorder",
+    "subclass",
+    "class",
+    "superclass",
+    "subphylum",
+    "phylum",
+    "kingdom",
+]
diff --git a/pyinaturalist/helpers.py b/pyinaturalist/helpers.py
index e758abb..85c41be 100644
--- a/pyinaturalist/helpers.py
+++ b/pyinaturalist/helpers.py
@@ -1,4 +1,5 @@
 import pyinaturalist
+from typing import Dict, Any
 
 
 # For Python < 3.5 compatibility
@@ -14,3 +15,18 @@ def get_user_agent(user_agent: str = None) -> str:
         return user_agent
     else:  # Otherwise we have a global one in __init__.py (configurable, with sensible defaults)
         return pyinaturalist.user_agent
+
+
+def concat_list_params(params) -> Dict[str, Any]:
+    """Convert any list parameters into an API-compatible (comma-delimited) string.
+    Will be url-encoded by requests. For example: `['k1', 'k2', 'k3'] -> k1%2Ck2%2Ck3`
+    """
+    for k, v in params.items():
+        if isinstance(v, list):
+            params[k] = ",".join(v)
+    return params
+
+
+def strip_empty_params(params) -> Dict[str, Any]:
+    """Remove any request parameters with empty or ``None`` values."""
+    return {k: v for k, v in params.items() if v}
diff --git a/pyinaturalist/node_api.py b/pyinaturalist/node_api.py
index e4ab8fd..72ab691 100644
--- a/pyinaturalist/node_api.py
+++ b/pyinaturalist/node_api.py
@@ -1,28 +1,38 @@
 # Code to access the (read-only, but fast) Node based public iNaturalist API
 # See: http://api.inaturalist.org/v1/docs/
+from logging import getLogger
 from time import sleep
 from typing import Dict, Any, List
 
 import requests
 from urllib.parse import urljoin
 
-from pyinaturalist.constants import THROTTLING_DELAY, INAT_NODE_API_BASE_URL
+from pyinaturalist.constants import THROTTLING_DELAY, INAT_NODE_API_BASE_URL, RANKS
 from pyinaturalist.exceptions import ObservationNotFound
-from pyinaturalist.helpers import merge_two_dicts, get_user_agent
+from pyinaturalist.helpers import (
+    merge_two_dicts,
+    get_user_agent,
+    concat_list_params,
+    strip_empty_params,
+)
 
 PER_PAGE_RESULTS = 30  # Paginated queries: how many records do we ask per page?
 
+logger = getLogger(__name__)
+
 
 def make_inaturalist_api_get_call(
     endpoint: str, params: Dict, user_agent: str = None, **kwargs
 ) -> requests.Response:
     """Make an API call to iNaturalist.
 
-    endpoint is a string such as 'observations' !! do not put / in front
+    endpoint is a string such as 'observations'
     method: 'GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'
     kwargs are passed to requests.request
     Returns a requests.Response object
     """
+    params = strip_empty_params(params)
+    params = concat_list_params(params)
     headers = {"Accept": "application/json", "User-Agent": get_user_agent(user_agent)}
 
     response = requests.get(
@@ -94,3 +104,89 @@ def get_all_observations(params: Dict, user_agent: str = None) -> List[Dict[str,
 
         sleep(THROTTLING_DELAY)
         id_above = results[-1]["id"]
+
+
+def get_taxa_by_id(taxon_id, user_agent: str = None) -> Dict[str, Any]:
+    """
+    Get one or more taxa by ID.
+    See: https://api.inaturalist.org/v1/docs/#!/Taxa/get_taxa_id
+
+    :param: taxon_id: Get taxa with this ID. Multiple values are allowed.
+
+    :returns: A list of dicts containing taxa results
+    """
+    r = make_inaturalist_api_get_call(
+        "taxa/{}".format(taxon_id), {}, user_agent=user_agent
+    )
+    r.raise_for_status()
+    return r.json()
+
+
+def get_taxa(
+    user_agent: str = None, min_rank: str = None, max_rank: str = None, **params
+) -> Dict[str, Any]:
+    """Given zero to many of following parameters, returns taxa matching the search criteria.
+    See https://api.inaturalist.org/v1/docs/#!/Taxa/get_taxa
+
+    :param q: Name must begin with this value
+    :param is_active: Taxon is active
+    :param taxon_id: Only show taxa with this ID, or its descendants
+    :param parent_id: Taxon's parent must have this ID
+    :param rank: Taxon must have this exact rank
+    :param min_rank: Taxon must have this rank or higher; overrides ``rank``
+    :param max_rank: Taxon must have this rank or lower; overrides ``rank``
+    :param rank_level: Taxon must have this rank level. Some example values are 70 (kingdom),
+        60 (phylum), 50 (class), 40 (order), 30 (family), 20 (genus), 10 (species), 5 (subspecies)
+    :param id_above: Must have an ID above this value
+    :param id_below: Must have an ID below this value
+    :param per_page: Number of results to return in a page. The maximum value is generally 200
+        unless otherwise noted
+    :param locale: Locale preference for taxon common names
+    :param preferred_place_id: Place preference for regional taxon common names
+    :param only_id: Return only the record IDs
+    :param all_names: Include all taxon names in the response
+
+    :returns: A list of dicts containing taxa results
+    """
+    if min_rank or max_rank:
+        params["rank"] = get_rank_range(min_rank, max_rank)
+    r = make_inaturalist_api_get_call("taxa", params, user_agent=user_agent)
+    r.raise_for_status()
+    return r.json()
+
+
+def get_taxa_autocomplete(user_agent: str = None, **params) -> Dict[str, Any]:
+    """Given a query string, returns taxa with names starting with the search term
+    See: https://api.inaturalist.org/v1/docs/#!/Taxa/get_taxa_autocomplete
+
+    :param q: Name must begin with this value
+    :param is_active: Taxon is active
+    :param taxon_id: Only show taxa with this ID, or its descendants
+    :param rank: Taxon must have this rank
+    :param rank_level: Taxon must have this rank level. Some example values are 70 (kingdom),
+        60 (phylum), 50 (class), 40 (order), 30 (family), 20 (genus), 10 (species), 5 (subspecies)
+    :param per_page: Number of results to return in a page. The maximum value is generally 200 unless otherwise noted
+    :param locale: Locale preference for taxon common names
+    :param preferred_place_id: Place preference for regional taxon common names
+    :param all_names: Include all taxon names in the response
+
+    :returns: A list of dicts containing taxa results
+    """
+    r = make_inaturalist_api_get_call(
+        "taxa/autocomplete", params, user_agent=user_agent
+    )
+    r.raise_for_status()
+    return r.json()
+
+
+def get_rank_range(min_rank: str = None, max_rank: str = None) -> List[str]:
+    """ Translate min and/or max rank into a list of ranks """
+    min_rank_index = _get_rank_index(min_rank) if min_rank else 0
+    max_rank_index = _get_rank_index(max_rank) + 1 if max_rank else len(RANKS)
+    return RANKS[min_rank_index:max_rank_index]
+
+
+def _get_rank_index(rank: str) -> int:
+    if rank not in RANKS:
+        raise ValueError("Invalid rank")
+    return RANKS.index(rank)
diff --git a/requirements.txt b/requirements.txt
index 5c2ec87..e10dd17 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -27,11 +27,14 @@ pyparsing==2.2.2
 pytz==2018.5
 readme-renderer==22.0
 requests==2.20.0
-requests-mock==1.5.2
+requests-mock==1.7.0
 requests-toolbelt==0.8.0
 six==1.11.0
 snowballstemmer==1.2.1
+sphinx==2.4.3
+sphinx-rtd-theme==0.4.3
 sphinx-autodoc-typehints==1.10.3
+sphinx-rtd-theme==0.4.3
 sphinxcontrib-websupport==1.1.0
 toml==0.10.0
 tox==3.5.2
diff --git a/setup.py b/setup.py
index 4a07aa8..6a985a1 100644
--- a/setup.py
+++ b/setup.py
@@ -25,10 +25,23 @@ setup(
     author="Nicolas Noé",
     author_email="nicolas@niconoe.eu",
     url="https://github.com/niconoe/pyinaturalist",
-    packages=["pyinaturalist",],
+    packages=["pyinaturalist"],
     package_dir={"pyinaturalist": "pyinaturalist"},
     include_package_data=True,
     install_requires=["requests>=2.21.0", "typing>=3.7.4"],
+    extras_require={
+        "dev": [
+            "black",
+            "flake8",
+            "mypy",
+            "pytest",
+            "requests-mock>=1.7",
+            "Sphinx",
+            "sphinx-autodoc-typehints",
+            "sphinx-rtd-theme",
+            "tox",
+        ]
+    },
     license="MIT",
     zip_safe=False,
     keywords="pyinaturalist",
diff --git a/tox.ini b/tox.ini
index 66a6694..8a4e14a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,8 +5,8 @@ envlist = py33, py34, py35, py36, py37, py38, style, docs, mypy
 setenv =
     PYTHONPATH = {toxinidir}:{toxinidir}/pyinaturalist
 deps =
-    pytest==3.10.1
-    requests-mock==1.5.2
+    pytest==4.6.9
+    requests-mock==1.7.0
 commands =
     py.test --basetemp={envtmpdir}
 
@@ -16,13 +16,11 @@ deps =
     flake8
 commands =
     python setup.py flake8
-    
+
 [testenv:docs]
 changedir=docs/
 deps =
     -r{toxinidir}/requirements.txt
-    sphinx
-    sphinx_rtd_theme
 whitelist_externals = make
 commands =
     make clean


Test patch:
diff --git a/test/sample_data/get_taxa.json b/test/sample_data/get_taxa.json
new file mode 100644
index 0000000..9369402
--- /dev/null
+++ b/test/sample_data/get_taxa.json
@@ -0,0 +1,1413 @@
+{
+  "total_results": 35,
+  "page": 1,
+  "per_page": 30,
+  "results": [
+    {
+      "observations_count": 336,
+      "taxon_schemes_count": 2,
+      "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Nicrophorus_vespilloides",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 53850,
+      "name": "Nicrophorus vespilloides",
+      "rank": "species",
+      "extinct": false,
+      "id": 70118,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751",
+        "attribution": "(c) salvatore_infanti, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/38359335/medium.jpg?1557348751",
+        "id": 38359335,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 2048,
+          "height": 1365
+        },
+        "url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47208,
+        71130,
+        372870,
+        48311,
+        53849,
+        204079,
+        53850,
+        70118
+      ],
+      "matched_term": "Nicrophorus vespilloides",
+      "iconic_taxon_name": "Insecta",
+      "preferred_common_name": "Lesser Vespillo Burying Beetle"
+    },
+    {
+      "observations_count": 187,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Nicrophorus_vespillo",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 53850,
+      "name": "Nicrophorus vespillo",
+      "rank": "species",
+      "extinct": false,
+      "id": 131878,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/24573164/square.jpg?1536478624",
+        "attribution": "(c) Robin Bad, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/24573164/medium.jpg?1536478624",
+        "id": 24573164,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 2048,
+          "height": 1365
+        },
+        "url": "https://static.inaturalist.org/photos/24573164/square.jpg?1536478624"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47208,
+        71130,
+        372870,
+        48311,
+        53849,
+        204079,
+        53850,
+        131878
+      ],
+      "matched_term": "Nicrophorus vespillo",
+      "iconic_taxon_name": "Insecta",
+      "preferred_common_name": "Vespillo Burying Beetle"
+    },
+    {
+      "observations_count": 55,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47822/48091/372853/414448/49995/326181/488425/520026/124163",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Temnostoma_vespiforme",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 124163,
+      "name": "Temnostoma vespiforme",
+      "rank": "species",
+      "extinct": false,
+      "id": 124162,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/5925301/square.jpg?1545677110",
+        "attribution": "(c) Ouwesok, alguns direitos reservados (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/5925301/medium.jpg?1545677110",
+        "id": 5925301,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 1200,
+          "height": 1200
+        },
+        "url": "https://static.inaturalist.org/photos/5925301/square.jpg?1545677110"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47822,
+        48091,
+        372853,
+        414448,
+        49995,
+        326181,
+        488425,
+        520026,
+        124163,
+        124162
+      ],
+      "matched_term": "Temnostoma vespiforme",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 39,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47157/122746/51573/456401/366342/51684",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Synanthedon_vespiformis",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 51684,
+      "name": "Synanthedon vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 362871,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/1014675/square.jpg?1545557196",
+        "attribution": "(c) Tony Morris, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/1014675/medium.jpg?1545557196",
+        "id": 1014675,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 551,
+          "height": 473
+        },
+        "url": "https://static.inaturalist.org/photos/1014675/square.jpg?1545557196"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47157,
+        122746,
+        51573,
+        456401,
+        366342,
+        51684,
+        362871
+      ],
+      "matched_term": "S\u00e9sie vespiforme",
+      "iconic_taxon_name": "Insecta",
+      "preferred_common_name": "Yellow-legged Clearwing"
+    },
+    {
+      "observations_count": 29,
+      "taxon_schemes_count": 2,
+      "ancestry": "48460/1/47120/372739/47158/184884/83201/372872/245155/252574",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Franklinothrips_vespiformis",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 252574,
+      "name": "Franklinothrips vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 270746,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/5079943/square.jpg?1475364205",
+        "attribution": "Sem direitos reservados",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/5079943/medium.jpg?1475364205",
+        "id": 5079943,
+        "license_code": "cc0",
+        "original_dimensions": {
+          "width": 819,
+          "height": 797
+        },
+        "url": "https://static.inaturalist.org/photos/5079943/square.jpg?1475364205"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        83201,
+        372872,
+        245155,
+        252574,
+        270746
+      ],
+      "matched_term": "Franklinothrips vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 12,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/48740/52747/119344",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 1,
+        "resolved": 2
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 119344,
+      "name": "Vespidae st1",
+      "rank": "species",
+      "extinct": false,
+      "id": 495392,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/5563170/square.jpg?1479599057",
+        "attribution": "(c) Stephen Thorpe, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/5563170/medium.jpg?1479599057",
+        "id": 5563170,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 781,
+          "height": 925
+        },
+        "url": "https://static.inaturalist.org/photos/5563170/square.jpg?1479599057"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        48740,
+        52747,
+        119344,
+        495392
+      ],
+      "matched_term": "Vespidae st1",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 11,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47822/48091/372853/414448/49995/326181/520014/125658",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Ceriana_vespiformis",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 125658,
+      "name": "Ceriana vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 466251,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/3035009/square.jpg?1545634240",
+        "attribution": "(c) gailhampshire, some rights reserved (CC BY)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/3035009/medium.jpg?1545634240",
+        "id": 3035009,
+        "license_code": "cc-by",
+        "original_dimensions": {
+          "width": 832,
+          "height": 704
+        },
+        "url": "https://static.inaturalist.org/photos/3035009/square.jpg?1545634240"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47822,
+        48091,
+        372853,
+        414448,
+        49995,
+        326181,
+        520014,
+        125658,
+        466251
+      ],
+      "matched_term": "Ceriana vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 7,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/47222/51955/210928/210927/507574/53067",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 53067,
+      "name": "Bembix vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 882585,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/33808490/square.jpeg?1554036738",
+        "attribution": "(c) birdnerd1, all rights reserved",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/33808490/medium.jpeg?1554036738",
+        "id": 33808490,
+        "license_code": null,
+        "original_dimensions": {
+          "width": 795,
+          "height": 1200
+        },
+        "url": "https://static.inaturalist.org/photos/33808490/square.jpeg?1554036738"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        47222,
+        51955,
+        210928,
+        210927,
+        507574,
+        53067,
+        882585
+      ],
+      "matched_term": "Bembix vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 7,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47744/61267/372850/133754/48959/320199/482431/129424",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 129424,
+      "name": "Zelus vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 633966,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/5292283/square.jpg?1477056217",
+        "attribution": "(c) Paul, all rights reserved, uploaded by creaturesnapper",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/5292283/medium.jpg?1477056217",
+        "id": 5292283,
+        "license_code": null,
+        "original_dimensions": {
+          "width": 1580,
+          "height": 1064
+        },
+        "url": "https://static.inaturalist.org/photos/5292283/square.jpg?1477056217"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47744,
+        61267,
+        372850,
+        133754,
+        48959,
+        320199,
+        482431,
+        129424,
+        633966
+      ],
+      "matched_term": "Zelus vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 4,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/48740/54028/201315/366768/563431",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 563431,
+      "name": "Ctenagenia vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 560666,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/30741827/square.jpg?1548679524",
+        "attribution": "(c) Paolo Mazzei, all rights reserved",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/30741827/medium.jpg?1548679524",
+        "id": 30741827,
+        "license_code": null,
+        "original_dimensions": {
+          "width": 800,
+          "height": 600
+        },
+        "url": "https://static.inaturalist.org/photos/30741827/square.jpg?1548679524"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        48740,
+        54028,
+        201315,
+        366768,
+        563431,
+        560666
+      ],
+      "matched_term": "Ctenagenia vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 4,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/48740/52747/343248/531700/752711",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 1,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 752711,
+      "name": "Pseudopolybia vespiceps",
+      "rank": "species",
+      "extinct": false,
+      "id": 752716,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/54013958/square.jpeg?1571007464",
+        "attribution": "(c) adrianomaciel, all rights reserved",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/54013958/medium.jpeg?1571007464",
+        "id": 54013958,
+        "license_code": null,
+        "original_dimensions": {
+          "width": 2048,
+          "height": 1536
+        },
+        "url": "https://static.inaturalist.org/photos/54013958/square.jpeg?1571007464"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        48740,
+        52747,
+        343248,
+        531700,
+        752711,
+        752716
+      ],
+      "matched_term": "Pseudopolybia vespiceps vespiceps",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 3,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/48740/52747/119344/428969",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 428969,
+      "name": "Hypodynerus vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 886207,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/29288906/square.jpg?1545155699",
+        "attribution": "(c) cmg_pdx, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/29288906/medium.jpg?1545155699",
+        "id": 29288906,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 1065,
+          "height": 795
+        },
+        "url": "https://static.inaturalist.org/photos/29288906/square.jpg?1545155699"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        48740,
+        52747,
+        119344,
+        428969,
+        886207
+      ],
+      "matched_term": "Hypodynerus vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 2,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47157/51269/51268",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Vespina",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 20,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 51268,
+      "name": "Vespina",
+      "rank": "genus",
+      "extinct": false,
+      "id": 84737,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47157,
+        51269,
+        51268,
+        84737
+      ],
+      "matched_term": "Vespina",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 2,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47744/61267/372868/51776/51777/319231/570423/605185",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 605185,
+      "name": "Moronopelios vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 605184,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/8932829/square.jpg?1499613099",
+        "attribution": "(c) kphuong7693, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/8932829/medium.jpg?1499613099",
+        "id": 8932829,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 1536,
+          "height": 2048
+        },
+        "url": "https://static.inaturalist.org/photos/8932829/square.jpg?1499613099"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47744,
+        61267,
+        372868,
+        51776,
+        51777,
+        319231,
+        570423,
+        605185,
+        605184
+      ],
+      "matched_term": "Moronopelios vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 2,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47822/48091/372853/414448/49995/326181/488425/520024/465579",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 465579,
+      "name": "Sphecomyia vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 876493,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/33293202/square.jpg?1553351857",
+        "attribution": "(c) Andrei, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/33293202/medium.jpg?1553351857",
+        "id": 33293202,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 1480,
+          "height": 1163
+        },
+        "url": "https://static.inaturalist.org/photos/33293202/square.jpg?1553351857"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47822,
+        48091,
+        372853,
+        414448,
+        49995,
+        326181,
+        488425,
+        520024,
+        465579,
+        876493
+      ],
+      "matched_term": "Sphecomyia vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 1,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47822/48091/372865/354603/47982/639471/639475/623118",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 623118,
+      "name": "Codula vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 983565,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/30581879/square.jpg?1548308953",
+        "attribution": "(c) Richard Yank, all rights reserved",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/30581879/medium.jpg?1548308953",
+        "id": 30581879,
+        "license_code": null,
+        "original_dimensions": {
+          "width": 2048,
+          "height": 1365
+        },
+        "url": "https://static.inaturalist.org/photos/30581879/square.jpg?1548308953"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47822,
+        48091,
+        372865,
+        354603,
+        47982,
+        639471,
+        639475,
+        623118,
+        983565
+      ],
+      "matched_term": "Codula vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/2/355675/47178/47286/51544/92786",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47178,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 92786,
+      "complete_rank": "subspecies",
+      "name": "Vespicula cypho",
+      "rank": "species",
+      "extinct": false,
+      "id": 621584,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        2,
+        355675,
+        47178,
+        47286,
+        51544,
+        92786,
+        621584
+      ],
+      "matched_term": "Vespicula cypho",
+      "iconic_taxon_name": "Actinopterygii"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/2/355675/47178/47286/51544/92786",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47178,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 92786,
+      "complete_rank": "subspecies",
+      "name": "Vespicula trachinoides",
+      "rank": "species",
+      "extinct": false,
+      "id": 621585,
+      "default_photo": {
+        "square_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/75px-FMIB_47485_Prosopodasys_gogorzae.jpeg",
+        "attribution": "David Starr Jordan\n, no known copyright restrictions (public domain)",
+        "flags": [],
+        "medium_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/500px-FMIB_47485_Prosopodasys_gogorzae.jpeg",
+        "id": 33535972,
+        "license_code": "pd",
+        "original_dimensions": null,
+        "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/75px-FMIB_47485_Prosopodasys_gogorzae.jpeg"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        2,
+        355675,
+        47178,
+        47286,
+        51544,
+        92786,
+        621585
+      ],
+      "matched_term": "Vespicula trachinoides",
+      "iconic_taxon_name": "Actinopterygii"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/2/355675/47178/47286/51544/92786",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47178,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 92786,
+      "complete_rank": "subspecies",
+      "name": "Vespicula zollingeri",
+      "rank": "species",
+      "extinct": false,
+      "id": 621586,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        2,
+        355675,
+        47178,
+        47286,
+        51544,
+        92786,
+        621586
+      ],
+      "matched_term": "Vespicula zollingeri",
+      "iconic_taxon_name": "Actinopterygii"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 0,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/48740/51967/469073/893840",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 893840,
+      "name": "Pygodasis vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 915291,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        48740,
+        51967,
+        469073,
+        893840,
+        915291
+      ],
+      "matched_term": "Pygodasis vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/47170/48250/83715/83716/200006/450114",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47170,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 450114,
+      "name": "Candida vespimorsuum",
+      "rank": "species",
+      "extinct": false,
+      "id": 554174,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        47170,
+        48250,
+        83715,
+        83716,
+        200006,
+        450114,
+        554174
+      ],
+      "matched_term": "Candida vespimorsuum",
+      "iconic_taxon_name": "Fungi"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 2,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/69750/125448/519360/250566",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 250566,
+      "name": "Vespita woolleyi",
+      "rank": "species",
+      "extinct": false,
+      "id": 299443,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        69750,
+        125448,
+        519360,
+        250566,
+        299443
+      ],
+      "matched_term": "Vespita woolleyi",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47157/47607/121850/47606/82089/82101/47988",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 47988,
+      "name": "Argyroeides vespina",
+      "rank": "species",
+      "extinct": false,
+      "id": 907874,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47157,
+        47607,
+        121850,
+        47606,
+        82089,
+        82101,
+        47988,
+        907874
+      ],
+      "matched_term": "Argyroeides vespina",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47822/48091/372865/354603/121526/699633",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 20,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 699633,
+      "name": "Vespiodes",
+      "rank": "genus",
+      "extinct": false,
+      "id": 646195,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47822,
+        48091,
+        372865,
+        354603,
+        121526,
+        699633,
+        646195
+      ],
+      "matched_term": "Vespiodes",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/2/355675/47178/47286/51544",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Vespicula",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47178,
+      "rank_level": 20,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": 3,
+      "parent_id": 51544,
+      "complete_rank": "subspecies",
+      "name": "Vespicula",
+      "rank": "genus",
+      "extinct": false,
+      "id": 92786,
+      "default_photo": {
+        "square_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/75px-FMIB_47485_Prosopodasys_gogorzae.jpeg",
+        "attribution": "David Starr Jordan\n, no known copyright restrictions (public domain)",
+        "flags": [],
+        "medium_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/500px-FMIB_47485_Prosopodasys_gogorzae.jpeg",
+        "id": 33535972,
+        "license_code": "pd",
+        "original_dimensions": null,
+        "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/75px-FMIB_47485_Prosopodasys_gogorzae.jpeg"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        2,
+        355675,
+        47178,
+        47286,
+        51544,
+        92786
+      ],
+      "matched_term": "Vespicula",
+      "iconic_taxon_name": "Actinopterygii"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 2,
+      "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/47951/373525/211904",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 211904,
+      "name": "Pseudopsis vespina",
+      "rank": "species",
+      "extinct": false,
+      "id": 267991,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47208,
+        71130,
+        372870,
+        48311,
+        47951,
+        373525,
+        211904,
+        267991
+      ],
+      "matched_term": "Pseudopsis vespina",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/245097/47119/47118/120474/342614/367172/60351/60357",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47119,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 60357,
+      "complete_rank": "subspecies",
+      "name": "Mimetus vespillo",
+      "rank": "species",
+      "extinct": false,
+      "id": 833068,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        245097,
+        47119,
+        47118,
+        120474,
+        342614,
+        367172,
+        60351,
+        60357,
+        833068
+      ],
+      "matched_term": "Mimetus vespillo",
+      "iconic_taxon_name": "Arachnida"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/47222/630955/47221/335715/340736/252728/572378",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 572378,
+      "name": "Odyneropsis vespiformis",
+      "rank": "species",
+      "extinct": false,
+      "id": 572367,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        47222,
+        630955,
+        47221,
+        335715,
+        340736,
+        252728,
+        572378,
+        572367
+      ],
+      "matched_term": "Odyneropsis vespiformis",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/69750/125448/519360",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 20,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 519360,
+      "name": "Vespita",
+      "rank": "genus",
+      "extinct": false,
+      "id": 250566,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        69750,
+        125448,
+        519360,
+        250566
+      ],
+      "matched_term": "Vespita",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47157/51269/51268/84737",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Vespina_quercivora",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 84737,
+      "name": "Vespina quercivora",
+      "rank": "species",
+      "extinct": false,
+      "id": 472528,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47157,
+        51269,
+        51268,
+        84737,
+        472528
+      ],
+      "matched_term": "Vespina quercivora",
+      "iconic_taxon_name": "Insecta"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/test/sample_data/get_taxa_autocomplete.json b/test/sample_data/get_taxa_autocomplete.json
new file mode 100644
index 0000000..e782293
--- /dev/null
+++ b/test/sample_data/get_taxa_autocomplete.json
@@ -0,0 +1,467 @@
+{
+  "total_results": 44,
+  "page": 1,
+  "per_page": 30,
+  "results": [
+    {
+      "observations_count": 121793,
+      "taxon_schemes_count": 2,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/48740",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 1,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Vespidae",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 30,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 48740,
+      "name": "Vespidae",
+      "rank": "family",
+      "extinct": false,
+      "id": 52747,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/13765/square.jpg?1545358964",
+        "attribution": "(c) C\u00c3\u00a9cile Bassaglia, some rights reserved (CC BY-NC-SA)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/13765/medium.jpg?1545358964",
+        "id": 13765,
+        "license_code": "cc-by-nc-sa",
+        "original_dimensions": {
+          "width": 1024,
+          "height": 679
+        },
+        "url": "https://static.inaturalist.org/photos/13765/square.jpg?1545358964"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        48740,
+        52747
+      ],
+      "matched_term": "Vespidae",
+      "iconic_taxon_name": "Insecta",
+      "preferred_common_name": "Hornets, Paper Wasps, Potter Wasps, and Allies"
+    },
+    {
+      "observations_count": 36400,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/48740/52747",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Vespinae",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 27,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 52747,
+      "name": "Vespinae",
+      "rank": "subfamily",
+      "extinct": false,
+      "id": 84738,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/11204897/square.jpeg?1508098617",
+        "attribution": "(c) brentnmoran, algunos derechos reservados (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/11204897/medium.jpeg?1508098617",
+        "id": 11204897,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 2048,
+          "height": 1365
+        },
+        "url": "https://static.inaturalist.org/photos/11204897/square.jpeg?1508098617"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        48740,
+        52747,
+        84738
+      ],
+      "matched_term": "Vespinae",
+      "iconic_taxon_name": "Insecta",
+      "preferred_common_name": "Hornets and Yellowjackets"
+    },
+    {
+      "observations_count": 187,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Nicrophorus_vespillo",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 53850,
+      "name": "Nicrophorus vespillo",
+      "rank": "species",
+      "extinct": false,
+      "id": 131878,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/24573164/square.jpg?1536478624",
+        "attribution": "(c) Robin Bad, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/24573164/medium.jpg?1536478624",
+        "id": 24573164,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 2048,
+          "height": 1365
+        },
+        "url": "https://static.inaturalist.org/photos/24573164/square.jpg?1536478624"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47208,
+        71130,
+        372870,
+        48311,
+        53849,
+        204079,
+        53850,
+        131878
+      ],
+      "matched_term": "Nicrophorus vespillo",
+      "iconic_taxon_name": "Insecta",
+      "preferred_common_name": "Vespillo Burying Beetle"
+    },
+    {
+      "observations_count": 12,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/326777/48740/52747/119344",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 1,
+        "resolved": 2
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 119344,
+      "name": "Vespidae st1",
+      "rank": "species",
+      "extinct": false,
+      "id": 495392,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/5563170/square.jpg?1479599057",
+        "attribution": "(c) Stephen Thorpe, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/5563170/medium.jpg?1479599057",
+        "id": 5563170,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 781,
+          "height": 925
+        },
+        "url": "https://static.inaturalist.org/photos/5563170/square.jpg?1479599057"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        326777,
+        48740,
+        52747,
+        119344,
+        495392
+      ],
+      "matched_term": "Vespidae st1",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 336,
+      "taxon_schemes_count": 2,
+      "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Nicrophorus_vespilloides",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 53850,
+      "name": "Nicrophorus vespilloides",
+      "rank": "species",
+      "extinct": false,
+      "id": 70118,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751",
+        "attribution": "(c) salvatore_infanti, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/38359335/medium.jpg?1557348751",
+        "id": 38359335,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 2048,
+          "height": 1365
+        },
+        "url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47208,
+        71130,
+        372870,
+        48311,
+        53849,
+        204079,
+        53850,
+        70118
+      ],
+      "matched_term": "Nicrophorus vespilloides",
+      "iconic_taxon_name": "Insecta",
+      "preferred_common_name": "Lesser Vespillo Burying Beetle"
+    },
+    {
+      "observations_count": 2,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/47120/372739/47158/184884/47157/51269/51268",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Vespina",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 20,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 51268,
+      "name": "Vespina",
+      "rank": "genus",
+      "extinct": false,
+      "id": 84737,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47157,
+        51269,
+        51268,
+        84737
+      ],
+      "matched_term": "Vespina",
+      "iconic_taxon_name": "Insecta"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/2/355675/47178/47286/51544/92786",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47178,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 92786,
+      "complete_rank": "subspecies",
+      "name": "Vespicula cypho",
+      "rank": "species",
+      "extinct": false,
+      "id": 621584,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        2,
+        355675,
+        47178,
+        47286,
+        51544,
+        92786,
+        621584
+      ],
+      "matched_term": "Vespicula cypho",
+      "iconic_taxon_name": "Actinopterygii"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/2/355675/47178/47286/51544/92786",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47178,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 92786,
+      "complete_rank": "subspecies",
+      "name": "Vespicula trachinoides",
+      "rank": "species",
+      "extinct": false,
+      "id": 621585,
+      "default_photo": {
+        "square_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/75px-FMIB_47485_Prosopodasys_gogorzae.jpeg",
+        "attribution": "David Starr Jordan\n, no known copyright restrictions (public domain)",
+        "flags": [],
+        "medium_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/500px-FMIB_47485_Prosopodasys_gogorzae.jpeg",
+        "id": 33535972,
+        "license_code": "pd",
+        "original_dimensions": null,
+        "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/FMIB_47485_Prosopodasys_gogorzae.jpeg/75px-FMIB_47485_Prosopodasys_gogorzae.jpeg"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        2,
+        355675,
+        47178,
+        47286,
+        51544,
+        92786,
+        621585
+      ],
+      "matched_term": "Vespicula trachinoides",
+      "iconic_taxon_name": "Actinopterygii"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 1,
+      "ancestry": "48460/1/2/355675/47178/47286/51544/92786",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47178,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 92786,
+      "complete_rank": "subspecies",
+      "name": "Vespicula zollingeri",
+      "rank": "species",
+      "extinct": false,
+      "id": 621586,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        2,
+        355675,
+        47178,
+        47286,
+        51544,
+        92786,
+        621586
+      ],
+      "matched_term": "Vespicula zollingeri",
+      "iconic_taxon_name": "Actinopterygii"
+    },
+    {
+      "observations_count": 0,
+      "taxon_schemes_count": 2,
+      "ancestry": "48460/1/47120/372739/47158/184884/47201/124417/69750/125448/519360/250566",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": null,
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 250566,
+      "name": "Vespita woolleyi",
+      "rank": "species",
+      "extinct": false,
+      "id": 299443,
+      "default_photo": null,
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47201,
+        124417,
+        69750,
+        125448,
+        519360,
+        250566,
+        299443
+      ],
+      "matched_term": "Vespita woolleyi",
+      "iconic_taxon_name": "Insecta"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/test/sample_data/get_taxa_by_id.json b/test/sample_data/get_taxa_by_id.json
new file mode 100644
index 0000000..4703f04
--- /dev/null
+++ b/test/sample_data/get_taxa_by_id.json
@@ -0,0 +1,954 @@
+{
+  "total_results": 1,
+  "page": 1,
+  "per_page": 30,
+  "results": [
+    {
+      "observations_count": 336,
+      "taxon_schemes_count": 2,
+      "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850",
+      "is_active": true,
+      "flag_counts": {
+        "unresolved": 0,
+        "resolved": 0
+      },
+      "wikipedia_url": "http://en.wikipedia.org/wiki/Nicrophorus_vespilloides",
+      "current_synonymous_taxon_ids": null,
+      "iconic_taxon_id": 47158,
+      "taxon_photos": [
+        {
+          "taxon_id": 70118,
+          "photo": {
+            "flags": [],
+            "type": "LocalPhoto",
+            "url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751",
+            "square_url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751",
+            "native_page_url": "https://www.inaturalist.org/photos/38359335",
+            "native_photo_id": "38359335",
+            "small_url": "https://static.inaturalist.org/photos/38359335/small.jpg?1557348751",
+            "original_url": "https://static.inaturalist.org/photos/38359335/original.jpg?1557348751",
+            "attribution": "(c) salvatore_infanti, some rights reserved (CC BY-NC)",
+            "medium_url": "https://static.inaturalist.org/photos/38359335/medium.jpg?1557348751",
+            "id": 38359335,
+            "license_code": "cc-by-nc",
+            "original_dimensions": {
+              "width": 2048,
+              "height": 1365
+            },
+            "large_url": "https://static.inaturalist.org/photos/38359335/large.jpg?1557348751"
+          },
+          "taxon": {
+            "taxon_schemes_count": 2,
+            "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850",
+            "min_species_ancestry": "48460,1,47120,372739,47158,184884,47208,71130,372870,48311,53849,204079,53850,70118",
+            "wikipedia_url": "http://en.wikipedia.org/wiki/Nicrophorus_vespilloides",
+            "current_synonymous_taxon_ids": null,
+            "iconic_taxon_id": 47158,
+            "created_at": "2011-05-01T07:20:55+00:00",
+            "taxon_changes_count": 0,
+            "complete_species_count": null,
+            "rank": "species",
+            "extinct": false,
+            "id": 70118,
+            "universal_search_rank": 336,
+            "ancestor_ids": [
+              48460,
+              1,
+              47120,
+              372739,
+              47158,
+              184884,
+              47208,
+              71130,
+              372870,
+              48311,
+              53849,
+              204079,
+              53850,
+              70118
+            ],
+            "observations_count": 336,
+            "is_active": true,
+            "flag_counts": {
+              "unresolved": 0,
+              "resolved": 0
+            },
+            "min_species_taxon_id": 70118,
+            "rank_level": 10,
+            "atlas_id": null,
+            "parent_id": 53850,
+            "name": "Nicrophorus vespilloides",
+            "default_photo": {
+              "square_url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751",
+              "attribution": "(c) salvatore_infanti, some rights reserved (CC BY-NC)",
+              "flags": [],
+              "medium_url": "https://static.inaturalist.org/photos/38359335/medium.jpg?1557348751",
+              "id": 38359335,
+              "license_code": "cc-by-nc",
+              "original_dimensions": {
+                "width": 2048,
+                "height": 1365
+              },
+              "url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751"
+            },
+            "iconic_taxon_name": "Insecta",
+            "preferred_common_name": "Lesser Vespillo Burying Beetle"
+          }
+        }
+      ],
+      "rank_level": 10,
+      "taxon_changes_count": 0,
+      "atlas_id": null,
+      "complete_species_count": null,
+      "parent_id": 53850,
+      "name": "Nicrophorus vespilloides",
+      "rank": "species",
+      "extinct": false,
+      "id": 70118,
+      "default_photo": {
+        "square_url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751",
+        "attribution": "(c) salvatore_infanti, some rights reserved (CC BY-NC)",
+        "flags": [],
+        "medium_url": "https://static.inaturalist.org/photos/38359335/medium.jpg?1557348751",
+        "id": 38359335,
+        "license_code": "cc-by-nc",
+        "original_dimensions": {
+          "width": 2048,
+          "height": 1365
+        },
+        "url": "https://static.inaturalist.org/photos/38359335/square.jpg?1557348751"
+      },
+      "ancestor_ids": [
+        48460,
+        1,
+        47120,
+        372739,
+        47158,
+        184884,
+        47208,
+        71130,
+        372870,
+        48311,
+        53849,
+        204079,
+        53850
+      ],
+      "iconic_taxon_name": "Insecta",
+      "preferred_common_name": "Lesser Vespillo Burying Beetle",
+      "ancestors": [
+        {
+          "observations_count": 19131154,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 7
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Animal",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 1,
+          "rank_level": 70,
+          "taxon_changes_count": 4,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 48460,
+          "complete_rank": "order",
+          "name": "Animalia",
+          "rank": "kingdom",
+          "extinct": false,
+          "id": 1,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/55133652/square.jpg?1572218969",
+            "attribution": "(c) Chien Lee, all rights reserved",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/55133652/medium.jpg?1572218969",
+            "id": 55133652,
+            "license_code": null,
+            "original_dimensions": {
+              "width": 1080,
+              "height": 721
+            },
+            "url": "https://static.inaturalist.org/photos/55133652/square.jpg?1572218969"
+          },
+          "ancestor_ids": [
+            48460,
+            1
+          ],
+          "iconic_taxon_name": "Animalia",
+          "preferred_common_name": "Animals"
+        },
+        {
+          "observations_count": 9438767,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460/1",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 1
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Arthropod",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 1,
+          "rank_level": 60,
+          "taxon_changes_count": 2,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 1,
+          "complete_rank": "order",
+          "name": "Arthropoda",
+          "rank": "phylum",
+          "extinct": false,
+          "id": 47120,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/4115/square.jpg?1545349417",
+            "attribution": "(c) Damien du Toit, some rights reserved (CC BY)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/4115/medium.jpg?1545349417",
+            "id": 4115,
+            "license_code": "cc-by",
+            "original_dimensions": {
+              "width": 640,
+              "height": 480
+            },
+            "url": "https://static.inaturalist.org/photos/4115/square.jpg?1545349417"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120
+          ],
+          "iconic_taxon_name": "Animalia",
+          "preferred_common_name": "Arthropods"
+        },
+        {
+          "observations_count": 8226302,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460/1/47120",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Hexapoda",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 1,
+          "rank_level": 57,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 47120,
+          "complete_rank": "order",
+          "name": "Hexapoda",
+          "rank": "subphylum",
+          "extinct": false,
+          "id": 372739,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/29253963/square.jpg?1545062858",
+            "attribution": "(c) Alan Manson, some rights reserved (CC BY)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/29253963/medium.jpg?1545062858",
+            "id": 29253963,
+            "license_code": "cc-by",
+            "original_dimensions": {
+              "width": 1396,
+              "height": 1159
+            },
+            "url": "https://static.inaturalist.org/photos/29253963/square.jpg?1545062858"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739
+          ],
+          "iconic_taxon_name": "Animalia",
+          "preferred_common_name": "Hexapods"
+        },
+        {
+          "observations_count": 8212912,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460/1/47120/372739",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 1,
+            "resolved": 29
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Insect",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 50,
+          "taxon_changes_count": 3,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 372739,
+          "complete_rank": "order",
+          "name": "Insecta",
+          "rank": "class",
+          "extinct": false,
+          "id": 47158,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/4744725/square.jpeg?1472813739",
+            "attribution": "(c) Jason Michael Crockwell, some rights reserved (CC BY-NC-ND)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/4744725/medium.jpeg?1472813739",
+            "id": 4744725,
+            "license_code": "cc-by-nc-nd",
+            "original_dimensions": {
+              "width": 2048,
+              "height": 1536
+            },
+            "url": "https://static.inaturalist.org/photos/4744725/square.jpeg?1472813739"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158
+          ],
+          "iconic_taxon_name": "Insecta",
+          "preferred_common_name": "Insects"
+        },
+        {
+          "observations_count": 8157224,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460/1/47120/372739/47158",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 3
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Pterygota",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 47,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 47158,
+          "complete_rank": "order",
+          "name": "Pterygota",
+          "rank": "subclass",
+          "extinct": false,
+          "id": 184884,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/33029706/square.jpg?1552913261",
+            "attribution": "(c) RAP, some rights reserved (CC BY-NC)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/33029706/medium.jpg?1552913261",
+            "id": 33029706,
+            "license_code": "cc-by-nc",
+            "original_dimensions": {
+              "width": 900,
+              "height": 600
+            },
+            "url": "https://static.inaturalist.org/photos/33029706/square.jpg?1552913261"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884
+          ],
+          "iconic_taxon_name": "Insecta",
+          "preferred_common_name": "Winged and Once-winged Insects"
+        },
+        {
+          "observations_count": 979878,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460/1/47120/372739/47158/184884",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 1
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Beetle",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 40,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 184884,
+          "name": "Coleoptera",
+          "rank": "order",
+          "extinct": false,
+          "id": 47208,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/33814912/square.jpeg?1554044732",
+            "attribution": "(c) Franz Anthony, algunos derechos reservados (CC BY-NC)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/33814912/medium.jpeg?1554044732",
+            "id": 33814912,
+            "license_code": "cc-by-nc",
+            "original_dimensions": {
+              "width": 1069,
+              "height": 1069
+            },
+            "url": "https://static.inaturalist.org/photos/33814912/square.jpeg?1554044732"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208
+          ],
+          "iconic_taxon_name": "Insecta",
+          "preferred_common_name": "Beetles"
+        },
+        {
+          "observations_count": 857104,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Polyphaga",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 37,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 47208,
+          "name": "Polyphaga",
+          "rank": "suborder",
+          "extinct": false,
+          "id": 71130,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/12466261/square.jpg?1513752231",
+            "attribution": "(c) Arnold Wijker, some rights reserved (CC BY-NC)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/12466261/medium.jpg?1513752231",
+            "id": 12466261,
+            "license_code": "cc-by-nc",
+            "original_dimensions": {
+              "width": 800,
+              "height": 714
+            },
+            "url": "https://static.inaturalist.org/photos/12466261/square.jpg?1513752231"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130
+          ],
+          "iconic_taxon_name": "Insecta",
+          "preferred_common_name": "Water, Rove, Scarab, Long-horned, Leaf, and Snout Beetles"
+        },
+        {
+          "observations_count": 33616,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Staphyliniformia",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 35,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 71130,
+          "name": "Staphyliniformia",
+          "rank": "infraorder",
+          "extinct": false,
+          "id": 372870,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/14776949/square.jpg?1545718794",
+            "attribution": "(c) Pierre Bornand, some rights reserved (CC BY-NC)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/14776949/medium.jpg?1545718794",
+            "id": 14776949,
+            "license_code": "cc-by-nc",
+            "original_dimensions": {
+              "width": 2048,
+              "height": 1536
+            },
+            "url": "https://static.inaturalist.org/photos/14776949/square.jpg?1545718794"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870
+          ],
+          "iconic_taxon_name": "Insecta",
+          "preferred_common_name": "Staphyliniform Beetles"
+        },
+        {
+          "observations_count": 28105,
+          "taxon_schemes_count": 2,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Staphylinoidea",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 33,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 372870,
+          "name": "Staphylinoidea",
+          "rank": "superfamily",
+          "extinct": false,
+          "id": 48311,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/19900/square.jpg?1545365918",
+            "attribution": "(c) Robert, some rights reserved (CC BY-NC)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/19900/medium.jpg?1545365918",
+            "id": 19900,
+            "license_code": "cc-by-nc",
+            "original_dimensions": {
+              "width": 960,
+              "height": 1280
+            },
+            "url": "https://static.inaturalist.org/photos/19900/square.jpg?1545365918"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870,
+            48311
+          ],
+          "iconic_taxon_name": "Insecta",
+          "preferred_common_name": "Rove, Ant-like stone, and Carrion Beetles"
+        },
+        {
+          "observations_count": 10508,
+          "taxon_schemes_count": 1,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Silphidae",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 30,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 48311,
+          "name": "Silphidae",
+          "rank": "family",
+          "extinct": false,
+          "id": 53849,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/24573164/square.jpg?1536478624",
+            "attribution": "(c) Robin Bad, some rights reserved (CC BY-NC)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/24573164/medium.jpg?1536478624",
+            "id": 24573164,
+            "license_code": "cc-by-nc",
+            "original_dimensions": {
+              "width": 2048,
+              "height": 1365
+            },
+            "url": "https://static.inaturalist.org/photos/24573164/square.jpg?1536478624"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870,
+            48311,
+            53849
+          ],
+          "iconic_taxon_name": "Insecta",
+          "preferred_common_name": "Burying and Carrion Beetles"
+        },
+        {
+          "observations_count": 4508,
+          "taxon_schemes_count": 1,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Nicrophorini",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 27,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 53849,
+          "name": "Nicrophorinae",
+          "rank": "subfamily",
+          "extinct": false,
+          "id": 204079,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/722951/square.jpg?1544743338",
+            "attribution": "(c) Natural History Museum:  Coleoptera Section, some rights reserved (CC BY-NC-SA)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/722951/medium.jpg?1544743338",
+            "id": 722951,
+            "license_code": "cc-by-nc-sa",
+            "original_dimensions": {
+              "width": 374,
+              "height": 500
+            },
+            "url": "https://static.inaturalist.org/photos/722951/square.jpg?1544743338"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870,
+            48311,
+            53849,
+            204079
+          ],
+          "iconic_taxon_name": "Insecta"
+        },
+        {
+          "observations_count": 4506,
+          "taxon_schemes_count": 1,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": "http://en.wikipedia.org/wiki/Burying_beetle",
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 20,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 204079,
+          "name": "Nicrophorus",
+          "rank": "genus",
+          "extinct": false,
+          "id": 53850,
+          "default_photo": {
+            "square_url": "https://static.inaturalist.org/photos/84004/square.jpg?1545389819",
+            "attribution": "(c) Dave, some rights reserved (CC BY-NC-SA)",
+            "flags": [],
+            "medium_url": "https://static.inaturalist.org/photos/84004/medium.jpg?1545389819",
+            "id": 84004,
+            "license_code": "cc-by-nc-sa",
+            "original_dimensions": {
+              "width": 660,
+              "height": 747
+            },
+            "url": "https://static.inaturalist.org/photos/84004/square.jpg?1545389819"
+          },
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870,
+            48311,
+            53849,
+            204079,
+            53850
+          ],
+          "iconic_taxon_name": "Insecta",
+          "preferred_common_name": "Burying Beetles"
+        }
+      ],
+      "children": [
+        {
+          "observations_count": 0,
+          "taxon_schemes_count": 1,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850/70118",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": null,
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 5,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 70118,
+          "name": "Nicrophorus vespilloides aurora",
+          "rank": "variety",
+          "extinct": false,
+          "id": 70114,
+          "default_photo": null,
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870,
+            48311,
+            53849,
+            204079,
+            53850,
+            70118,
+            70114
+          ],
+          "iconic_taxon_name": "Insecta"
+        },
+        {
+          "observations_count": 0,
+          "taxon_schemes_count": 1,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850/70118",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": null,
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 5,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 70118,
+          "name": "Nicrophorus vespilloides sylvivagus",
+          "rank": "subspecies",
+          "extinct": false,
+          "id": 70116,
+          "default_photo": null,
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870,
+            48311,
+            53849,
+            204079,
+            53850,
+            70118,
+            70116
+          ],
+          "iconic_taxon_name": "Insecta"
+        },
+        {
+          "observations_count": 0,
+          "taxon_schemes_count": 1,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850/70118",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": null,
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 5,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 70118,
+          "name": "Nicrophorus vespilloides altumi",
+          "rank": "form",
+          "extinct": false,
+          "id": 70115,
+          "default_photo": null,
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870,
+            48311,
+            53849,
+            204079,
+            53850,
+            70118,
+            70115
+          ],
+          "iconic_taxon_name": "Insecta"
+        },
+        {
+          "observations_count": 0,
+          "taxon_schemes_count": 1,
+          "ancestry": "48460/1/47120/372739/47158/184884/47208/71130/372870/48311/53849/204079/53850/70118",
+          "is_active": true,
+          "flag_counts": {
+            "unresolved": 0,
+            "resolved": 0
+          },
+          "wikipedia_url": null,
+          "current_synonymous_taxon_ids": null,
+          "iconic_taxon_id": 47158,
+          "rank_level": 5,
+          "taxon_changes_count": 0,
+          "atlas_id": null,
+          "complete_species_count": null,
+          "parent_id": 70118,
+          "name": "Nicrophorus vespilloides subfasciatus",
+          "rank": "variety",
+          "extinct": false,
+          "id": 70117,
+          "default_photo": null,
+          "ancestor_ids": [
+            48460,
+            1,
+            47120,
+            372739,
+            47158,
+            184884,
+            47208,
+            71130,
+            372870,
+            48311,
+            53849,
+            204079,
+            53850,
+            70118,
+            70117
+          ],
+          "iconic_taxon_name": "Insecta"
+        }
+      ],
+      "conservation_statuses": [],
+      "listed_taxa_count": 4,
+      "listed_taxa": [
+        {
+          "id": 5577060,
+          "taxon_id": 70118,
+          "establishment_means": "native",
+          "place": {
+            "id": 1,
+            "name": "United States",
+            "display_name": "United States",
+            "admin_level": 0,
+            "ancestor_place_ids": [
+              97394,
+              1
+            ]
+          },
+          "list": {
+            "id": 299,
+            "title": "United States Check List"
+          }
+        },
+        {
+          "id": 5680497,
+          "taxon_id": 70118,
+          "establishment_means": "native",
+          "place": {
+            "id": 6712,
+            "name": "Canada",
+            "display_name": "Canada",
+            "admin_level": 0,
+            "ancestor_place_ids": [
+              97394,
+              6712
+            ]
+          },
+          "list": {
+            "id": 187791,
+            "title": "NatureServe Canada"
+          }
+        },
+        {
+          "id": 5577061,
+          "taxon_id": 70118,
+          "establishment_means": "native",
+          "place": {
+            "id": 6,
+            "name": "Alaska",
+            "display_name": "Alaska, US",
+            "admin_level": 1,
+            "ancestor_place_ids": [
+              97394,
+              1,
+              6
+            ]
+          },
+          "list": {
+            "id": 304,
+            "title": "Alaska Check List"
+          }
+        },
+        {
+          "id": 5577062,
+          "taxon_id": 70118,
+          "establishment_means": "native",
+          "place": {
+            "id": 341,
+            "name": "Kenai Peninsula",
+            "display_name": "Kenai Peninsula County, US, AK",
+            "admin_level": 2,
+            "ancestor_place_ids": [
+              97394,
+              1,
+              6,
+              341
+            ]
+          },
+          "list": {
+            "id": 639,
+            "title": "Kenai Peninsula Borough Check List"
+          }
+        }
+      ],
+      "wikipedia_summary": "<i><b>Nicrophorus vespilloides</b></i> is a burying beetle described by Johann Friedrich Wilhelm Herbst in 1783."
+    }
+  ]
+}
\ No newline at end of file
diff --git a/test/test_pyinaturalist.py b/test/test_pyinaturalist.py
index 16463a8..1654521 100755
--- a/test/test_pyinaturalist.py
+++ b/test/test_pyinaturalist.py
@@ -4,13 +4,21 @@ Tests for `pyinaturalist` module.
 import json
 import os
 from datetime import datetime, timedelta
+from unittest.mock import patch
 
 import pytest
 import requests_mock
 from requests import HTTPError
+from urllib.parse import urlencode, urljoin
 
 import pyinaturalist
-from pyinaturalist.node_api import get_observation
+from pyinaturalist.constants import INAT_NODE_API_BASE_URL
+from pyinaturalist.node_api import (
+    get_observation,
+    get_taxa,
+    get_taxa_by_id,
+    get_taxa_autocomplete,
+)
 from pyinaturalist.rest_api import (
     get_access_token,
     get_all_observation_fields,
@@ -37,11 +45,9 @@ PAGE_2_JSON_RESPONSE = _load_sample_json("get_observation_fields_page2.json")
 
 
 class TestNodeApi(object):
-    @requests_mock.Mocker(kw="mock")
-    def test_get_observation(self, **kwargs):
-        mock = kwargs["mock"]
-        mock.get(
-            "https://api.inaturalist.org/v1/observations?id=16227955",
+    def test_get_observation(self, requests_mock):
+        requests_mock.get(
+            urljoin(INAT_NODE_API_BASE_URL, "observations?id=16227955"),
             json=_load_sample_json("get_observation.json"),
             status_code=200,
         )
@@ -52,17 +58,94 @@ class TestNodeApi(object):
         assert obs_data["user"]["login"] == "niconoe"
         assert len(obs_data["photos"]) == 2
 
-    @requests_mock.Mocker(kw="mock")
-    def test_get_non_existent_observation(self, **kwargs):
-        mock = kwargs["mock"]
-        mock.get(
-            "https://api.inaturalist.org/v1/observations?id=99999999",
+    def test_get_non_existent_observation(self, requests_mock):
+        requests_mock.get(
+            urljoin(INAT_NODE_API_BASE_URL, "observations?id=99999999"),
             json=_load_sample_json("get_nonexistent_observation.json"),
             status_code=200,
         )
         with pytest.raises(ObservationNotFound):
             get_observation(observation_id=99999999)
 
+    def test_get_taxa(self, requests_mock):
+        params = urlencode({"q": "vespi", "rank": "genus,subgenus,species"})
+        requests_mock.get(
+            urljoin(INAT_NODE_API_BASE_URL, "taxa?" + params),
+            json=_load_sample_json("get_taxa.json"),
+            status_code=200,
+        )
+
+        response = get_taxa(q="vespi", rank=["genus", "subgenus", "species"])
+        first_result = response["results"][0]
+
+        assert len(response["results"]) == 30
+        assert response["total_results"] == 35
+        assert first_result["id"] == 70118
+        assert first_result["name"] == "Nicrophorus vespilloides"
+        assert first_result["rank"] == "species"
+        assert first_result["is_active"] is True
+        assert len(first_result["ancestor_ids"]) == 14
+
+    CLASS_AND_HIGHER = ["class", "superclass", "subphylum", "phylum", "kingdom"]
+    SPECIES_AND_LOWER = ["form", "variety", "subspecies", "hybrid", "species"]
+    CLASS_THOUGH_PHYLUM = ["class", "superclass", "subphylum", "phylum"]
+
+    @pytest.mark.parametrize(
+        "params, expected_ranks",
+        [
+            ({"rank": "genus"}, "genus"),
+            ({"min_rank": "class"}, CLASS_AND_HIGHER),
+            ({"max_rank": "species"}, SPECIES_AND_LOWER),
+            ({"min_rank": "class", "max_rank": "phylum"}, CLASS_THOUGH_PHYLUM),
+            ({"max_rank": "species", "rank": "override_me"}, SPECIES_AND_LOWER),
+        ],
+    )
+    @patch("pyinaturalist.node_api.make_inaturalist_api_get_call")
+    def test_get_taxa_by_rank_range(
+        self, mock_inaturalist_api_get_call, params, expected_ranks,
+    ):
+        # Make sure custom rank params result in the correct 'rank' param value
+        get_taxa(**params)
+        mock_inaturalist_api_get_call.assert_called_with(
+            "taxa", {"rank": expected_ranks}, user_agent=None
+        )
+
+    def test_get_taxa_by_id(self, requests_mock):
+        taxon_id = 70118
+        requests_mock.get(
+            urljoin(INAT_NODE_API_BASE_URL, "taxa/" + str(taxon_id)),
+            json=_load_sample_json("get_taxa_by_id.json"),
+            status_code=200,
+        )
+
+        response = get_taxa_by_id(taxon_id)
+        result = response["results"][0]
+        assert len(response["results"]) == 1
+        assert result["id"] == taxon_id
+        assert result["name"] == "Nicrophorus vespilloides"
+        assert result["rank"] == "species"
+        assert result["is_active"] is True
+        assert len(result["ancestors"]) == 12
+
+    def test_get_taxa_autocomplete(self, requests_mock):
+        requests_mock.get(
+            urljoin(INAT_NODE_API_BASE_URL, "taxa/autocomplete?q=vespi"),
+            json=_load_sample_json("get_taxa_autocomplete.json"),
+            status_code=200,
+        )
+
+        response = get_taxa_autocomplete(q="vespi")
+        first_result = response["results"][0]
+
+        assert len(response["results"]) == 10
+        assert response["total_results"] == 44
+        assert first_result["matched_term"] == "Vespidae"
+        assert first_result["id"] == 52747
+        assert first_result["name"] == "Vespidae"
+        assert first_result["rank"] == "family"
+        assert first_result["is_active"] is True
+        assert len(first_result["ancestor_ids"]) == 11
+
 
 class TestRestApi(object):
     @requests_mock.Mocker(kw="mock")
@@ -325,7 +408,7 @@ class TestRestApi(object):
         # TODO: test for all functions that access the inaturalist API?
         mock = kwargs["mock"]
         mock.get(
-            "https://api.inaturalist.org/v1/observations?id=16227955",
+            urljoin(INAT_NODE_API_BASE_URL, "observations?id=16227955"),
             json=_load_sample_json("get_observation.json"),
             status_code=200,
         )