Princeton University Art Museum API

Open, REST-style API providing developer access to data about the Princeton University Art Museum and its collections. Four surfaces: objects (with a label-level /tombstone sub-resource and filtering by maker, department, term and on-view status), makers, packages, and a full-text search endpoint that returns the raw Elasticsearch envelope. Pagination and incremental harvesting are supported via size, from, sort, sortorder and lastupdated. No authentication is currently required, though the Museum documents that this may change. Weekly-refreshed static JSON dumps of the whole collection are offered alongside the API for bulk and machine-learning use. The Museum publishes prose documentation, not a contract; the OpenAPI in this repo is DERIVED from that documentation and verified against live responses, and is not Princeton's own artifact.

OpenAPI Specification

princeton-art-museum-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Princeton University Art Museum API
  version: '1.0'
  summary: Open, no-authentication REST access to the Princeton University Art Museum collections.
  description: >-
    REST-style service providing developer access to data about the Princeton University Art
    Museum and its collections. Four resource surfaces are documented: objects (art objects and
    their tombstone records), makers (artists, cultural groups and other makers), packages
    (curated groupings) and a full-text search endpoint backed by Elasticsearch. All responses
    are JSON. No authentication is currently required, though the Museum notes this may change.

    PROVENANCE: the Museum publishes prose documentation in a GitHub repository, not a machine
    readable contract. This OpenAPI was DERIVED by API Evangelist from that documentation and
    verified against live responses on 2026-08-19; it was not published by Princeton. Paths,
    parameters and status codes below were each exercised against the production host.
  contact:
    name: Princeton University Art Museum API
    url: https://github.com/Princeton-University-Art-Museum/puam-api-docs
  x-operator: institution
  x-provenance:
    method: derived
    source: https://github.com/Princeton-University-Art-Museum/puam-api-docs
    derived_by: API Evangelist university pipeline
    verified_against: https://data.artmuseum.princeton.edu
    verified: '2026-08-19'
servers:
  - url: https://data.artmuseum.princeton.edu
    description: Production collections data host (verified 200, 2026-08-19)
tags:
  - name: Objects
    description: Art objects in the Museum's collection.
  - name: Makers
    description: Artists, cultural groups and other makers.
  - name: Packages
    description: Curated groupings of collection material.
  - name: Search
    description: Full-text search across all collection data types.
paths:
  /objects/{id}:
    get:
      tags: [Objects]
      operationId: getObjectById
      summary: Get a single art object by ID
      description: Returns the full record for one art object, including titles, makers, depicted subjects, texts, terms and image references.
      parameters:
        - name: id
          in: path
          required: true
          description: Numeric objectid.
          schema:
            type: integer
          example: 9449
      responses:
        '200':
          description: The art object record.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArtObject'
        '404':
          description: No object with that ID.
  /objects/{id}/tombstone:
    get:
      tags: [Objects]
      operationId: getObjectTombstone
      summary: Get the tombstone (label) record for an object
      description: Returns the abbreviated "tombstone" record — the caption-level fields a gallery label carries.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          example: 9449
      responses:
        '200':
          description: Tombstone record.
          content:
            application/json:
              schema:
                type: object
        '404':
          description: No object with that ID.
  /objects:
    get:
      tags: [Objects]
      operationId: listObjects
      summary: Get multiple objects by filter
      description: >-
        Returns all object records matching the selected criteria. Filter by maker, department,
        term or on-view status, then control the result window with size/from/sort/sortorder and
        harvest incrementally with lastupdated.
      parameters:
        - name: maker
          in: query
          description: Maker ID.
          schema: { type: integer }
          example: 6353
        - name: department
          in: query
          description: Exact department name.
          schema: { type: string }
        - name: term
          in: query
          description: Term ID.
          schema: { type: integer }
        - name: onview
          in: query
          description: Restrict to objects currently on view.
          schema: { type: boolean }
        - name: size
          in: query
          description: Maximum records per response (default 10, maximum 500).
          schema: { type: integer, default: 10, maximum: 500 }
        - name: from
          in: query
          description: Offset of the first result, for pagination.
          schema: { type: integer, default: 0 }
        - name: sort
          in: query
          description: Field to sort on. Defaults to relevance score.
          schema: { type: string }
        - name: sortorder
          in: query
          description: Sort direction.
          schema:
            type: string
            enum: [ASC, DESC]
            default: DESC
        - name: lastupdated
          in: query
          description: Return objects updated on or after this date (YYYY-MM-DD). The incremental-harvest parameter.
          schema: { type: string, format: date }
      responses:
        '200':
          description: Matching object records.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ArtObject'
        '400':
          description: >-
            Bad Request — returned as a plain-text body, not JSON, when the filter set is not
            accepted (for example size supplied with no filter parameter). Verified 2026-08-19.
          content:
            text/plain:
              schema: { type: string }
              example: Bad Request
  /makers/{id}:
    get:
      tags: [Makers]
      operationId: getMakerById
      summary: Get a single maker by ID
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: integer }
          example: 6353
      responses:
        '200':
          description: The maker record.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Maker'
        '404':
          description: No maker with that ID.
  /packages/{id}:
    get:
      tags: [Packages]
      operationId: getPackageById
      summary: Get a single package by ID
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: integer }
      responses:
        '200':
          description: The package record.
          content:
            application/json:
              schema: { type: object }
        '404':
          description: No package with that ID.
  /search:
    get:
      tags: [Search]
      operationId: searchCollections
      summary: Full-text search across collection data
      description: >-
        Full-text search over the Museum's data. The response is the raw Elasticsearch result
        envelope — took, timed_out, _shards and hits — rather than a Museum-specific shape.
      parameters:
        - name: q
          in: query
          required: true
          description: Search term(s).
          schema: { type: string }
          example: monet
        - name: type
          in: query
          description: Data type to search. Use `all` to search every type.
          schema: { type: string }
          example: all
      responses:
        '200':
          description: Elasticsearch search envelope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
