API Reference

Note: a faster API with more consistent response formats can be found at api.inaturalist.org. You will still need to refer to these docs for obtaining an OAuth access token.

The iNat API is a set of REST endpoints that can be used to read data from iNat and write data back on the behalf of users. Data can be retrieved in different formats by appending .[format] to the endpoint, e.g. /observations.json to retrieve observations as JSON. Read-only endpoints generally do not require authentication, but if you want to access data like unobscured coordinates on behalf of users or write data to iNat, you will need to make authenticated requests (see below).

Note that endpoints that receive binary data must have the Content-Type: multipart-formdata header and parts that are not binary should be simple form data, even if you're requesting JSON data.

Authentication

iNaturalist is an OAuth2 provider and supports the Authorization Code, Resource Owner Password Credentials, and Proof Key for Code Exchange (PKCE) flows, as well as some custom auth flows for 3rd party authentication. Methods marked Auth required require authentication via one of the aforementioned methods. Please make sure to use https://www.inaturalist.org as the base URL for authorization flows and for authenticated requests to ensure passwords and access tokens are encrypted. Unfortunately we must maintain the vanilla http endpoints for backward compatability, but all future API users should make requests with SSL. Note that many PUT and DELETE methods also check for ownership and will fail if you try to use them when not authenticated as the user who owns the associated resources.

Auth Examples

Before you make any authenticated requests, you'll need to create an iNat application. The redirect_uri should be functioning URL to which users will be redirected upon successfully authorizing your app with access to the user's iNat data.

There are plenty of language-specific OAuth2 libraries out there, so find one you like or get familiar enough with OAuth2 to construct requests and manage redirect flows yourself. The following examples use Ruby's oauth2 gem.

Authorization Code Flow

This is what you'll want to use if your app is a web app, and/or you're sure you're users can open a web browser for auth *and* you can store your client secret in a secure fashion. The rough outline is you redirect your user to iNat, the user is offered the choice to authorize your app with access to their iNat data, and if they agree, they are redirected to the redirect_uri you specified with an access_token in the params.

Proof Key for Code Exchange Flow

This is a variation on the Authorization Code Flow for use in situations where you cannot store your client secret securely, e.g. in a client-side Javascript application or a mobile application that could be decompiled. Instead of providing a secret to identify itself, the client provides a hashed, single-use "code verifier" when requesting an authorization code. When the client requests an access token it must provide the unhashed code verifier to verify that it is the same client that requested the authorization code. More details at the IETF, but the Doorkeeper docs might be easier to read.

Resource Owner Password Credentials Flow

Retrieve an access token based on the user's iNat username and password. This is more for desktop and mobile apps, or any situation where you can store a user's password and they have reason to trust you, i.e. not for web.

Assertion Flow

This is roughly based on http://tools.ietf.org/html/draft-ietf-oauth-assertions-01#section-6.3 and used to retrieve an access token for a user based on a 3rd party access token from Facebook or Google. It assumes the user is already a member of iNat or wants to be, and uses the 3rd party token to sign them up and / or authenticate them. It returns an access token without the authorization step. This method is only available to partners we're working with directly.

Endpoints

All of these endpoints should use https://www.inaturalist.org as the base URL, particularly endpoints that require auth.

POST /comments

Auth required

Create comments. Comments are automatically associated with the signed in user.

Formats: json

Params

comment[parent_type]
Type of parent record to which this comment is being added.
AssessmentSection | ListedTaxon | Observation | ObservationField | Post | TaxonChange
comment[parent_id]
Parent record ID
Valid iNat record ID
comment[body]
Comment body.

PUT /comments/:id

Auth required

Update a comment. Params are the same as POST /comments.

Formats: json

DELETE /comments/:id

Auth required

Delete a comment.

Formats: json

POST /identifications

Auth required

Create identifications. Identifications are automatically associated with the signed in user.

Formats: json

Params

identification[observation_id]
ID of the associated observation
Valid iNat observation ID
identification[taxon_id]
ID of the associated taxon
Valid iNat taxon ID
identification[body]
Optional user remarks on the identification.

PUT /identifications/:id

Auth required

Update a identification. Params are the same as POST /identifications.

Formats: json

DELETE /identifications/:id

Auth required

Delete a identification.

Formats: json

GET /observations

Primary endpoint for retrieving observations. If you're looking for pagination info, check the X headers in the response. You should see X-Total-Entries, X-Page, and X-Per-Page. JSON and ATOM responses are what you'd expect, but DwC is Simple Darwin Core, an XML schema for biodiversity data. iNat uses JSON responses internally quite a bit, so it will probably always be the most information-rich. The widget response is a JS snippet that inserts HTML. It should be used with a script tag, e.g.

<script
src="http://www.inaturalist.org/observations.widget"></script>
. Note that while this endpoint doesn't require authentication under normal circumstances, it WILL require it when you request pages higher than 100. If you're going to scrape us, we want to know who you are.

Formats: atom, csv, dwc, json, kml, widget

Params

