NAV Navbar
Logo
http shell r ruby

Introduction

Welcome to the BIEN API! You can use our API to access BIEN data.

We have examples for Shell (using curl and jq), R, and Ruby! You can view code examples in the dark area to the right (or below if on mobile), and you can switch the programming language of the examples with the tabs in the top right.

Base URL

https://bienapi.club/

HTTP methods

This is a read only API. That is, we only allow GET (and HEAD) requests on this API.

Requests of all other types will be rejected with appropriate 405 code, including POST, PUT, COPY, HEAD, DELETE, etc.

Response Codes

400 responses will look something like

HTTP/1.1 400 Bad Request
Cache-Control: public, must-revalidate, max-age=60
Connection: close
Content-Length: 61
Content-Type: application/json
Date: Thu, 26 Feb 2015 23:27:57 GMT
Server: nginx/1.7.9
Status: 400 Bad Request
X-Content-Type-Options: nosniff

{
    "error": "invalid request",
    "message": "maximum limit is 5000"
}

401 responses will look something like

HTTP/1.1 401 Unauthorized
Access-Control-Allow-Methods: HEAD, GET
Access-Control-Allow-Origin: *
Cache-Control: public, must-revalidate, max-age=60
Content-Length: 26
Content-Type: application/json; charset=utf8
Date: Mon, 26 Jun 2017 16:53:22 GMT
Server: Caddy
X-Content-Type-Options: nosniff

{
    "error": "not authorized"
}

404 responses will look something like

HTTP/1.1 404 Not Found
Cache-Control: public, must-revalidate, max-age=60
Connection: close
Content-Length: 27
Content-Type: application/json
Date: Thu, 26 Feb 2015 23:27:16 GMT
Server: nginx/1.7.9
Status: 404 Not Found
X-Cascade: pass
X-Content-Type-Options: nosniff

{
    "error": "route not found"
}

405 responses will look something like (with an empty body)

HTTP/1.1 405 Method Not Allowed
Access-Control-Allow-Methods: HEAD, GET
Access-Control-Allow-Origin: *
Cache-Control: public, must-revalidate, max-age=60
Connection: close
Content-Length: 0
Content-Type: application/json; charset=utf8
Date: Mon, 27 Jul 2015 20:48:27 GMT
Server: nginx/1.9.3
Status: 405 Method Not Allowed
X-Content-Type-Options: nosniff

500 responses will look something like

HTTP/1.1 500 Internal Server Error
Cache-Control: public, must-revalidate, max-age=60
Connection: close
Content-Length: 24
Content-Type: application/json
Date: Thu, 26 Feb 2015 23:19:57 GMT
Server: nginx/1.7.9
Status: 500 Internal Server Error
X-Content-Type-Options: nosniff

{
    "error": "server error"
}

Response headers

Response headers give the following noteable things:

200 response header will look something like

Access-Control-Allow-Methods: HEAD, GET
Access-Control-Allow-Origin: *
Cache-Control: public, must-revalidate, max-age=60
Connection: close
Content-Length: 10379
Content-Type: application/json; charset=utf8
Date: Mon, 09 Mar 2015 23:01:23 GMT
Server: nginx/1.7.10
Status: 200 OK
X-Content-Type-Options: nosniff

Response bodies

Response bodies generally look like:

{
  "count": 5701,
  "returned": 1,
  "data": [
    {
      "symbol": "ABBA",
      "synonym_symbol": "",
      "scientific_name": "Abies balsamea (L.) Mill.",
      "common_name": "balsam fir",
      "federal_status": "",
      "state_status_codes": "CT (E)"
    }
  ],
  "error": null
}

Responses have 4 slots:

Responses with errors also have the same 4 slots, but no data returned, and there should be an informative error message.

Media Types

We serve up two types:

You can set a content type header in curl like -H "Content-Type: application/json" or -H "Content-Type: text/csv"

Pagination

