Read-only JSON API
Specify metadata
Browse collection-specific tables, fields, relationships, and tree ranks from the museum’s current Specify schema snapshot. All examples use the public API mounted at /metadata.
/metadataNo authentication is required. Only GET and HEAD are supported.curl -s "/metadata/collections?limit=25"Reference
Endpoints
/healthCache status, rebuild time, and collection count.
/collectionsList every accessible collection.
/collections/{collection}Get one collection by ID, code, name, or alias.
/collections/{collection}/tablesList the collection’s Specify tables.
/collections/{collection}/tables/{table}Get a table and its normalized metadata.
/collections/{collection}/tables/{table}/fieldsList fields on a table.
/collections/{collection}/tables/{table}/fields/{field}Get one field.
/collections/{collection}/tables/{table}/relationshipsList relationships on a table.
/collections/{collection}/tables/{table}/relationships/{relationship}Get one relationship.
/collections/{collection}/treesList the collection’s taxon and geography trees.
/collections/{collection}/trees/{tree}/ranksList the ranks in a tree.
/collections/{collection}/search?q={query}Search tables, fields, relationships, and ranks.
/collections/{collection}/resolve?string_id={value}Normalize a Specify query-field ID or dotted path.
Discovery
Collections
Start with GET /collections. A collection reference in later routes may be its numeric ID, code, full name, or an unambiguous normalized alias. Matching is case-insensitive; URL-encode names containing spaces.
GET /metadata/collections/4
GET /metadata/collections/vascular
GET /metadata/collections/Vascular%20PlantsList response
{
"items": [
{
"id": 4,
"code": "UBC",
"name": "Vascular Plants",
"tables": "/collections/4/tables",
"trees": "/collections/4/trees",
"search": "/collections/4/search",
"raw": { "…": "original Specify collection metadata" }
}
],
"total": 1,
"limit": 25,
"offset": 0
}Resources
Tables, fields, relationships, and ranks
List endpoints return a standard paginated envelope. Detail endpoints return one resource directly. Names are technical Specify identifiers; labels and descriptions come from English schema localization. The raw property preserves the source metadata for clients that need details beyond the normalized fields.
Field
{
"name": "catalogNumber",
"label": "Catalog Number",
"description": "The collection-assigned identifier",
"type": "text",
"required": true,
"path": "/collections/4/tables/CollectionObject/fields/catalogNumber",
"raw": {
"model": { "…": "Specify data-model metadata" },
"localization": { "…": "English schema localization" }
}
}Relationship
A relationship target is marked resolved: false and has a null path when the target model is not included in the published collection schema.
{
"name": "taxon",
"label": "Current Taxon",
"description": "Accepted taxon",
"type": "many-to-one",
"target": {
"name": "Taxon",
"resolved": true,
"path": "/collections/4/tables/Taxon"
},
"path": "/collections/4/tables/CollectionObject/relationships/taxon",
"raw": { "model": { "…": "…" }, "localization": { "…": "…" } }
}Trees and ranks
/trees returns tree names and links to their ranks. Each rank includes name, label,description, rank_id, and raw.
Full-text lookup
Search
Supply a non-empty q. Search is collection-scoped and prefix-matches every word across technical names, localized labels, and descriptions. Results are ordered by resource kind: tables, fields, relationships, then ranks.
GET /metadata/collections/4/search?q=global%20unique
GET /metadata/vascular/search?q=taxonomic%20fam&limit=20{
"items": [
{
"resource": "field",
"name": "catalogNumber",
"label": "Catalog Number",
"description": "The collection-assigned identifier",
"table": "CollectionObject",
"tree": null,
"type": "text",
"required": true,
"target": null,
"path": "/collections/4/tables/CollectionObject/fields/catalogNumber"
}
],
"total": 1,
"limit": null,
"offset": 0
}Query builder interoperability
Resolve query fields
The resolver converts either a Specify query-field string ID or a dotted technical/localized path into canonical components. Usestring_id on canonical routes; concise routes also accept stringid.
GET /metadata/collections/4/resolve?string_id=1%2C2-taxon.Taxon.fullName
GET /metadata/collections/4/resolve?string_id=CollectionObject.taxon.fullName{
"string_id": "1,2-taxon.Taxon.fullName",
"components": [
{ "resource": "table", "name": "CollectionObject" },
{ "resource": "relationship", "name": "taxon" },
{ "resource": "field", "name": "fullName" }
],
"path": "CollectionObject.taxon.fullName"
}Compound tree-rank fields are returned as table, relationship, rank, and field components. Ambiguous localized names return HTTP 409.
Convenience syntax
Concise routes and traversal
Short routes omit /collections and the explicit resource segments. After a table, each intermediate name is traversed as a relationship. The terminal name resolves to either a field or target table.
/vascular/vascular/taxon/vascular/taxon/fullName/vascular/collectionobject/taxon/fullNameTraversed responses add traversal andresolved_path. If a terminal name is both a field and a relationship, the API returns 409; use the canonical/fields/ or /relationships/ route to make the intent explicit.
List controls
Pagination
All list and search endpoints accept limit (1–1000) and a nonnegative offset. Without a limit, all matching items from the offset are returned and limit is null.total always describes the full result set.
GET /metadata/collections/4/tables?limit=50&offset=100Failure handling
Errors
{
"error": {
"code": "not_found",
"message": "Unknown collection: missing",
"details": {}
}
}400invalid_query — missing or malformed parameters404not_found — unknown resource405method_not_allowed — API resources are read-only409ambiguous_reference — an alias or terminal name has multiple matches502metadata_unavailable — the frontend cannot reach the service503metadata_unavailable — the metadata cache is invalid or unavailableOperational notes
HTTP and cache behavior
- Responses use
application/json; charset=utf-8. - GET and HEAD are available through the public frontend gateway.
- Schema responses are normally cached for 5 minutes and may be served stale while revalidating for 1 hour.
/healthis never cached and reports the snapshot rebuild time, format revision, collection count, and excluded collections.- Resource links in responses are root-relative API paths; prefix them with
/metadatawhen calling through this site. - The API exposes schema metadata only. It does not provide specimen records, Darwin Core mappings, or publication configuration.