q
Search query. Note that this is largely intended to be used on its own and may yield unexpected or limited results when used with other filters. If you're trying to retrieve observations of a particular taxon, taxon_id and taxon_name are better options.
any string
page
any integer
per_page
1 to 200
order_by
Field to sort by
observed_on
date observed
date_added
date added to iNat
order
Sort order
asc | desc
license
Specify the license users have applied to their observations.
none
No license specified, observer withholds all rights to distribution.
any
Observation licensed, see response for license specified.
CC-BY
Creative Commons Attribution License
CC-BY-NC
Creative Commons Attribution-NonCommercial License
CC-BY-SA
Creative Commons Attribution-ShareAlike License
CC-BY-ND
Creative Commons Attribution-NoDerivs License
CC-BY-NC-SA
Creative Commons Attribution-NonCommercial-ShareAlike License
CC-BY-NC-ND
Creative Commons Attribution-NonCommercial-NoDerivs License
photo_license
Filter by the license of the associated photos.
Same as license param
taxon_id
Filter by iNat taxon ID. Note that this will also select observations of descendant taxa.
valid iNat taxon ID
taxon_name
Filter by iNat taxon name. Note that this will also select observations of descendant taxa. Note that names are not unique, so if the name matches multiple taxa, no observations may be returned.
Name string
iconic_taxa[]
Filter by iconic taxa. Can be used multiple times, e.g. iconic_taxa[]=Fungi&iconic_taxa[]=Mammalia
Plantae | Animalia | Mollusca | Reptilia | Aves | Amphibia | Actinopterygii | Mammalia | Insecta | Arachnida | Fungi | Protozoa | Chromista | unknown
has[]
Catch-all for some boolean selectors. This can be used multiple times, e.g. has[]=photos&has[]=geo
photos
only show observations with photos
geo
only show georeferenced observations
quality_grade
Filter by quality grade
casual | research
out_of_range
Filter by whether or not iNat considers the observation out of range for the associated taxon. This is based on iNat's range data.
true
on
Filter by date string
Date strings in the form yyyy-mm-dd, e.g. 2001-05-02. You can also omit day and/or month, e.g. 2001-05 and 2001
year
Filter by year
any integer
month
Filter by month
1 to 12
day
Filter by day of the month
1 to 31
d1
First date of a date range
Date strings in the form yyyy-mm-dd, e.g. 2001-05-02.
d2
Last date of a date range
Date strings in the form yyyy-mm-dd, e.g. 2001-05-02.
m1
First month of a month range
1 to 12
m2
Last month of a month range
1 to 12
h1
First hour of a hour range
0 to 23
h2
Last hour of a hour range
0 to 23
swlat
Southwest latitude of a bounding box query.
-90 to 90
swlng
Southwest longitude of a bounding box query.
-180 to 180
nelat
Northeast latitude of a bounding box query.
-90 to 90
nelng
Northeast longitude of a bounding box query.
-180 to 180
list_id
Restrict results to observations of taxa on the specified list. Limited to lists with 2000 taxa or less.
iNat list ID
updated_since
Filter by observations that have been updated since a timestamp.
ISO 8601 datetime, e.g. 2013-10-09T13:40:13-07:00
extra
Retrieve additional information. 'projects' returns info about the projects the observations have been added to, 'fields' returns observation field values, 'observation_photos' returns information about the photos' relationship with the observation, like their order.
fields | identifications | projects

Example

Request (try it)
/observations.json
Response
[{
    "user_login": "greatjon",
    "place_guess": "San Francisco, San Francisco",
    "location_is_exact": false,
    "quality_grade": "casual",
    "latitude": 37.713539,
    "created_at": "2012-04-10T21:48:25-07:00",
    "timeframe": null,
    "species_guess": "gray wolf",
    "observed_on": "2012-04-10",
    "num_identification_disagreements": 0,
    "delta": true,
    "updated_at": "2012-04-10T21:49:50-07:00",
    "num_identification_agreements": 0,
    "license": null,
    "geoprivacy": null,
    "positional_accuracy": 354,
    "coordinates_obscured": false,
    "taxon_id": 42048,
    "id": 2281,
    "iconic_taxon": {
        "name": "Mammalia",
        "ancestry": "48460/1/2",
        "rank": "class",
        "id": 40151,
        "rank_level": 50,
        "iconic_taxon_name": "Mammalia"
    },
    "time_observed_at_utc": "2012-04-11T04:47:55Z",
    "user_id": 53,
    "time_observed_at": "2012-04-10T21:47:55-07:00",
    "observed_on_string": "Tue Apr 10 2012 21:47:55 GMT-0700 (PDT)",
    "short_description": "",
    "time_zone": "Pacific Time (US & Canada)",
    "out_of_range": null,
    "longitude": -122.340054,
    "description": "",
    "user": {
        "login": "greatjon"
    },
    "positioning_method": null,
    "map_scale": null,
    "photos": [],
    "iconic_taxon_name": "Mammalia",
    "positioning_device": null,
    "iconic_taxon_id": 40151
}]