components:
  schemas:
    ArtObject:
      type: object
      description: An art object in the Museum's collection.
      properties:
        type: { type: string, examples: [artobject] }
        objectid: { type: integer }
        objectnumber: { type: string }
        sortnumber: { type: string }
        displaytitle: { type: string }
        department: { type: string }
        classification: { type: string }
        datebegin: { type: [integer, 'null'] }
        dateend: { type: [integer, 'null'] }
        datecomputed: { type: [integer, 'null'] }
        daterange: { type: [string, 'null'] }
        displaydate: { type: [string, 'null'] }
        medium: { type: [string, 'null'] }
        dimensions: { type: [string, 'null'] }
        creditline: { type: [string, 'null'] }
        markings: { type: [string, 'null'] }
        inscribed: { type: [string, 'null'] }
        signed: { type: [string, 'null'] }
        restrictions: { type: [string, 'null'] }
        on_view: { type: boolean }
        accessionyear: { type: [string, 'null'] }
        titles:
          type: array
          items:
            type: object
            properties:
              title: { type: string }
              titletype: { type: string }
              displayorder: { type: integer }
        makers:
          type: array
          items:
            $ref: '#/components/schemas/ObjectMaker'
        depicted: { type: array, items: { type: object } }
        texts: { type: array, items: { type: object } }
    ObjectMaker:
      type: object
      properties:
        id: { type: integer }
        displayname: { type: string }
        displaydate: { type: [string, 'null'] }
        datebegin: { type: [integer, 'null'] }
        dateend: { type: [integer, 'null'] }
        prefix: { type: [string, 'null'] }
        suffix: { type: [string, 'null'] }
        role: { type: [string, 'null'] }
        displaymaker: { type: [string, 'null'] }
        displayorder: { type: integer }
    Maker:
      type: object
      properties:
        makerid: { type: integer }
        displayname: { type: string }
        displaybio: { type: [string, 'null'] }
        culturegroup: { type: [string, 'null'] }
        firstname: { type: [string, 'null'] }
        middlename: { type: [string, 'null'] }
        lastname: { type: [string, 'null'] }
        alphasort: { type: [string, 'null'] }
        begindate: { type: [integer, 'null'] }
        enddate: { type: [integer, 'null'] }
        altnames: { type: array, items: { type: object } }
    SearchResponse:
      type: object
      description: Raw Elasticsearch response envelope.
      properties:
        took: { type: integer }
        timed_out: { type: boolean }
        _shards:
          type: object
          properties:
            total: { type: integer }
            successful: { type: integer }
            failed: { type: integer }
        hits:
          type: object
          properties:
            total: { type: integer }
            max_score: { type: [number, 'null'] }
            hits:
              type: array
              items:
                type: object
                properties:
                  _index: { type: string }
                  _type: { type: string }
                  _id: { type: string }
                  _score: { type: number }
                  _source: { type: object }