Web service API v1.0


The goal of this API is to facilitate access to speciesLink data by other applications.

Calls are made through HTTP GET method, passing optional parameters as part of the query string. Responses are in JSON format.

This service provides access to both provider metadata, such as collection name and type, as well as biodiversity records.

Access to the API is open to anyone, but requires an API key that has to be provided as an "apikey" parameter in every service call. Manage your API keys here. For clarity, the "apikey" parameter is omitted in the URLs displayed for all examples below.


Basic metadata, such as available languages, institution types, collection types and networks, can be accessed with the following URL:


metadata fields
language acronym, name
institution type id, name
collection type id, name and hierarchical attributes according to the modified preorder tree traversal method
network id, name

To get information only in a particular language use the "lang" parameter. Available languages can also be found in the response:


Listing all collections and institutions

To get all participant collections and institutions hierarchically:


Getting data about a single institution

To get data about a specific institution returning content in all available languages:

To get data about a specific institution returning content only in a specific language:

Getting data about a single collection

A similar approach can be used to get data about a specific collection:

Getting data about a single dataset

Each collection may provide multiple datasets to speciesLink. To get data about a specific dataset, use the dataset id:


Biodiversity records

Biodiversity records can be searched returning either individual records or clusters of records grouped by a specified criterion. In both cases, there is a common set of filters that can be used, but there are also more specific parameters that only apply on each case. Responses are in GeoJSON format: points for individual records, multipolygons for records grouped by geohash. By default, individual records are returned. The following base URL is shared in both cases:


Common filters

The following searchable fields can be used as part of the query string. Parameter names are case-insensitive.

→ Accepts multiple comma-separated values.

name description example
institutionCode institution acronym UNICAMP, Fiocruz
collectionCode collection acronym FIOCRUZ-CEIOC, UEC, HUEFS
collectionID collection id 1, 2, 3
catalogNumber 435643, empty, nonempty
basisOfRecord PreservedSpecimen, LivingSpecimen, FossilSpecimen, HumanObservation, MachineObservation, MaterialSample
kingdom Plantae, Animalia, Fungi
phylum Chordata, Mollusca
class Mammalia, Magnoliopsida
order Lepidoptera
family Bromeliaceae, Apidae
genus Passiflora, Bacillus, Boa, Hoplias
specificEpithet edulis, alata
scientificName Bothrops neuwiedii matogrossensis, Leishmania braziliensis
identifiedBy Abreu MC
yearIdentified four-digits year 1887, 1997, 2015
typeStatus holotypus, paratypus, neotypus
recordedBy collector name Kock, Almeida F
recordNumber collector number 125, 1897
yearCollected four-digits year 1987, 1897, 2016
country Brazil, Peru
stateProvince MS, GO, MT
county Altamira
locality Floresta da Tijuca
occurrenceRemarks General notes latossolo, cultivo, restinga
barcode NY00000001, FPS00257, FCM00096, UEC006758


Special filters

→ Accepts multiple comma-separated values.

