---
title: OAI-PMH Harvesting
description: Harvest an institution's public collection metadata over OAI-PMH 2.0 — endpoint shape, verbs, formats, sets, and selective harvesting.
section: protocols
order: 1
updated: 2026-07-11
verified: 2026-07-11
related: [formats/metadata-formats, protocols/linked-data]
features: [metadata-export]
---

# OAI-PMH Harvesting

Every institution hosted on Preservated exposes a public [OAI-PMH](http://www.openarchives.org/OAI/openarchivesprotocol.html) 2.0 endpoint you can harvest with any standard OAI-PMH client, no authentication required.

## Endpoint

```
https://{your-domain}/{institution}/oai
```

`{institution}` is the museum's slug on its Preservated site. The endpoint speaks the standard OAI-PMH request/response cycle: send a `verb` query parameter (plus that verb's arguments) and get back an XML envelope.

## Verbs

All six required OAI-PMH verbs are implemented:

| Verb | Purpose |
| --- | --- |
| `Identify` | Repository name, base URL, protocol version, earliest datestamp, granularity |
| `ListMetadataFormats` | The metadata formats available (optionally scoped to one record) |
| `ListSets` | The institution's public collections, as OAI sets |
| `ListIdentifiers` | Record headers (identifier + datestamp + set membership) for a metadata format, without the metadata body |
| `ListRecords` | Full records (header + metadata) for a metadata format |
| `GetRecord` | A single record by identifier and metadata format |

## Metadata formats

Pass one of these as `metadataPrefix` on `ListRecords`, `ListIdentifiers`, or `GetRecord`: `oai_dc`, `oai_qdc`, `lido`, `cdwalite`, or `marc21`. See [Metadata Formats](/developers/en-US/formats/metadata-formats) for what each one contains and when to pick it.

## Sets

OAI sets correspond to the institution's **public** collections. `setSpec` is the collection's slug and `setName` is its display name. Pass a `set` argument to `ListIdentifiers`/`ListRecords` to scope harvesting to one collection. An institution with no public collections returns a `noSetHierarchy` error from `ListSets`.

## Selective harvesting

`ListIdentifiers` and `ListRecords` accept `from` and `until` (either `YYYY-MM-DD` or full `YYYY-MM-DDThh:mm:ssZ` datetimes — both arguments must use the same granularity) to harvest only records updated within a window, so you can run an initial full harvest and then poll incrementally.

## Pagination

Large result sets are paginated: a partial response includes a `resumptionToken` element, which you pass back as the `resumptionToken` argument (alone — no other arguments — on the follow-up request) to fetch the next page. A list that started issuing tokens closes with an empty `resumptionToken` element on its final page.

## Scope

Only **public** artifacts are harvestable — an OAI-PMH request from an anonymous or third-party harvester never surfaces anything a member of the public couldn't already see on the institution's site.

## Record identifiers

Each record's OAI identifier is a stable opaque string of the form `oai:{host}:{institution}:{artifactId}`. Treat it as opaque — you get identifiers from `ListIdentifiers`/`ListRecords`, not by constructing them.

## Error handling

Protocol-level problems (a bad verb, a missing required argument, an unknown metadata format, no matching records) are reported as an OAI `<error>` element inside a normal `200 OK` envelope, per the OAI-PMH spec — check the response body for `<error>`, not just the HTTP status. A genuine server fault returns a non-200 status.