POST /observations

Auth required

Primary endpoint for creating observations. POST params can be specified for a single observation (e.g. observation[species_guess]) or as multiple to add a multiple observations at a time (e.g. observations[0][species_guess]).

Formats: html, json

Params

observation[species_guess]
Equivalent of the "What did you see?" field on the observation form, this is the name of the organism observed. If the taxon ID is absent, iNat will try to choose a single taxon based on this string, but it may fail if there's some taxonomic amgiguity.
observation[taxon_id]
ID of the taxon to associate with this observation. An identification for this taxon will automatically be added for the user."
valid iNat taxon ID
observation[observed_on_string]
Text representation of the date/time of the observation.
iNat is pretty flexible in the dates it can parse out of this value. Here are some examples
  • 2 days ago
  • January 21st, 2010
  • 2012-01-05
  • October 30, 2008 10:31PM
  • 2011-12-23T11:52:06-0500
  • July 9, 2012 7:52:39 AM ACST
  • September 27, 2012 8:09:50 AM GMT+01:00
The only constraint is that dates may not be in the future. Time zone will default to the user's default time zone if not specified.
observation[time_zone]
Time zone the observation was made in.
Abu Dhabi | Adelaide | Africa/Johannesburg | Alaska | Almaty | American Samoa | Amsterdam | Arizona | Asia/Magadan | Astana | Athens | Atlantic Time (Canada) | Atlantic/Cape_Verde | Auckland | Australia/Perth | Azores | Baghdad | Baku | Bangkok | Beijing | Belgrade | Berlin | Bern | Bogota | Brasilia | Bratislava | Brisbane | Brussels | Bucharest | Budapest | Buenos Aires | Cairo | Canberra | Cape Verde Is. | Caracas | Casablanca | Central America | Central Time (US & Canada) | Chennai | Chihuahua | Chongqing | Copenhagen | Darwin | Dhaka | Dublin | Eastern Time (US & Canada) | Edinburgh | Ekaterinburg | Europe/London | Fiji | Georgetown | Greenland | Guadalajara | Guam | Hanoi | Harare | Hawaii | Helsinki | Hobart | Hong Kong | Indiana (East) | International Date Line West | Irkutsk | Islamabad | Istanbul | Jakarta | Jerusalem | Kabul | Kamchatka | Karachi | Kathmandu | Kolkata | Krasnoyarsk | Kuala Lumpur | Kuwait | Kyiv | La Paz | Lima | Lisbon | Ljubljana | London | Madrid | Magadan | Marshall Is. | Mazatlan | Melbourne | Mexico City | Mid-Atlantic | Midway Island | Minsk | Monrovia | Monterrey | Moscow | Mountain Time (US & Canada) | Mumbai | Muscat | Nairobi | New Caledonia | New Delhi | Newfoundland | Novosibirsk | Nuku'alofa | Osaka | Pacific Time (US & Canada) | Pacific/Majuro | Pacific/Port_Moresby | Paris | Perth | Port Moresby | Prague | Pretoria | Quito | Rangoon | Riga | Riyadh | Rome | Samoa | Santiago | Sapporo | Sarajevo | Saskatchewan | Seoul | Singapore | Skopje | Sofia | Solomon Is. | Sri Jayawardenepura | St. Petersburg | Stockholm | Sydney | Taipei | Tallinn | Tashkent | Tbilisi | Tehran | Tijuana | Tokelau Is. | Tokyo | UTC | Ulaan Bataar | Urumqi | Vienna | Vilnius | Vladivostok | Volgograd | Warsaw | Wellington | West Central Africa | Yakutsk | Yerevan | Zagreb
observation[description]
Observation description
observation[tag_list]
Comma-separated list of tags
Comma-separated strings
observation[place_guess]
Name of the place where the observation was recorded. Not that iNat will *not* try to automatically look up coordinates based on this string. That task is uncertain enough that the UI should perform it so the user can confirm it."
Any string
observation[latitude]
Latitude of the observation. Presumed datum is WGS84.
-90 to 90
observation[longitude]
Longitude of the observation. Presumed datum is WGS84.
-180 to 180
observation[map_scale]
Google Maps zoom level at which to show this observation's map marker.
0 to 19
observation[positional_accuracy]
Positional accuracy of the observation coordinates in meters.
Any positive integer
observation[geoprivacy]
Geoprivacy for the observation
open | obscured | private
observation[observation_field_values_attributes][order]
Nested fields for observation field values are specified in the observation_field_values_attributes param. order is just an integer starting with zero specifying the order of entry.
ObservationFieldValue attributes. So you might specify an entire observation field value for an observation field with an ID of 1 as observation[observation_field_values_attributes][0][observation_field_id]=1&observation[observation_field_values_attributes][0][value]=foo.
flickr_photos[]
List of Flickr photo IDs to add as photos for this observation. User must have their Flickr and iNat accounts connected and the user must own the photo on Flickr.
Valid Flickr photo ID of a photo belonging to the user. Flickr photo IDs are integers.
picasa_photos[]
List of Picasa photo IDs to add as photos for this observation. User must have their Picasa and iNat accounts connected and the user must own the photo on Picasa.
Valid Flickr photo ID of a photo belonging to the user.
facebook_photos[]
List of Facebook photo IDs to add as photos for this observation. User must have their Facebook and iNat accounts connected and the user must own the photo on Facebook.
Valid Facebook photo ID of a photo belonging to the user.
local_photos[]
List of fields containing uploaded photo data. Request must have a Content-Type of "multipart." We recommend that you use the POST /observation_photos endpoint instead.
Photo data