The query parameters limit (default = 10) and offset (default = 0) can be used to toggle the number of results you get back and what record you start at. This doesn’t apply to some routes, which don’t accept any parameters (e.g., docs).

The response body from the server will include data on records found in count and number returned in returned:

Authentication

Some routes require authentication via an API key.

Email Scott scott@ropensci.org to request a key

The only routes that don’t require an API key are the root / and /heartbeat

Pass your API key in a header Authorization: Bearer, e.g., Authorization: Bearer <your api key>

Parameters

Common parameters

Above parameters common to all routes except:

Sometimes available

fields is available only on routes:

On other routes fields is not available because we are returning a given set of pre-defined fields.

Routes

Root

GET https://bienapi.club

has a html landing page - does not return JSON payload - check it out at https://bienapi.club

Heartbeat

Lists all the routes, and gives some indicaion of what can be passed to them.

curl "https://bienapi.club/heartbeat" |  jq .

The above command returns JSON structured like this:

{
  "routes": [
    "/heartbeat",
    "/list",
    "/list/country",
    "/plot/metadata",
    "/plot/protocols",
    "/traits/",
    "/traits/family",
    "/iucn?<params>",
    "/usda?<params>"
  ]
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(url = "https://bienapi.club")
res <- cli$get("heartbeat")
jsonlite::fromJSON(res$parse("UTF-8"))
$routes
 [1] "/heartbeat"           "/list"                "/list/country"
 [4] "/plot/metadata"       "/plot/protocols"      "/traits/"
 [7] "/traits/family"       "/phylogeny"           "/meta/version"
[10] "/meta/politicalnames" "/ranges/list"         "/ranges/species"
[13] "/ranges/genus"        "/stem/species"        "/iucn?<params>"
[16] "/usda?<params>"
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
res = conn.get 'heartbeat'
MultiJson.load(res.body)

The above command returns a Hash like:

=> {"routes"=>
  ["/heartbeat",
   "/list",
   "/list/country",
   "/plot/metadata",
   "/plot/protocols",
   "/traits/",
   "/traits/family",
   "/phylogeny",
   "/meta/version",
   "/meta/politicalnames",
   "/ranges/list",
   "/ranges/species",
   "/ranges/genus",
   "/stem/species",
   "/iucn?<params>",
   "/usda?<params>"]}

list

list all species

GET [/list{?limit}{?offset}]

Get species list

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/list" |  jq .
{
  "count": 220424,
  "returned": 10,
  "data": [
    {
      "species": "Aa achalensis"
    },
    {
      "species": "Aa argyrolepis"
    },
    {
      "species": "Aa calceata"
    },
    {
      "species": "Aa colombiana"
    },
    {
      "species": "Aa denticulata"
    },
    {
      "species": "Aa fiebrigii"
    },
    {
      "species": "Aa hartwegii"
    },
    {
      "species": "Aa hieronymi"
    },
    {
      "species": "Aa leucantha"
    },
    {
      "species": "Aa macra"
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("list")
jsonlite::fromJSON(res$parse("UTF-8"))
$count
[1] 220424

$returned
[1] 10

$data
          species
1   Aa achalensis
2  Aa argyrolepis
3     Aa calceata
4   Aa colombiana
5  Aa denticulata
6    Aa fiebrigii
7    Aa hartwegii
8    Aa hieronymi
9    Aa leucantha
10       Aa macra

$error
NULL
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'list'
dat = MultiJson.load(res.body)
dat['data'].collect{ |x| x['species']}
=> ["Aa achalensis",
 "Aa argyrolepis",
 "Aa calceata",
 "Aa colombiana",
 "Aa denticulata",
 "Aa fiebrigii",
 "Aa hartwegii",
 "Aa hieronymi",
 "Aa leucantha",
 "Aa macra"]

list by country

GET [/list/country{?limit}{?offset}]

Get species list for a specific country

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/list/country?country=Canada&limit=2" |  jq .
{
  "count": 1,
  "returned": 2,
  "data": [
    {
      "species_by_political_division_id": null,
      "scrubbed_species_binomial": "Abelia x",
      "country": "Canada"
    },
    {
      "species_by_political_division_id": null,
      "scrubbed_species_binomial": "Abeliophyllum distichum",
      "country": "Canada"
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("list/country", query = list(country = "Canada"))
jsonlite::fromJSON(res$parse("UTF-8"))$data$scrubbed_species_binomial
 [1] "Abelia x"                "Abeliophyllum distichum"
 [3] "Abelmoschus moschatus"   "Abies alba"
 [5] "Abies amabilis"          "Abies balsamea"
 [7] "Abies cephalonica"       "Abies chensiensis"
 [9] "Abies densa"             "Abies grandis"
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'list/country', {"country": "Canada"}
dat = MultiJson.load(res.body)
dat['data'].collect{ |x| x['scrubbed_species_binomial']}
=> ["Abelia x",
 "Abeliophyllum distichum",
 "Abelmoschus moschatus",
 "Abies alba",
 "Abies amabilis",
 "Abies balsamea",
 "Abies cephalonica",
 "Abies chensiensis",
 "Abies densa",
 "Abies grandis"]

usda

GET [/usda{?limit}{?offset}{?fields}]

USDA data

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/usda?limit=1" |  jq .
{
  "count": 5701,
  "returned": 1,
  "data": [
    {
      "symbol": "ABBA",
      "synonym_symbol": "",
      "scientific_name": "Abies balsamea (L.) Mill.",
      "common_name": "balsam fir",
      "federal_status": "",
      "state_status_codes": "CT (E)"
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("usda", query = list(limit = 3))
jsonlite::fromJSON(res$parse("UTF-8"))
$count
[1] 5701

$returned
[1] 3

$data
  symbol synonym_symbol                                    scientific_name
1   ABBA                                         Abies balsamea (L.) Mill.
2   ABCO                Abies concolor (Gord. & Glend.) Lindl. ex Hildebr.
3   ABFR                                       Abies fraseri (Pursh) Poir.
  common_name federal_status state_status_codes
1  balsam fir                            CT (E)
2   white fir                           NV (CY)
3  Fraser fir                            TN (T)

$error
NULL
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'usda', {"limit": 3}
MultiJson.load(res.body)
=> {"count"=>5701,
 "returned"=>3,
 "data"=>
  [{"symbol"=>"ABBA", "synonym_symbol"=>"", "scientific_name"=>"Abies balsamea (L.) Mill.", "common_name"=>"balsam fir", "federal_status"=>"", "state_status_codes"=>"CT (E)"},
   {"symbol"=>"ABCO", "synonym_symbol"=>"", "scientific_name"=>"Abies concolor (Gord. & Glend.) Lindl. ex Hildebr.", "common_name"=>"white fir", "federal_status"=>"", "state_status_codes"=>"NV (CY)"},
   {"symbol"=>"ABFR", "synonym_symbol"=>"", "scientific_name"=>"Abies fraseri (Pursh) Poir.", "common_name"=>"Fraser fir", "federal_status"=>"", "state_status_codes"=>"TN (T)"}],
 "error"=>nil}

iucn

GET [/iucn{?limit}{?offset}{?fields}]

IUCN data

plot

Get all plot metadata

GET [/plot/metadata{?limit}{?offset}{?fields}]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/plot/metadata" |  jq .
{
  "count": 113390,
  "returned": 10,
  "data": [
    {
      "datasource": "VegBank",
      "dataset": "Pawnee Grassland Classification",
      "dataowner": "Michael Schiebout",
      "primary_dataowner_email": null,
      "plot_name": "001-Schieb-92a",
      "country": "United States",
      "state_province": "Colorado",
      "county": null,
      "locality": null,
      "latitude": 40.7565333333333,
      "longitude": -104.464211111111,
      "coord_uncertainty_m": null,

...
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("plot/metadata")
jsonlite::fromJSON(res$parse("UTF-8"))
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'plot/metadata'
dat = MultiJson.load(res.body)

List available sampling protocols

GET [/plot/protocols{?limit}{?offset}]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/plot/protocols?limit=3" |  jq .
{
  "count": 1,
  "returned": 3,
  "data": [
    {
      "sampling_protocol": "",
      "plot_metadata_id": null
    },
    {
      "sampling_protocol": "0.1 ha  transect, stems >= 2.5 cm dbh",
      "plot_metadata_id": null
    },
    {
      "sampling_protocol": "1 ha tree plot, stems >= 10 cm dbh",
      "plot_metadata_id": null
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("plot/protocols")
jsonlite::fromJSON(res$parse("UTF-8"))$data$sampling_protocol
[1] NA
[2] "Point-intercept"
[3] "0.1 ha  transect, stems >= 2.5 cm dbh"
[4] "1 ha tree plot, stems >= 10 cm dbh"
[5] ""
[6] "TEAM Forest Inventory Sampling Protocol"
[7] "Center for Tropical Forest Science Forest Inventory  Protocol"
[8] "Carolina Vegetation Survey Standard Sampling Method"
[9] "US Forest Inventory and Analysis Sampling Protocol"
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'plot/protocols'
dat = MultiJson.load(res.body)
dat['data'].collect{ |x| x['sampling_protocol']}
=> [nil,
 "Point-intercept",
 "0.1 ha  transect, stems >= 2.5 cm dbh",
 "1 ha tree plot, stems >= 10 cm dbh",
 "",
 "TEAM Forest Inventory Sampling Protocol",
 "Center for Tropical Forest Science Forest Inventory  Protocol",
 "Carolina Vegetation Survey Standard Sampling Method",
 "US Forest Inventory and Analysis Sampling Protocol"]

traits

Get all traits

GET [/traits{?limit}{?offset}{?fields}]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/traits?limit=2" |  jq .
{
  "count": 1,
  "returned": 2,
  "data": [
    {
      "trait_name": "diameter at breast height (1.3 m)"
    },
    {
      "trait_name": "flower pollination syndrome"
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("traits", query = list(limit = 2))
jsonlite::fromJSON(res$parse("UTF-8"))
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'traits'
dat = MultiJson.load(res.body)

Traits by family

GET [/traits/family{?limit}{?offset}]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/traits/family?family=Poaceae" |  jq .
{
  "count": 48309,
  "returned": 10,
  "data": [
    {
      "id": 110789,
      "scrubbed_family": "Poaceae",
      "scrubbed_genus": "Achnatherum",
      "scrubbed_species_binomial": "Achnatherum breviaristatum",
      "trait_name": "whole plant growth form",
      "trait_value": "Herb",
      "unit": null,
      "method": "Species with multiple growth form classifications were assigned the growth form classification agreed upon by the majority (>2/3) of sources. Species with ambiguous or otherwise not interpretable growth form assignments were excluded from the final dataset but are made available with the original data.",
      "latitude": null,
      "longitude": null,
...
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("traits/family", query = list(family = "Poaceae"))
jsonlite::fromJSON(res$parse("UTF-8"))
$count
[1] 48309

$returned
[1] 10

$data
       id scrubbed_family scrubbed_genus  scrubbed_species_binomial
1  110789         Poaceae    Achnatherum Achnatherum breviaristatum
2  178202         Poaceae    Achnatherum Achnatherum breviaristatum
3  745668         Poaceae    Achnatherum       Achnatherum lemmonii
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'traits/family', { :family => "Poaceae"}
MultiJson.load(res.body)
=> {"count"=>48309,
 "returned"=>10,
 "data"=>
  [{"id"=>110789,
    "scrubbed_family"=>"Poaceae",
    "scrubbed_genus"=>"Achnatherum",
    "scrubbed_species_binomial"=>"Achnatherum breviaristatum",
    "trait_name"=>"whole plant growth form",
    "trait_value"=>"Herb",
    "unit"=>nil,
    "method"=>
    ...

meta

Get current BIEN database version and release date

GET [/meta/version]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/meta/version" |  jq .
{
  "data": [
    {
      "bien_metadata_id": null,
      "db_version": "3.4.5",
      "db_release_date": "2017-05-18"
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("meta/version")
jsonlite::fromJSON(res$parse("UTF-8"))
$data
  bien_metadata_id db_version db_release_date
1               NA      3.4.5      2017-05-18

$error
NULL
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'meta/version'
MultiJson.load(res.body)
=> {"data"=>[{"bien_metadata_id"=>nil, "db_version"=>"3.4.5", "db_release_date"=>"2017-05-18"}], "error"=>nil}

Get political divisions and associated geonames codes

GET [/meta/politicalnames{?limit}{?offset}]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/meta/politicalnames?limit=1" |  jq .
{
  "count": 35211,
  "returned": 1,
  "data": [
    {
      "geonameid": null,
      "country": "Aland Islands",
      "state_province": null,
      "state_province_ascii": null,
      "county_parish": "Landskapet Åland",
      "county_parish_ascii": "Landskapet Aland",
      "country.code": "AX",
      "state.code": "01",
      "county.code": "830602"
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("meta/politicalnames", query = list(limit = 3))
jsonlite::fromJSON(res$parse("UTF-8"))
$count
[1] 35211

$returned
[1] 3

$data
  geonameid       country state_province state_province_ascii    county_parish
1        NA Aland Islands             NA                   NA Landskapet Åland
2        NA    Azerbaijan             NA                   NA  Mirbǝşir Rayonu
3        NA    Azerbaijan             NA                   NA   Shaumyan Rayon
  county_parish_ascii country.code state.code county.code
1    Landskapet Aland           AX         01      830602
2     Mirbasir Rayonu           AZ         00      585509
3      Shaumyan Rayon           AZ         00      585038

$error
NULL
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'meta/politicalnames', { :limit => 2}
MultiJson.load(res.body)
=> {"count"=>35211,
 "returned"=>2,
 "data"=>
  [{"geonameid"=>nil,
    "country"=>"Aland Islands",
    "state_province"=>nil,
    "state_province_ascii"=>nil,
    "county_parish"=>"Landskapet Åland",
    "county_parish_ascii"=>"Landskapet Aland",
    "country.code"=>"AX",
    "state.code"=>"01",
    "county.code"=>"830602"},
   {"geonameid"=>nil,
    "country"=>"Azerbaijan",
    "state_province"=>nil,
    "state_province_ascii"=>nil,
    "county_parish"=>"Mirbǝşir Rayonu",
    "county_parish_ascii"=>"Mirbasir Rayonu",
    "country.code"=>"AZ",
    "state.code"=>"00",
    "county.code"=>"585509"}],
 "error"=>nil}

ranges

List available range maps

GET [/ranges/list]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/ranges/list?limit=3" |  jq .
{
  "count": 98829,
  "returned": 3,
  "data": [
    {
      "species": "Aa_argyrolepis",
      "gid": 1
    },
    {
      "species": "Aa_colombiana",
      "gid": 2
    },
    {
      "species": "Aa_denticulata",
      "gid": 3
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("ranges/list", query = list(limit = 3))
jsonlite::fromJSON(res$parse("UTF-8"))
$count
[1] 98829

$returned
[1] 3

$data
         species gid
1 Aa_argyrolepis   1
2  Aa_colombiana   2
3 Aa_denticulata   3

$error
NULL
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'ranges/list', { :limit => 3}
MultiJson.load(res.body)
=> {"count"=>98829,
 "returned"=>3,
 "data"=>[{"species"=>"Aa_argyrolepis", "gid"=>1}, {"species"=>"Aa_colombiana", "gid"=>2}, {"species"=>"Aa_denticulata", "gid"=>3}],
 "error"=>nil}

Get range maps for a species

GET [/ranges/species]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/ranges/species?species=Abies%20lasiocarpa" |  jq .
{
  "count": 1,
  "returned": 1,
  "data": [
    {
      "species": "Abies_lasiocarpa",
      "gid": 90,
      "st_astext": "MULTIPOLYGON(((-107.75178470368 28.3154733778057,-107.547252123305 28.3434017070036,-107.505343314215 28.1691476302491,-107.60747528854 28.15526534
      ...
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("ranges/species", query = list(species = "Abies lasiocarpa"))
jsonlite::fromJSON(res$parse("UTF-8"))
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'ranges/species', { :species => 'Abies lasiocarpa'}
MultiJson.load(res.body)

Get range maps for a genus

GET [/ranges/genus]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/ranges/genus?genus=Abies" |  jq .
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("ranges/genus", query = list(genus = "Abies"))
jsonlite::fromJSON(res$parse("UTF-8"))
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'ranges/genus', { :genus => 'Abies'}
MultiJson.load(res.body)

stem

Get stem data for a species

GET [/stem/species]

curl -H "Authorization: Bearer <api key>" "https://bienapi.club/stem/species?species=Lysimachia%20quadrifolia&limit=1" |  jq .
{
  "count": 1207,
  "returned": 1,
  "data": [
    {
      "datasource_id": 48,
      "datasource": "CVS",
      "dataset": "Carolina Vegetation Survey",
      "dataowner": "Robert Peet",
      "taxonobservation_id": 56914049,
      "latitude": 35.365642578,
      "longitude": -82.853980026,
      "custodial_institution_codes": null,
      "collection_code": null,
      "date_collected": "1993-09-10",
      "scrubbed_species_binomial": "Lysimachia quadrifolia",
      "relative_x_m": null,
      "relative_y_m": null,
      "stem_code": null,
      "stem_dbh_cm": null,
      "stem_height_m": null,
      "analytical_stem_id": null
    }
  ],
  "error": null
}
library("crul")
library("jsonlite")

cli <- crul::HttpClient$new(
  url = "https://bienapi.club",
  headers = list(Authorization = "Bearer <api key>")
)
res <- cli$get("stem/species", query = list(species = "Lysimachia quadrifolia", limit=1))
jsonlite::fromJSON(res$parse("UTF-8"))
$count
[1] 1207

$returned
[1] 1

$data
  datasource_id datasource                    dataset   dataowner
1            48        CVS Carolina Vegetation Survey Robert Peet
  taxonobservation_id latitude longitude custodial_institution_codes
1            56914049 35.36564 -82.85398                          NA
  collection_code date_collected scrubbed_species_binomial relative_x_m
1              NA     1993-09-10    Lysimachia quadrifolia           NA
  relative_y_m stem_code stem_dbh_cm stem_height_m analytical_stem_id
1           NA        NA          NA            NA                 NA

$error
NULL
require 'faraday'
require 'multi_json'

conn = Faraday.new(url: 'https://bienapi.club')
conn.headers['Authorization'] = 'Bearer <api key>'
res = conn.get 'stem/species', { :species = "Lysimachia quadrifolia", :limit => 1}
MultiJson.load(res.body)
=> {"count"=>1207,
 "returned"=>1,
 "data"=>
  [{"datasource_id"=>48,
    "datasource"=>"CVS",
    "dataset"=>"Carolina Vegetation Survey",
    "dataowner"=>"Robert Peet",
    "taxonobservation_id"=>56914049,
    "latitude"=>35.365642578,
    "longitude"=>-82.853980026,
    "custodial_institution_codes"=>nil,
    "collection_code"=>nil,
    "date_collected"=>"1993-09-10",
    "scrubbed_species_binomial"=>"Lysimachia quadrifolia",
    "relative_x_m"=>nil,
    "relative_y_m"=>nil,
    "stem_code"=>nil,
    "stem_dbh_cm"=>nil,
    "stem_height_m"=>nil,
    "analytical_stem_id"=>nil}],
 "error"=>nil}

API Clients

R - RBIEN