name description example
bbox bounding box delimiting a rectangular area to filter records based on their coordinates, starting with the bottom left corner (1) in decimal degrees (datum WGS84) and ending with the top right corner (2), using dot as decimal separator and space as coordinate separator: longitude1 latitude1 longitude2 latitude2 -180.0+-90.0+180.0+90.0
landuse_1 comma-separated mapbiomas landuse categories, according to mapbiomas codes, in the record point at land_use_year_1 time. Mapbiomas codes 23,33
landuse_year_1 four-digit year to be considered for the landuse_1 condition (1985-2021) 1985
landuse_2 comma-separated mapbiomas landuse categories, according to mapbiomas codes, in the record point at land_use_year_2 time. Mapbiomas codes 15,9,21
landuse_year_2 four-digit year to be considered for the landuse_2 condition (1985-2021) 2021
phonetic perform phonetic search on taxonomy fields yes/no (default: no)
typus only typus records yes/no (no default)
scope collection type a (animals)
p (plants)
b (broad scope)
m (microorganisms)
f (fossils)
images with images yes/no (no default)
redlist redlist categories for Brazil CR (critically endangered)
PEX (Probably extinct)
EN (endangered)
EW (Extinct in nature)
EX (Extinct)
RE (Extinct in Brazil)
VU (Vulnerable)
coordinates Use 'yes' to get records with any kind of coordinates, 'no' for records without coordinates. More specific qualifiers can be used instead, such as 'original' (having original coordinates from the data provider), 'automatic' (having coordinates automatically suggested by speciesLink based on county), 'blocked' (coordinates not shared by the data provider), 'consistent' (coordinates that passed consistency checks) or 'suspect' (coordinates that didn't pass one or more consistency checks).
  • yes
    • original
      • suspect
      • consistent
    • automatic
  • no
    • absent
    • blocked
synonyms include synonyms according to the specified name authorities algaebase (AlgaeBase)
moure (Catálogo Moure)
dsmz (DSMZ)
flora2020 (Flora e Funga do Brasil)
mycobank (MycoBank)
sp2000 (Species 2000)


Two parameters can be used for pagination, and they are only available when handling individual records:

offset: Index of the first record to be returned, starting at zero.

limit: Number of records to be returned. Default: 200. Maximum: 5000.

Every page includes an attribute *numberReturned* that will always be less than or equals the *limit* being used. Additionally, the first page always includes the attribute *numberMatched* to indicate the total number of records matched by the query. If a client is only interested in the total number of matched records, it's possible to set limit = 0 in the request to avoid streaming results.


Fields to be returned

In the previous examples, you may have noticed that a standard set of fields is always returned for each individual record. The following parameter can be used to choose between different sets of fields to be returned according to the next table. This parameter only applies when returning individual records. For each record, some fields may not be returned if there is no data associated.

output: Specifies which set of fields should be returned. Default: "dwc".

field namedwcmodellingcoords

Grouping records

Records can be grouped by a specified criterion. Currently this is only available for geohash, allowing mapping applications to retrieve results grouped by larger pixels rather than fetching millions of individual records. When records are grouped by geohash, a set of square multipolygons is returned in GeoJSON, including the total number of records per geohash, so that heat maps can be generated.

groupby: Criterion by which records are grouped. Available options: geohash.

precision: Auxiliary parameter when records are grouped by geohash, specifying the geohash precision in kilometers. Default: 500km.

above: Auxiliary parameter when records are grouped by geohash, indicating that aggregation should only take place when the number of matching records is above the specified number. Otherwise, response will fall back to returning individual records. Use either a positive number or the keyword "max_limit" to indicate the maximum number of records that can be returned by the service through pagination. When specifying a number, it cannot exceed the maximum number of records returned by the service, otherwise it will be automatically adjusted. This parameter can be particularly useful for mapping applications that need to switch between displaying individual records or geohash aggregations, depending on the number of matching records, sparing clients from implementing an extra service call to get the number of matching records followed by additional logic to build the request and also avoiding to handle pagination.


Leaflet example

Since specieslink contains millions of records, displaying them on a map requires some special approach. The following example makes service calls using the "groupby" parameter associated with the "above" parameter, so that results are automatically aggregated if the number of matching records exceeds, in this case, 1k records. Every call always includes a bounding box filter, restricting search to the visible area. The map is also refreshed after each pan or zoom. A simple approximation is used to adjust geohash precision according to the map area.

    var mymap = L.map('map');

    // set map center with zoom level
    mymap.setView(new L.LatLng(-23.36, -46.84), 5);

    // add openstreetmap layer
    L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 19,
        attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'

    // function to fetch remote json data given an url
    function getJSON(url, param) {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", url, false);
        xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        eval("my_points_layer = " + xhttp.responseText);
        return my_points_layer
    var specieslink_layer = null;

    // function to build specieslink web service url
    function get_specieslink_url(){
        // estimate precision in km so that we get ~500 cells displayed on the map with aggregation
        var diagonal_in_km = mymap.distance(mymap.getBounds().getSouthWest(), mymap.getBounds().getNorthEast())/1000;
        var visible_area = (diagonal_in_km*diagonal_in_km)/2;
        var cell_area = visible_area/500;
        var precision = Math.round(Math.sqrt(cell_area));
        // only aggregate results when displaying more than 1k records
        return 'https://specieslink.net/ws/1.0/search?apikey=YOUR_API_KEY&groupby=geohash&precision='+precision+'&above=1000'

    function refresh_specieslink_data() {
        if (specieslink_layer !== null) {
        var url = get_specieslink_url();
        var geojson_data = getJSON(url);
        var style = {}
        // use different style when results are aggregated as MultiPolygons
        if (geojson_data.hasOwnProperty("features") &&
            geojson_data.features.length > 0 &&
            geojson_data.features[0].hasOwnProperty("geometry") &&
            geojson_data.features[0].geometry.type == "MultiPolygon") {
            style = { style: function (feature) {
                                 var num_points = feature.properties.num_points;
                                 // set color according to the number of aggregated points
                                 switch (true) {
                                     case num_points < 11  : return {color: "#D88A01"};
                                     case num_points < 51  : return {color: "#EA8015"};
                                     case num_points < 101 : return {color: "#EA5615"};
                                     case num_points < 501 : return {color: "#EA2C15"};
                                     default               : return {color: "#BC2110"};
        specieslink_layer = L.geoJson(geojson_data, style);

    // load data for the first time

    // refresh data after each pan or zoom
    mymap.on('moveend', refresh_specieslink_data);

Additional references

available collections

available institutions