Example

Request
/observations.json?
          observation[species_guess]=Northern+Cardinal&
          observation[taxon_id]=9083&
          observation[observed_on_string]=2013-01-03&
          observation[time_zone]=Eastern+Time+(US+%26+Canada)&
          observation[description]=what+a+cardinal&
          observation[tag_list]=foo,bar&
          observation[place_guess]=clinton,+ct&
          observation[latitude]=41.27872259999999&
          observation[longitude]=-72.5276073&
          observation[map_scale]=11&
          observation[location_is_exact]=false&
          observation[positional_accuracy]=7798&
          observation[geoprivacy]=obscured&
          observation[observation_field_values_attributes][0][observation_field_id]=5&
          observation[observation_field_values_attributes][0][value]=male&
          flickr_photos[0]=8331632744
Response
[
          {
            "created_at": "2013-01-15T15:04:57-05:00",
            "delta": true,
            "description": "what a cardinal",
            "geoprivacy": "obscured",
            "iconic_taxon_id": 3,
            "id": 3281,
            "latitude": "41.2995543746",
            "license": "CC-BY",
            "location_is_exact": false,
            "longitude": "-72.5571845909",
            "map_scale": 11,
            "num_identification_agreements": 0,
            "num_identification_disagreements": 0,
            "observed_on": "2013-01-03",
            "observed_on_string": "2013-01-03",
            "out_of_range": null,
            "place_guess": "clinton, ct",
            "positional_accuracy": 7798,
            "positioning_device": null,
            "positioning_method": null,
            "quality_grade": "casual",
            "species_guess": "Northern Cardinal",
            "taxon_id": 9083,
            "time_observed_at": null,
            "time_zone": "Eastern Time (US & Canada)",
            "timeframe": null,
            "updated_at": "2013-01-15T17:10:02-05:00",
            "uri": "http://www.inaturalist.org/observations/3281",
            "user_id": 1,
            "user_login": "kueda",
            "iconic_taxon_name": "Aves",
            "created_at_utc": "2013-01-15T20:04:57Z",
            "updated_at_utc": "2013-01-15T22:10:02Z",
            "time_observed_at_utc": null,
            "coordinates_obscured": true,
            "observation_field_values": [{
              "created_at": "2013-01-15T15:05:00-05:00",
              "id": 403,
              "observation_field_id": 5,
              "observation_id": 3281,
              "updated_at": "2013-01-15T15:05:00-05:00",
              "value": "male"
            }],
            "project_observations": [],
            "observation_photos": [{
              "created_at": "2013-01-15T15:04:59-05:00",
              "id": 995,
              "observation_id": 3281,
              "photo_id": 1298,
              "position": null,
              "updated_at": "2013-01-15T15:04:59-05:00",
              "photo": {
                "created_at": "2013-01-15T15:04:59-05:00",
                "file_content_type": null,
                "file_file_name": null,
                "file_file_size": null,
                "file_processing": null,
                "file_updated_at": null,
                "id": 1298,
                "large_url": "http://farm9.staticflickr.com/8499/8331632744_8a0fc40fbb_b.jpg",
                "license": 2,
                "medium_url": "http://farm9.staticflickr.com/8499/8331632744_8a0fc40fbb.jpg",
                "metadata": null,
                "mobile": false,
                "native_page_url": "http://www.flickr.com/photos/ken-ichi/8331632744/",
                "native_photo_id": "8331632744",
                "native_realname": "Ken-ichi Ueda",
                "native_username": "Ken-ichi",
                "original_url": "http://farm9.staticflickr.com/8499/8331632744_f84c5a3f3c_o.jpg",
                "small_url": "http://farm9.staticflickr.com/8499/8331632744_8a0fc40fbb_m.jpg",
                "square_url": "http://farm9.staticflickr.com/8499/8331632744_8a0fc40fbb_s.jpg",
                "thumb_url": "http://farm9.staticflickr.com/8499/8331632744_8a0fc40fbb_t.jpg",
                "updated_at": "2013-01-15T17:10:01-05:00",
                "user_id": 1
              }
            }]
          }
        ]

GET /observations/:id

Retrieve information about an observation

Formats: json

PUT /observations/:id

Auth required

Update a single observation. Not that since most HTTP clients do not support PUT requests, you can fake it be specifying a _method param. This basically takes all the same params as POST /observations using the observation[] params. Here we're documenting some additional params for updating.

Params

