Activity, content and search
The read-only parts of the Storage API: what has changed, the bytes of a preserved file, where those bytes really are, and a crude path search.
The activity stream of Import Jobs
Section titled “The activity stream of Import Jobs”The Storage API publishes an activity stream in the same IIIF Change Discovery shape as the Preservation API’s, but about a different subject: it is a record of the Storage API’s own Import Job activity, not of Archival Groups. The Preservation API consumes it and, from it, produces the stream of created and updated Archival Groups that everything else reads.
GET /activity/importjobs/collection{ "@context": "http://iiif.io/api/discovery/1/context.json", "id": "https://storage-api.example/activity/importjobs/collection", "type": "OrderedCollection", "totalItems": 3914, "first": { "id": "https://storage-api.example/activity/importjobs/pages/1", "type": "OrderedCollectionPage" }, "last": { "id": "https://storage-api.example/activity/importjobs/pages/40", "type": "OrderedCollectionPage" }}Pages hold 100 entries and are numbered from 1. A client wanting the events since it last read would load the last page:
GET /activity/importjobs/pages/40{ "@context": "http://iiif.io/api/discovery/1/context.json", "id": "https://storage-api.example/activity/importjobs/pages/40", "type": "OrderedCollectionPage", "startIndex": 3900, "partOf": { "id": "https://storage-api.example/activity/importjobs/collection", "type": "OrderedCollection" }, "prev": { "id": "https://storage-api.example/activity/importjobs/pages/39", "type": "OrderedCollectionPage" }, "orderedItems": [ { "type": "Update", "object": { "id": "https://storage-api.example/import/results/m3cnbckjmtd9/cc/lqj7mqhg", "type": "ImportJob", "seeAlso": [ { "id": "https://storage-api.example/repository/cc/lqj7mqhg", "type": "ArchivalGroup" } ] }, "startTime": "2025-10-06T10:31:02Z", "endTime": "2025-10-06T10:34:19Z" } ] // ... 99 more}…and then work from the end of orderedItems backwards until it reaches an endTime earlier than the last time it read the stream, following prev to the page before if it needs to. It will then have gathered all the new events. A page that is not the last one also has a next.
| Property | Description |
|---|---|
type (of the activity) |
Always Update. The Storage API does not distinguish creating an Archival Group from changing one. |
object.id |
The Import Job Result URI. |
object.type |
ImportJob, even though the id is that of a result. |
object.seeAlso |
An array with one entry: the Archival Group the job applied to. |
startTime |
When the job was received. |
endTime |
When the job finished. This is what the stream is ordered by, and what a reader keeps track of. |
Only jobs that have finished appear; a job that is still waiting or running is not in the stream and is not counted in totalItems.
Fetching file content
Section titled “Fetching file content”If you can call the Storage API you can retrieve the bytes of any Binary.
GET /content/library/manuscripts/ms-342/objects/34r.tiffThe path is the same as the repository path apart from the first segment. This URI is exposed as the content property of a Binary in both APIs; it is only honoured here.
The response streams the file with the Binary’s recorded contentType. Anything at the path that is not a Binary - a Container, an Archival Group, nothing at all - is an error, and the body is a problem document saying 404. Be careful how you detect it: the controller does not set the response status, so what you actually receive is HTTP 200 carrying that document, and a client that branches on the status code will read the failure as success. Check the content type, or the body, rather than the status (issue #262).
Callers that are trusted with direct access to the OCFL bucket do not need this endpoint at all: a Binary’s origin property gives the real S3 location of the bytes.
The storage map
Section titled “The storage map”GET /ocfl/storagemap/{archivalGroupPathUnderRoot}GET /ocfl/storagemap/{archivalGroupPathUnderRoot}?version=v3The same resource, at the same path, as the Preservation API’s - the Preservation API passes it straight through. It maps each logical path in an Archival Group to the S3 key that path resolves to in a given version, which is what makes it possible to read an old version’s files without asking Fedora for them.
| Property | Description |
|---|---|
archivalGroup |
The Archival Group this map is of. |
version |
The version the map describes: ocflVersion, mementoTimestamp, mementoDateTime. |
headVersion |
The current version of the object. |
allVersions |
Every version, in order. |
storageType |
The kind of storage - S3. |
root |
The bucket. |
objectPath |
The key prefix of the OCFL object within the bucket. |
files |
A map of logical path to hash (SHA-256) and fullPath (the key, relative to objectPath, of the version of the file this version points at). |
hashes |
The reverse lookup: SHA-256 to path. |
Asking for a version the map does not resolve to is an error rather than a silently different answer.
Fedora search
Section titled “Fedora search”GET /FedoraSearch?text=ms-342&page=0&pageSize=50A deliberately simple search, and quite unlike the Preservation API’s. It is a case-insensitive substring match over repository paths, run directly against Fedora’s own database, restricted to rows that have a media type - which is to say, to Binaries. It does not look at names (dc:title), at METS, or at file content.
| Parameter | Description |
|---|---|
text |
Required. The substring to look for in the path. An empty or whitespace value is a 400. |
page |
Zero-based. page=0 is the first page. |
pageSize |
Between 1 and 500. |
{ "total": 128, "count": 50, "page": 0, "pageSize": 50, "results": [ { "fedoraId": "info:fedora/library/manuscripts/ms-342/objects/34r.tiff", "created": "2025-03-11T11:19:13Z", "lastModified": "2025-03-11T11:19:13Z", "contentSize": 15986, "mimeType": "image/tiff" } ]}total is the number of matches, count the number returned on this page.
Note that the page numbering here starts at 0, while the activity stream’s pages start at 1.
Connectivity checks
Section titled “Connectivity checks”| Path | What it tells you |
|---|---|
/health |
The service is up. This is what the load balancer uses. |
/fedora |
Whether the Storage API can reach Fedora. |
/storagecheck |
Whether the Storage API can read its S3 bucket. |
/whoami |
Who the API resolved you as. See Authentication. |