Brown Digital Repository (BDR) API

The Brown University Library's public, keyless REST API over the Brown Digital Repository — an item API, a collection API, a Solr-backed search API, and a two-key link index at /api/. Live and unauthenticated on 2026-08-30 against an index of 1,147,400 public objects. Brown documents it itself, in prose, in the wiki of its own Brown-University-Library/bdr_api_documentation GitHub repository; there is no Brown-published OpenAPI, so the contract in this repo is derived and marked as such. Notable behaviours, all probed: rows is silently clamped to 500, malformed queries return 200 rather than the documented 400, unknown PIDs return a nine-byte text/html "Not Found" rather than the documented 403, no CORS headers are sent (JSONP via a callback parameter is the documented cross-origin path), and Cloudflare bot protection added in Spring 2025 fronts the host.

Operations 5

GET /api/ API root link index #
GET /api/search/ Search public BDR objects #
GET /api/items/{pid}/ Get one repository object #
GET /api/collections/ List top-level collections #
GET /api/collections/{collection_id}/ Get one collection, its sub-collections and its items #

Documentation

Specifications

Schemas & Data

Other Resources

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/bdr-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

brown-bdr-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Brown Digital Repository (BDR) API
  version: '2026-08-30'
  summary: Public, keyless read API over the Brown University Library's digital repository.
  description: |-
    The Brown Digital Repository (BDR) is the Brown University Library's platform for gathering,
    indexing, storing, preserving and making available digital assets produced by scholarly,
    instructional, research and administrative activity at Brown. It exposes three public,
    unauthenticated read endpoints — an item API, a collection API and a Solr-backed search API —
    plus a two-key root link index at `/api/`.

    This document was DERIVED. Brown does not publish an OpenAPI, AsyncAPI or any other machine-
    readable contract for the BDR. It publishes prose documentation, which it authors itself, in the
    wiki of its own `Brown-University-Library/bdr_api_documentation` GitHub repository and on the
    `/studio/api-docs/` page of the repository application. Every path, parameter, status code and
    schema below was reconciled between that first-party prose and live probes run on 2026-08-30;
    where the two disagree, the OBSERVED behaviour is documented and the divergence is called out in
    the operation description and in `errors/brown-bdr-errors.yml`. Nothing here is asserted that was
    not either published by Brown or observed on the wire.

    Operator: institution. `repository.library.brown.edu` is under Brown's own registrable domain;
    the application is Brown University Library software (its indexer, XML layer, uploader hub and
    API tooling are public repositories in the Brown-University-Library GitHub organization), and
    DataCite registers the repository as client BROWN.BDR, "Brown Digital Repository", with
    14,089 DOIs minted under prefix 10.26300. Cloudflare fronts the host as a CDN and bot-protection
    layer; that is delivery, not operation.
  contact:
    name: Brown University Library
    url: https://library.brown.edu
  termsOfService: https://policy.brown.edu/policy/privacy
  license:
    name: Rights vary per repository object; see each object's MODS metadata
    url: https://repository.library.brown.edu/studio/
  x-operator: institution
  x-operator-basis: >-
    Host is under brown.edu, Brown's own registrable domain. The repository application is authored
    and maintained by the Brown University Library (public source in
    https://github.com/Brown-University-Library — bdr_indexer, bdrxml, bdr_uploader_hub_project,
    bdr-api-tools), the API documentation is written by Brown Library staff in Brown's own GitHub
    wiki, and DataCite lists the repository as Brown's registered client BROWN.BDR. No vendor
    platform identity appears in servers[], info.title or info.contact.
  x-provenance:
    generated: '2026-08-30'
    method: derived
    source:
    - https://github.com/Brown-University-Library/bdr_api_documentation/wiki
    - https://repository.library.brown.edu/api/
    - https://repository.library.brown.edu/api/search/?q=primary_title:irish&rows=2&fl=pid,primary_title,abstract
    - https://repository.library.brown.edu/api/items/bdr:80246/
    - https://repository.library.brown.edu/api/collections/
    - https://api.datacite.org/clients/brown.bdr
    note: >-
      Derived from Brown's own prose documentation plus live probing on 2026-08-30. Not published by
      Brown as a specification. Do not present this document as a Brown-authored contract.
servers:
- url: https://repository.library.brown.edu
  description: Brown Digital Repository production
tags:
- name: Search
  description: Solr-backed search across public BDR objects.