_method
HTTP method to use if your client doesn't support PUT
put
ignore_photos
Ignore the absence of photo params. iNat assumes you are submitting data about existing photos with each request to update an observation, since that's how the HTML form works. If they're absent, iNat assumes the user wanted to remove those photos. Setting this param will override this behavior and leave any existing photos in place.
0 | 1
observation[observation_field_values_attributes][order]
Again, pretty much the same as POST /observations, but you can update existing ObservationFieldValues by including their IDs, and remove them using the _delete param.
ObservationFieldValue attributes. You could update an ObservationFieldValue with an ID of 1 with observation[observation_field_values_attributes][0][id]=1&observation[observation_field_values_attributes][0][value]=foo. You could delete the same with observation[observation_field_values_attributes][0][id]=1&observation[observation_field_values_attributes][0][_delete]=true

DELETE /observations/:id

Auth required

Delete an observation. Authenticated user must own the observation. No response body, just a 200 SUCCESS.

Formats: json

Example

Request
/observations/297867.json
Response

POST /observations/:id/quality/:metric

Auth required

Vote on quality metrics for an observation. These allow any user to vote on aspects of any observation's data quality.

Formats: json

Params

id
ID of observation being voted on.
Observation ID integer
metric
Aspect of data quality being voted on. Possible values are wild (whether or not observation is of a wild vs. captive / cultivated organism), location (whether or not coordinates seem accurate), date (whether or not date seem accurate).
wild | location | date
agree
Whether the user is voting yes or no on this metric, e.g. if the metric is wild and agree is false, the user is voting that the observation is not of a wild organism, i.e. it is captive or cultivated.
true | false

DELETE /observations/:id/quality/:metric

Auth required

Remove the user's vote on a quality metric. Not the same as voting no. Same id and metric params as POST /observations/:id/quality/:metric

Formats: json

PUT /observations/:id/viewed_updates

Mark updates associated with this observation (e.g. new comment notifications) as viewed. Response should be NO CONTENT.

Formats: json

GET /observations/:username

Mostly the same as /observations except filtered by a username.

Params

updated_since
Behaves the same as it does with GET /observations, with the addition of an extra HTTP header in the response. Since this is mainly used for syncing with 3rd party services and devices, this will also include an HTTP header called X-Deleted-Observations that contains a comma- separated list of observation IDs that have been deleted.
ISO 8601 datetime, e.g. 2013-10-09T13:40:13-07:00

GET /observations/project/:id

Just like /observations except filtered by a project. :id can be a project ID or slug. CSV response will return some extra project-specific daa.

Formats: atom, csv, json, kml, widget

GET /observations/taxon_stats

Retrieve some stats about taxa within a range of observations. species_counts are counts of observations identified to the species level or lower. total is the total number of taxa of all ranks. You must include the on, d1/d2, place_id, user_id, or projects params or this endpoint will just return blank results. This endpoint should accept all the params available for /observations.

Formats: json

Example

Request (try it)
/observations/taxon_stats.json?on=2008-03-19
Response
{
  total: 40,
  species_counts: [
    {
      count: "2",
      taxon: {
        id: 8649,
        name: "Calocitta formosa",
        rank: "species",
        rank_level: 10,
        default_name: {
          created_at: "2011-05-17T20:12:15-07:00",
          creator_id: null,
          id: 139851,
          is_valid: true,
          lexicon: "English",
          name: "White-throated Magpie-Jay",
          name_provider: null,
          source_id: null,
          source_identifier: null,
          source_url: null,
          taxon_id: 8649,
          updated_at: "2011-05-17T20:12:15-07:00",
          updater_id: null
        },
        image_url: "http://farm6.staticflickr.com/5179/5479426866_e0f6740520_s.jpg",
        iconic_taxon_name: "Aves",
        conservation_status_name: "least_concern"
      }
    }
  ],
  rank_counts: {
    superfamily: "1",
    genus: "1",
    species: "36",
    family: "2"
  }
}

GET /observations/user_stats

Retrieve some stats about users within a range of observations. You must include the on, d1/d2, place_id, user_id, or projects params or this endpoint will just return blank results. This endpoint should accept all the params available for /observations.

Formats: json

Example

Request (try it)
/observations/user_stats.json?on=2008-03-19
Response
{
  "total": 20,
  "most_observations": [{
    "count": "9",
    "user": {
      id: "1",
      count: "2",
      user: {
        id: 1,
        login: "kueda",
        name: "Ken-ichi Ueda",
        user_icon_url: "http://www.inaturalist.org/attachments/users/icons/1-thumb.jpg"
      }
    }
  }, ...],
  "most_species": [{
    "count": "9",
    "user": {
      id: "1",
      count: "2",
      user: {
        id: 1,
        login: "kueda",
        name: "Ken-ichi Ueda",
        user_icon_url: "http://www.inaturalist.org/attachments/users/icons/1-thumb.jpg"
      }
    }
  }, ...]
}

GET /observation_fields

List / search observation fields. ObservationFields are basically typed data fields that users can attach to observation.

