For Developers

Search

Search for people is exposed as JSON-LD documents with Cross-Origin Resource Sharing (CORS) using elements from https://schema.org as type DataFeed, OpenSearch, and W3C ActivityStreams.

Base URL
https://api.bionomia.net/users/search
?q=
single human name (required)
&families_collected=
comma-separated list of taxonomic families collected (optional)
&families_identified=
comma-separated list of taxonomic families identified (optional)
&date=
a date expressed as YYYY-MM-DD, YYYY-MM, or YYYY (optional)
&page=
page number; there is a fixed 30 items per page (optional)
&strict=
boolean for MUST (=true) vs SHOULD (=false) on families_identified, families_collected, and date when any are present (optional)
&callback=
A string to produce a JSONP response instead of a JSON-LD response (optional)
Example
https://api.bionomia.net/users/search?q=smith&families_collected=scarabaeidae&strict=true
Response
{
  "@context": {
    "@vocab": "http://schema.org",
    "opensearch": "http://a9.com/-/spec/opensearch/1.1/",
    "as": "https://www.w3.org/ns/activitystreams#"
  },
  "@type": "DataFeed",
  "opensearch:totalResults": 1,
  "opensearch:itemsPerPage": 1,
  "as:first": "https://api.bionomia.net/users/search?q=smith&families_collected=curculionidae&strict=true&page=1",
  "as:prev": null,
  "as:current": "https://api.bionomia.net/users/search?q=smith&families_collected=curculionidae&strict=true",
  "as:next": null,
  "as:last": "https://api.bionomia.net/users/search?q=smith&families_collected=curculionidae&strict=true&page=1",
  "name": "Bionomia user search results",
  "description": "Bionomia user search results expressed as a schema.org JSON-LD DataFeed.
    q={name} is a search by human name;
    families_identified={families_identified} is a comma-separated list of taxonomic families identified;
    families_collected={families_collected} is a comma-separated list of taxonomic families collected;
    date={date} is a date in the form YYYY, YYYY-MM, or YYYY-MM-DD and is compared to birth and death dates;
    page={page} is the page number and there is a fixed 30 items per page;
    strict={true|false} is a boolean for MUST vs SHOULD on families_identified, families_collected, and date",
  "license": "https://creativecommons.org/publicdomain/zero/1.0/",
  "potentialAction": {
    "@type": "SearchAction",
    "target": "https://api.bionomia.net/users/search?q={name}&families_identified={families_identified}&families_collected={families_collected}&date={date}&page={page}&strict={true|false}"
  },
  "dataFeedElement": [
    {
      "@type": "DataFeedItem",
      "item": {
        "@type": "Person",
        "@id": "https://bionomia.net/0000-0002-8059-5133",
        "name": "Andrew B.T. Smith",
        "givenName": "Andrew B.T.",
        "familyName": "Smith",
        "alternateName": [
          "Smith, Andrew B.T."
        ],
        "knowsAbout": [
          {
            "@type": "ItemList",
            "name": "families_identified",
            "itemListElement": [
              {
                "@type": "ListItem",
                "name": "Carabidae"
              }
            ]
          },
          {
            "@type": "ItemList",
            "name": "families_collected",
            "itemListElement": [
              {
                "@type": "ListItem",
                "name": "Scarabaeidae"
              },
              {
                "@type": "ListItem",
                "name": "Curculionidae"
              },
              ...
            ]
          }
        ],
        "sameAs": "https://orcid.org/0000-0002-8059-5133"
      }
    }
  ]
}

Autocomplete Widget

Using jQuery, typeahead.js, handlebars.js, and Bootstrap.

Autocomplete Widget

Stylesheets

/* Bootstrap from a CDN */
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

/* Customizations */
<style>
  .twitter-typeahead { line-height:1em; }
  .typeahead, .tt-query, .tt-hint {
    width: 100%;
    height: 1rem;
    padding: 1rem;
    font-size: 1rem;
    line-height: 1rem;
    border: 2px solid #ccc;
    border-radius: 8px;
    outline: none;
  }
.typeahead { background-color: #fff; width:300px; }
.typeahead:focus { border: 2px solid #40924F; }
.tt-query { box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); }
.tt-hint { color: #999; }
.tt-menu {
  width: 100%;
  margin: 5px 0;
  padding: 8px 0;
  background-color: #fff;
  border: 1px solid rgba(0, 0, 0, 0.2);
  border-radius: 8px;
  box-shadow: 0 5px 10px rgba(0,0,0,.2);
  z-index:10000 !important;
}
.tt-suggestion, .tt-no-result {
  padding: 3px 10px;
  font-size: 1rem;
  line-height: 1.1rem;
  color:#495057;
}
.tt-suggestion:hover {
  cursor: pointer;
  color: #fff;
  background-color: #40924F;
}
.tt-suggestion.tt-cursor { color: #fff; background-color: #40924F; }
.tt-suggestion p { margin: 0; }
.tt-menu-header {
  margin: 0 10px 5px 10px;
  padding: 3px 0;
  border-bottom: 1px solid #a8a7a5;
  font-size:1em;
}
.dropdown-menu{
  border-radius:0px !important;
  font-size:1rem !important;
}
</style>

Javascript

// jQuery, typeahead.js and handlebars.js from a CDN
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.6/handlebars.min.js"></script>

<script>
  $(function() {

    var collectors = new Bloodhound({
      datumTokenizer: Bloodhound.tokenizers.whitespace,
      queryTokenizer: Bloodhound.tokenizers.whitespace,
      sufficient: 10,
      remote: {
        url: 'https://api.bionomia.net/user.json?q=%QUERY',
        wildcard: '%QUERY',
        transform : function(r) {
          return $.map(r, function (v) { v.type = "user"; return v; });
        }
      }
    });

    $('#collector-search .typeahead').typeahead({
        minLength: 3,
        highlight: true
      },
      {
        name: 'user',
        limit: 10,
        source: collectors,
        display: 'fullname_reverse',
        templates: {
          suggestion: Handlebars.compile($("#result-template").html()),
          empty: Handlebars.compile($("#empty-template").html())
        }
      }
    ).on("typeahead:select", function(obj, datum) {
      var identifier = datum.orcid || datum.wikidata;
      console.log(identifier);
      // DO SOMETHING WITH THE IDENTIFIER WHEN THE ITEM IS SELECTED
      /*
         The identifier will appear either in the form
         0000-0002-4286-147X or Q10293705.
         Recommended best practice is to show the user the identifier they
         chose by rendering an active link to either
         https://orcid.org/{{identifier}} or https://www.wikidata.org/wiki/{{identifier}}
       */
    });
  });
</script>

HTML

<div id="collector-search" class="m-2">
  <input class="typeahead" type="text" placeholder="Mary Anning" size="50">
</div>

<!-- Result template -->
<script id='result-template' type='text/x-handlebars-template'>
  <div class='d-flex'>
    <div>
      <img class='rounded' src='{{thumbnail}}'>
    </div>
    <div class='ml-2 flex-grow-1 small'>
      <h5 class='m-0 p-0'>{{fullname_reverse}}</h5>
      <div class='m-0 p-0 small muted'>{{{lifespan}}}</div>
      <div class='m-0 p-0 small muted'>{{{description}}}</div>
    </div>
  </div>
</script>

<!-- Non-result template -->
<script id='empty-template' type='text/x-handlebars-template'>
  <div class='m-2 tt-no-result'>Your search turned up 0 results.</div>
</script>