- name: Items
  description: Metadata for a single repository object, addressed by PID.
- name: Collections
  description: Repository collections and their membership.
- name: Discovery
  description: The API root link index.
paths:
  /api/:
    get:
      tags: [Discovery]
      operationId: getApiRoot
      summary: API root link index
      description: >-
        Returns a two-key object linking to the collection API and to the human documentation page.
        It is a link index, not a service description; the BDR publishes no machine-readable
        contract of its own.
      responses:
        '200':
          description: Link index
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiRoot'
              example:
                collections: https://repository.library.brown.edu/api/collections/
                api docs: https://repository.library.brown.edu/studio/api-docs/
        '500':
          description: Internal server error, per Brown's documented global exception behaviour.
  /api/search/:
    get:
      tags: [Search]
      operationId: searchRepository
      summary: Search public BDR objects
      description: |-
        Solr query interface over the public repository index (1,147,400 objects at probe time on
        2026-08-30). Brown documents that queries follow standard Solr syntax, that a badly formatted
        query returns 400, and that a successful search returns 200 even with zero results.

        OBSERVED DIVERGENCE: malformed queries did not return 400 on any probe. `q=[`, `q=((` and an
        unbalanced quote each returned 200 with `responseHeader.status: 0` and an empty or sanitized
        result set. Treat 400 as documented-but-unobserved.

        OBSERVED, UNDOCUMENTED: `rows` is silently clamped to 500 — `rows=501`, `rows=1000` and
        `rows=99999` all echoed `rows: "500"` and returned 500 documents. A non-numeric `rows` falls
        back to 10 and `start=-1` is clamped to 0, both silently. Paginate with `start` rather than
        raising `rows`.
      parameters:
      - name: q
        in: query
        required: true
        description: Solr query string. A subset of Solr query syntax is supported.
        schema:
          type: string
        examples:
          allObjects:
            summary: Everything in the public index
            value: '*'
          titlePhrase:
            summary: Title keyword
            value: primary_title:irish
          collectionMembership:
            summary: Members of one collection
            value: 'rel_is_member_of_collection_ssim:"bdr:wum3gm43"'
          negation:
            summary: In a collection but not part of another object
            value: 'rel_is_member_of_collection_ssim:"bdr:wum3gm43" -rel_is_part_of_ssim:*'
      - name: fl
        in: query
        required: false
        description: >-
          Comma-separated Solr field list. Defaults to `*`, which returns 50+ fields per document;
          narrowing it is the single biggest response-size lever. See vocabulary/brown-bdr-field-vocabulary.yml.
        schema:
          type: string
          default: '*'
        example: pid,primary_title,abstract
      - name: rows
        in: query
        required: false
        description: Documents to return. Defaults to 10. Silently clamped to a maximum of 500 (observed).
        schema:
          type: integer
          default: 10
          minimum: 0
          maximum: 500
      - name: start
        in: query
        required: false
        description: Zero-based offset for pagination. Negative values are silently clamped to 0 (observed).
        schema:
          type: integer
          default: 0
          minimum: 0
      - name: callback
        in: query
        required: false
        description: >-
          JSONP callback name. Documented by Brown as accepted on all BDR APIs, and confirmed:
          supplying it changes the response Content-Type to `application/javascript` and wraps the
          JSON body in the named function call. JSONP exists here because the API sends no CORS
          headers — no `Access-Control-Allow-Origin` was returned on any probe, so a browser client
          on another origin cannot use `fetch` against it.
        schema:
          type: string
        example: myCb
      responses:
        '200':
          description: >-
            Search result. Returned for successful searches, for searches with zero results, and
            (observed) for malformed queries.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
            application/javascript:
              schema:
                type: string
                description: JSONP wrapper, returned when `callback` is supplied — the JSON body wrapped in the named function call.
        '400':
          description: >-
            Bad request. Documented by Brown for a badly formatted query; not reproduced by any
            probe on 2026-08-30.
          content:
            text/html:
              schema:
                type: string
        '500':
          description: >-
            Internal server error. Documented by Brown as the response to any exception during
            request processing.
          content:
            text/html:
              schema:
                type: string
  /api/items/{pid}/:
    get:
      tags: [Items]
      operationId: getItem
      summary: Get one repository object
      description: >-
        Returns the full metadata record for a single object. The response is link-rich: `api_links`
        dereferences to collection and search API calls, `links.views.iiif_image_info` and
        `links.views.iiif_manifest` point at the IIIF surface, and `links.content_datastreams` and
        `links.descriptive_datastreams` point at the object's binary and MODS XML.
      parameters:
      - name: pid
        in: path
        required: true
        description: Persistent identifier, e.g. `bdr:80246`. Both numeric and Noid-style suffixes occur.
        schema:
          type: string
          pattern: '^bdr:[A-Za-z0-9]+$'
        example: bdr:80246
      responses:
        '200':
          description: Object metadata
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Item'
        '403':
          description: >-
            Forbidden. Documented by Brown for an item that is not found OR is a private object.
          content:
            text/html:
              schema:
                type: string
        '404':
          description: >-
            Not Found. OBSERVED behaviour for an unknown PID — `bdr:0000000` returned 404 with the
            nine-byte `text/html` body `Not Found`, not the documented 403 and not JSON. A client
            parsing every response as JSON will throw here.
          content:
            text/html:
              schema:
                type: string
              example: Not Found
        '500':
          description: Internal server error, per Brown's documented exception behaviour.
  /api/collections/:
    get:
      tags: [Collections]
      operationId: listTopLevelCollections
      summary: List top-level collections
      description: >-
        Returns the repository's TOP-LEVEL collections only, which Brown notes explicitly — this is
        not the full collection tree. Descend via each collection's own endpoint.
      responses:
        '200':
          description: Top-level collection list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CollectionList'
        '500':
          description: Internal server error, per Brown's documented global exception behaviour.
  /api/collections/{collection_id}/:
    get:
      tags: [Collections]
      operationId: getCollection
      summary: Get one collection, its sub-collections and its items
      description: >-
        Accepts either the numeric database id (`403`) or the PID (`bdr:k499pm6d`); both were
        confirmed live. Responses that carry items return URLs to both the web view and the item API
        view of each member.
      parameters:
      - name: collection_id
        in: path
        required: true
        description: Numeric collection id or `bdr:`-prefixed PID.
        schema:
          type: string
        examples:
          numeric:
            value: '403'
          pid:
            value: bdr:k499pm6d
      - name: q
        in: query
        required: false
        description: Sub-query restricting the returned items within this collection.
        schema:
          type: string
        example: greek
      responses:
        '200':
          description: Collection record
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Collection'
        '404':
          description: Not Found. OBSERVED for an unknown collection id, as a nine-byte `text/html` body.