Formats: json

Params

q
Search query
Any string
page
any integer

POST /observation_field_values

Auth required

Create a new observation field value. ObservationFields are basically typed data fields that users can attach to observation. ObservationFieldValues are the instaces of those fields. Note that you can also create these with nested params in POST /observations.

Formats: json

Params

observation_field_value[observation_id]
ID of the observation receiving this observation field value.
Valid iNat observation ID
observation_field_value[observation_field_id]
ID of the observation field for this observation field value.
Valid iNat observation field ID
observation_field_value[value]
Value for the observation field value.
Any string, but check the field's allowed values.

PUT /observation_field_values/:id

Auth required

Update an observation field value. Parameters are the same as POST /observation_field_values

Formats: json

DELETE /observation_field_values/:id

Auth required

Delete observation field value.

Formats: json

POST /observation_photos

Auth required

Add photos to observations. This is only for iNat-hosted photos. For adding photos hosted on other services, see POST /observations and PUT /observations/:id. This should be a multipart request.

Params

observation_photo[observation_id]
ID of the observation receiving this photo. This part of the multipart should appear as regular form data, not JSON, so Content-Disposition: form-data; and no Content-Type
Valid iNat observation ID
file
The photo data.
Multipart photo data

GET /places

Retrieve information about places.

Formats: json

Params

page
any integer
1
per_page
1 to 200
30
ancestor_id
Filter places by an ancestor place based on place hierarchy. If you wanted to view all places that are a part of California, you would set ancestor_id=14.
Place ID integer
place_type
Type of place to retrieve
Aggregate | Airport | Colloquial | Continent | Country | County | Drainage | Estate | Historical County | Historical State | Historical Town | Intersection | Island | Land Feature | Local Administrative Area | Miscellaneous | Nationality | Open Space | Point of Interest | Region | State | Street | Street | Street Segment | Supername | Town | Undefined | Zone
taxon
Retrieve places with this taxon on their check lists. Can be specified as an ID or a name, though vernacular names may yield unpredictable results. Note that this gets a bit weird for continents, since they don't have check lists: continents will not be returned *unless* place_type=continent.
Taxon ID or name
establishment_means
Filter taxon-specific place searches by how the taxon was established there, e.g. if it is native, introduced, invasive, etc. Note: searches for "native" will return places where the taxon is "native" or "endemic," and searches for "introduced" will return places where the taxon is "introduced," "naturalised," "invasive," or "managed."
native | endemic | introduced | naturalised | invasive | managed
latitude
Retrieve places that contain this lat/lon combination. This will only return places with boundaries defined.
Decimal latitude, e.g. 12.345
longitude
See latitude
Decimal longitude, e.g. 12.345

Example

Request (try it)
/places.json?taxon=Calochortus+tiburonensis&place_type=open+space
Response
[{
    "ancestry": "1/14/2319",
    "check_list_id": 6079,
    "code": null,
    "created_at": "2009-06-29T22:24:50-07:00",
    "display_name": "Ring Mountain Open Space Preserve, CA, US",
    "id": 3104,
    "latitude": "37.9130554199",
    "longitude": "-122.4938278198",
    "name": "Ring Mountain Open Space Preserve",
    "nelat": "37.92107",
    "nelng": "-122.48223",
    "parent_id": 2319,
    "place_type": 100,
    "source_identifier": "Ring Mountain Preserve",
    "source_name": "Ring Mountain Preserve",
    "swlat": "37.90504",
    "swlng": "-122.50542",
    "updated_at": "2012-09-26T03:14:01-07:00",
    "user_id": null,
    "woeid": null,
    "place_type_name": "Open Space"
  }]

Example

Request (try it)
/places.json?place_type=state&q=California
Response
[{
    "ancestry": "1",
    "check_list_id": 312,
    "code": "US-CA",
    "created_at": "2009-06-29T21:46:28-07:00",
    "display_name": "California, US",
    "id": 14,
    "latitude": "37.2691993713",
    "longitude": "-119.3069992065",
    "name": "California",
    "nelat": "42.008804",
    "nelng": "-114.131211",
    "parent_id": 1,
    "place_type": 8,
    "source_identifier": "3195",
    "source_name": "3195",
    "swlat": "32.528832",
    "swlng": "-124.480543",
    "updated_at": "2012-09-26T03:13:52-07:00",
    "user_id": null,
    "woeid": 2347563,
    "place_type_name": "State"
  }, {
    "ancestry": "6793",
    "check_list_id": 7754,
    "code": "MX-BCN",
    "created_at": "2009-10-24T18:01:56-07:00",
    "display_name": "Baja California, MX",
    "id": 7403,
    "latitude": "30.3589992523",
    "longitude": "-114.9445877075",
    "name": "Baja California",
    "nelat": "32.71804",
    "nelng": "-112.4939948948",
    "parent_id": 6793,
    "place_type": 8,
    "source_identifier": "1805",
    "source_name": "1805",
    "swlat": "27.835026736",
    "swlng": "-118.4187830224",
    "updated_at": "2012-09-26T03:14:35-07:00",
    "user_id": null,
    "woeid": 2346265,
    "place_type_name": "State"
  }, {
    "ancestry": "6793",
    "check_list_id": 9190,
    "code": "MX-BCS",
    "created_at": "2010-06-28T12:49:24-07:00",
    "display_name": "Baja California Sur, MX",
    "id": 8501,
    "latitude": "25.4334506989",
    "longitude": "-111.53881073",
    "name": "Baja California Sur",
    "nelat": "28.0027035634",
    "nelng": "-109.362976567",
    "parent_id": 6793,
    "place_type": 8,
    "source_identifier": "1806",
    "source_name": "1806",
    "swlat": "18.2910523956",
    "swlng": "-115.8180955045",
    "updated_at": "2012-09-26T03:14:37-07:00",
    "user_id": null,
    "woeid": 2346266,
    "place_type_name": "State"
  }]

