Skip to content

Export

Exporting copies the files of an Archival Group, at a chosen version, out of OCFL and into a location you name. The Preservation API’s exports are built on this, but present it differently: there you export into a Deposit, and the API works out the destination for you. Here you give the destination yourself, and no Deposit is involved.

POST /export
{
"archivalGroup": "https://storage-api.example/repository/docs-misc/import-job-doc",
"destination": "s3://my-export-bucket/export-of-my-ag",
"sourceVersion": "v15"
}

Omit sourceVersion to export the current version.

The response is 201 Created with the same resource type back, now with an id of its own:

{
"id": "https://storage-api.example/export/h6bb4dpm32",
"type": "Export",
"archivalGroup": "https://storage-api.example/repository/docs-misc/import-job-doc",
"destination": "s3://my-export-bucket/export-of-my-ag",
"sourceVersion": "v15",
"dateBegun": null,
"dateFinished": null,
"files": [],
"errors": null
}

Nothing has been copied yet. A 409 Conflict instead means there is already an unfinished export for this Archival Group; only one runs at a time.

GET /export/h6bb4dpm32

Poll until a non-null dateFinished appears:

{
"id": "https://storage-api.example/export/h6bb4dpm32",
"type": "Export",
"archivalGroup": "https://storage-api.example/repository/docs-misc/import-job-doc",
"destination": "s3://my-export-bucket/export-of-my-ag",
"sourceVersion": "v15",
"dateBegun": "2025-10-03T09:55:34.3621834Z",
"dateFinished": "2025-10-03T09:57:20.076543Z",
"files": [
"s3://my-export-bucket/export-of-my-ag/mets.xml",
"s3://my-export-bucket/export-of-my-ag/objects/file1.doc"
],
"errors": []
}
Property Description
archivalGroup The Storage API URI of the Archival Group to export.
destination The S3 location to export to. A trailing slash is trimmed; the Archival Group’s internal paths are recreated below it.
sourceVersion The OCFL version being exported. If you asked for one it is honoured or the export fails; if you left it out, it is filled in with the version that was actually exported, so the result always records what you got.
dateBegun When the API started processing. Null or missing until then.
dateFinished When the API finished. Null or missing until then.
files Every file successfully exported, as S3 URIs.
errors Error objects, not strings. Null until the export has run.

An Export also carries the common properties, but unlike every other resource in the platform the API does not fill them in: the export is stored as you sent it, with only an id added. If you want created and createdBy on the record, send them.

The API looks up the Storage Map for the requested version, which tells it, for every logical path in the Archival Group, the real S3 key of the file that path resolves to in that version and its SHA-256. It then copies each one with a server-side S3 copy, asking S3 to compute the SHA-256 of the copy as it goes.

The checksum of each copy is compared with the one OCFL recorded. A file that matches is added to files; a file that does not is added to errors with both digests in the message, and is not listed in files. So an export is verified, and files is a list of what arrived intact rather than a list of what was attempted.

If you asked for a version that is not the one the Storage Map resolves to, POST /exportMetsOnly answers 409 there and then, because it is synchronous. POST /export cannot: it has already returned 201, and the mismatch is only logged - the Export you are polling simply never gains a dateFinished, and gains no errors entry either. Poll with a timeout rather than forever.

POST /exportMetsOnly

The body is the same, and so is the response body - but this one runs synchronously and returns 200 OK with the finished Export. It is not recorded, so there is no id to poll and nothing appears under /export/....

It copies only the METS file: any file in the object whose name ends .xml and contains mets. Everything else in the Archival Group is skipped.

This exists because a great deal of work on a preserved object needs only its METS - the Preservation API uses it to create a METS-only Deposit for an existing Archival Group, so that the METS can be edited and preserved again without moving gigabytes of TIFFs around.

Unlike import, export has no separately deployable runner: it is queued in memory inside the Storage API itself, on a channel bounded at ten. Two consequences for a caller. A restart loses anything still queued — an export that never reaches dateFinished may simply have been dropped, so poll with a timeout rather than forever. And with only ten slots, a burst of export requests will block rather than queue indefinitely.