components:
  schemas:
    ApiRoot:
      type: object
      description: The `/api/` link index.
      properties:
        collections:
          type: string
          format: uri
        api docs:
          type: string
          format: uri
    SearchResponse:
      type: object
      required: [responseHeader, response]
      properties:
        responseHeader:
          type: object
          description: Solr response header. `params` echoes the query AFTER the service applied its own defaults and clamps, which is how the 500-row cap becomes visible.
          properties:
            status:
              type: integer
              description: Solr status. 0 on success. Observed as 0 even for malformed queries.
            QTime:
              type: integer
              description: Query time in milliseconds.
            params:
              type: object
              additionalProperties: true
        response:
          type: object
          required: [numFound, start, docs]
          properties:
            numFound:
              type: integer
            start:
              type: integer
            docs:
              type: array
              items:
                $ref: '#/components/schemas/Document'
        links:
          type: object
          description: >-
            Present on every search response. Carries a single `login` URL pointing at the
            affiliation-gated view of the same query — the API's only signal that a larger,
            Brown-authenticated result set exists behind Shibboleth.
          properties:
            login:
              type: string
              format: uri
    Document:
      type: object
      description: >-
        One indexed object. The field set is Solr-dynamic and varies by object type; `fl=*` returned
        50+ fields per document at probe time. Only the fields common to every probed document are
        typed here — see vocabulary/brown-bdr-field-vocabulary.yml for the wider field inventory.
      additionalProperties: true
      properties:
        pid:
          type: string
          example: bdr:80246
        primary_title:
          type: string
        abstract:
          type: array
          items:
            type: string
        object_type:
          type: string
          example: image
        resource_type_ssi:
          type: string
    Item:
      type: object
      description: A full object record from the item API.
      additionalProperties: true
      required: [pid]
      properties:
        pid:
          type: string
        object_type:
          type: string
        primary_title:
          type: string
        uri:
          type: string
          format: uri
          description: Human web view of the object.
        json_uri:
          type: string
          format: uri
          description: Self link — this item API call.
        brief:
          type: object
          description: Display-oriented summary block; every value is an array of strings.
          additionalProperties: true
        relations:
          $ref: '#/components/schemas/Relations'
        api_links:
          type: object
          description: Dereferenceable API URLs for this object's collections and keywords.
          additionalProperties: true
        links:
          $ref: '#/components/schemas/ItemLinks'
        views_dict:
          type: object
          description: Named viewer and IIIF URLs. Duplicates `links.views`.
          additionalProperties:
            type: string
            format: uri
        datastreams:
          type: object
          description: Per-datastream mimeType, size, SHA-512 checksum and lastModified.
          additionalProperties: true
    ItemLinks:
      type: object
      properties:
        thumbnail:
          type: string
          format: uri
        descriptive_datastreams:
          type: object
          description: Descriptive metadata datastreams. `MODS` is the descriptive standard the BDR serves, as XML.
          additionalProperties:
            type: string
            format: uri
        content_datastreams:
          type: object
          description: Binary content datastreams, e.g. `highres`, `lowres`.
          additionalProperties:
            type: string
            format: uri
        views:
          type: object
          description: >-
            Viewer and IIIF endpoints, including `iiif_image_info` and `iiif_manifest`. These are the
            documented route from the item API into the IIIF surface; the IIIF paths are not
            otherwise discoverable, and `/iiif` is disallowed in the repository's robots.txt.
          additionalProperties:
            type: string
            format: uri
    Relations:
      type: object
      description: >-
        Fixed set of relation predicates, each an array. Empty arrays are returned rather than
        omitted, so a client can rely on every key being present.
      properties:
        hasAnnotation: {type: array, items: {type: object, additionalProperties: true}}
        hasDerivation: {type: array, items: {type: object, additionalProperties: true}}
        hasDescription: {type: array, items: {type: object, additionalProperties: true}}
        hasTranscript: {type: array, items: {type: object, additionalProperties: true}}
        hasTranslation: {type: array, items: {type: object, additionalProperties: true}}
        hasPart: {type: array, items: {type: object, additionalProperties: true}}
        isDerivationOf: {type: array, items: {type: object, additionalProperties: true}}
        isVersionOf: {type: array, items: {type: object, additionalProperties: true}}
        isTranscriptOf: {type: array, items: {type: object, additionalProperties: true}}
        isTranslationOf: {type: array, items: {type: object, additionalProperties: true}}
        isMemberOf: {type: array, items: {type: object, additionalProperties: true}}
        isPartOf: {type: array, items: {type: object, additionalProperties: true}}
        isMemberOfCollection:
          type: array
          items:
            $ref: '#/components/schemas/CollectionRef'
    CollectionList:
      type: object
      required: [collections]
      properties:
        collections:
          type: array
          items:
            $ref: '#/components/schemas/CollectionRef'
    CollectionRef:
      type: object
      properties:
        pid: {type: string}
        id: {type: string}
        db_id: {type: integer}
        name: {type: string}
        description: {type: string}
        tags: {type: array, items: {type: string}}
        json_uri: {type: string, format: uri, description: Collection API URL for this collection.}
        uri: {type: string, format: uri, description: Human web view of this collection.}
        thumbnail_url: {type: string, format: uri}
    Collection:
      type: object
      description: A single collection, its sub-collections and its member items.
      additionalProperties: true
      properties:
        name: {type: string}
        description: {type: string}
        items:
          type: object
          additionalProperties: true
        children:
          type: array
          items:
            $ref: '#/components/schemas/CollectionRef'
  securitySchemes: {}
security: []
x-access:
  authentication: none
  description: >-
    Every documented BDR API endpoint is anonymous and keyless. There is no API key, no OAuth flow
    and no registration step. The boundary is not authentication but VISIBILITY — the index exposes
    `_display_public_bsi`, `_display_brown_bsi` and `_display_private_bsi`, and the anonymous API
    sees only public objects. Brown-affiliated access to the wider set goes through the Shibboleth
    login the `links.login` key on every search response points at.
x-throttling:
  observed_headers: none
  description: >-
    No rate-limit headers were returned on any probe. Brown documents in its own API wiki that
    Cloudflare bot protection was added in Spring 2025 and may affect API users requesting a large
    volume of items at a high rate, and advises Brown community members to use the VPN to reduce the
    impact. The repository's robots.txt sets `Crawl-delay: 30`. The 500-row response cap is the only
    hard, observable limit.