GET /projects

Retrieve information about projects on iNaturalist.

Formats: json

Params

page
Results are returned in pages of 100 projects.
any integer
featured
Select only featured projects. Featured projects are chosen by site admins.
true
latitude
Search for observations within 5 degrees of a given point. Results are ordered by distance from that point. Geographic queries will only return projects that have an observation rule tied to a given place.
-90 to 90
longitude
See latitude.
-180 to 180
source
Find projects by source, usually a URI identifying an external resource from which the project was derived.

Example

Request (try it)
/projects.json?featured=true
Response
[{
    "created_at": "2011-08-12T10:21:28-07:00",
    "created_at_utc": "2011-08-12T17:21:28Z",
    "title": "ASC Pika Project",
    "project_type": "contest",
    "project_observation_rule_terms": "must be on list",
    "updated_at": "2012-04-26T19:38:51-07:00",
    "updated_at_utc": "2012-04-27T02:38:51Z",
    "source_url": "",
    "id": 44,
    "user_id": 477,
    "featured_at": "2012-04-26T19:38:51-07:00",
    "featured_at_utc": "2012-04-27T02:38:51Z",
    "icon_url": "http://www.inaturalist.org/attachments/projects/icons/44/span2/APAlogo.png?1315005828",
    "icon_file_size": 9454,
    "icon_file_name": "APAlogo.png",
    "icon_content_type": "image/png",
    "description": "The goal of this project is to document the persistence or extirpation of American Pika throughout their range for science and conservation. Read our flyer to find out more! According to the pika range map compiled by the IUCN, American pika are thought to occur in two occur in 2 Countries, 12 States (or Canadian Provinces) and 276 Counties (or Canadian Regional Districts). We seek to collect recent observations verifying Pika persistence in each of these places. This project is supported by the North American Pika Consortium, the California Department of Fish and Game, and the Front Range Pika Project.",
    "cached_slug": "asc-pika-project",
    "project_list": {
        "comprehensive": false,
        "place_id": null,
        "created_at": "2011-08-12T12:33:04-07:00",
        "created_at_utc": "2011-08-12T19:33:04Z",
        "title": "American Pika Atlas's Check List",
        "updated_at": "2011-08-12T12:33:04-07:00",
        "project_id": 44,
        "updated_at_utc": "2011-08-12T19:33:04Z",
        "taxon_id": null,
        "id": 52561,
        "user_id": null,
        "last_synced_at": null,
        "description": "Every species observed by members of American Pika Atlas",
        "source_id": null
    },
    "terms": "Please only upload observations if you agree to make them available non-commercial scientific analyses. We will attribute you as the photographer if your photos are used in any published scientific analyses. If possible please include locations, dates, and photos with your observations.",
    "observed_taxa_count": 2,
    "icon_updated_at": "2011-09-02T16:23:48-07:00",
    "rule_place": null,
    "project_observations_count": 12
}]

GET /projects/:id

Retrieve information about a single project. :id is the project ID or slug.

Formats: json

GET /projects/:id?iframe=true

This returns a complete web page without header or footer suitable for use in an IFRAME.

GET /projects/:id/contributors.widget

JS widget snippet of the top contributors to a project.

GET /projects/user/:login

Auth required

Lists projects the user specified by :login has joined. Actually it lists our ProjectUser records, which represent membership in a project.

Formats: json

Example

Request (try it)
http://www.inaturalist.org/projects/user/kueda.json
Response
[{
  "created_at": "2012-05-02T15:27:13-04:00",
  "id": 63,
  "observations_count": 0,
  "project_id": 1,
  "role": "curator",
  "taxa_count": 0,
  "updated_at": "2012-05-02T15:35:22-04:00",
  "user_id": 23,
  "user": {
    "login": "kueda"
  },
  "project": {
    "created_at": "2011-09-18T17:10:07-04:00",
    "delta": false,
    "description": "In which we observe things that may or may not be like white whales.",
    "featured_at": null,
    "icon_content_type": "image/jpeg",
    "icon_file_name": "spilosoma.jpg",
    "icon_file_size": 119605,
    "icon_updated_at": "2011-09-18T17:10:05-04:00",
    "id": 1,
    "latitude": null,
    "longitude": null,
    "map_type": "terrain",
    "observed_taxa_count": 8,
    "place_id": null,
    "project_type": "contest",
    "slug": "white-whales-et-al",
    "source_url": "",
    "terms": "You must be awesome.  The thing you've observed must be like unto a white whale.",
    "title": "White Whales et al.",
    "updated_at": "2012-05-07T21:31:15-04:00",
    "user_id": 1,
    "zoom_level": null,
    "icon_url": "http://www.inaturalist.org/attachments/projects/icons/1/span2/spilosoma.jpg?1316380205",
    "project_observation_rule_terms": "",
    "featured_at_utc": null,
    "rule_place": null,
    "cached_slug": "white-whales-et-al",
    "project_list": {
      "comprehensive": false,
      "created_at": "2011-09-18T17:10:07-04:00",
      "description": "Every species observed by members of White Whales et al.",
      "id": 99143,
      "last_synced_at": null,
      "place_id": null,
      "project_id": 1,
      "show_obs_photos": true,
      "source_id": null,
      "taxon_id": null,
      "title": "White Whales et al.'s Check List",
      "updated_at": "2011-09-18T17:10:07-04:00",
      "user_id": null
    },
    "project_observation_fields": []
  }
}]

GET /projects/:id/members

Auth required

Get the users who have joined this project.

Params

page
any integer
per_page
1 to 200

POST /projects/:id/join

Auth required

Adds the authenticated user as a member of the project

Formats: json

DELETE /projects/:id/leave

Auth required

Removes the authenticated user as a member of the project

Formats: json

POST /project_observations

Auth required

Add observations to projects

Formats: json

Params

project_observation[observation_id]
ID of the observation.
Valid iNat observation ID
project_observation[project_id]
ID of the project that will be receiving this contribution.
Valid iNat project ID

POST /users

Create a new iNaturalist user

Formats: json

Params

user[email]
Email address of the user.
Any valid email address.
user[login]
Username for this user.
Must be within 3 and 40 characters and must not begin with a number.
user[password]
User password
user[password_confirmation]
User password confirmation
user[description]
User description, just a brief blurb in which they describe themselves.
user[time_zone]
User time zone, will be used as the default time zone for observations that don't specify a time zone.
See POST /observations above for valid time zone values,

Example

Request
POST /users.json?user[login]=karina&user[email]=foo@bar.net&
  user[password]=******&user[password_confirmation]=******
Response
{
  "created_at": "2013-03-19T04:17:42Z",
  "description": null,
  "email": "foo@bar.net",
  "icon_content_type": null,
  "icon_file_name": null,
  "icon_file_size": null,
  "icon_updated_at": null,
  "icon_url": null,
  "id": 2,
  "identifications_count": 0,
  "journal_posts_count": 0,
  "life_list_id": 3,
  "life_list_taxa_count": 0,
  "login": "karina",
  "name": null,
  "observations_count": 0,
  "time_zone": null,
  "updated_at": "2013-03-19T04:17:42Z",
  "uri": "http://www.inaturalist.org/users/2"
}

PUT /users/:id

Auth required

Update a user. Takes the same parameters as POST /users and response should be the same. :id is the user ID.

Formats: json

Params

icon_delete
Delete the user icon
true

GET /users/edit

Auth required

Retrieve user profile info. Response should be like POST /users above.

Formats: json

GET /users/new_updates

Auth required

Get info about new updates for the authenticated user, e.g. comments and identifications on their content.

Formats: json

Params

resource_type
Filter by the type of resource that received the update, e.g. only show updates on your observations.
ListedTaxon | Observation | Post
notifier_type
Filter by the type of resource that created the update, e.g. only show comments.
Comment | Identification
notifier_types[]
Filter by multiple notifier types.
Comment | Identification
skip_view
Skip marking updates as viewed when retrieving them. The default behavior is to assume that if you're hitting this endpoint on behalf of the user, they will have viewed the updates returned.
true | false

Example

Request (try it)
GET /users/new_updates.json
Response
[
  {
    created_at: "2013-10-07T16:22:43-07:00",
    id: 954,
    notification: "activity",
    notifier_id: 610,
    notifier_type: "Comment",
    resource_id: 1,
    resource_owner_id: 1,
    resource_type: "Post",
    subscriber_id: 1,
    updated_at: "2013-10-07T16:22:43-07:00",
    viewed_at: "2013-10-07T16:22:49-07:00"
  },
  {
    created_at: "2013-09-12T13:39:21-07:00",
    id: 945,
    notification: "activity",
    notifier_id: 607,
    notifier_type: "Comment",
    resource_id: 199,
    resource_owner_id: 1,
    resource_type: "Observation",
    subscriber_id: 1,
    updated_at: "2013-09-12T13:39:21-07:00",
    viewed_at: "2013-10-07T16:21:09-07:00"
  }
]

Revised on 12 de diciembre de 2023 by kueda kueda