26.3.0 26.2.0 26.1.0 25.4.0 25.3.0
26.3.0 26.2.0 26.1.0 25.4.0 25.3.0

Preservation actions API

You can use the Preservation actions API to run preservation actions on packages, follow their progress, and read the results. A preservation action is a task that the archive runs on a package, such as calculating fixity information or validating PDF/A files. It keeps the files usable and verifiable.

When you start an action, the call returns at once, and you follow the run with a status call. You can also schedule actions to run on a regular basis.

Every call needs the headers in Common headers.

How a run works

  1. To find the action names, list the enabled actions with GET /v2/preservation-action?onlyEnabled=true.

  2. Start the run with POST /v2/preservation-action/execute. The response holds an executionId.

  3. Poll GET /v2/preservation-action/bulk/{executionId} until status is COMPLETED or FAILED.

  4. To see the result on each package, list the execution reports with GET /v2/preservation-action/reports.

List the available actions

Returns the preservation actions, enabled or not, with their order and settings. Only enabled actions can run.

GET /v2/preservation-action

Required role: archive-content-manager

Name

Type

Required

Description

onlyEnabled

boolean

No

If true, returns only the actions that are enabled. Default: false.

Response: 200 OK with a PreservationActionList.

JSON
{
  "items": [
    {
      "name": "fixityInformationPlugin",
      "enabled": true,
      "order": 40,
      "properties": {
        "algorithm": "SHA256"
      }
    },
    {
      "name": "pdfValidationPlugin",
      "enabled": true,
      "order": 30
    }
  ]
}

Run actions on packages

Starts one or more preservation actions on a set of packages. Pick the packages in one of three ways:

  • packageIds: a list of package IDs.

  • criteria: a query that finds the packages. For the format, see QueryCriteria.

  • allPackages: set it to true to run on every package in the archive. If you leave out all three, the call fails.

The archive skips the packages that you aren't allowed to manage, and the packages in the trash.

POST /v2/preservation-action/execute

Required role: archive-content-manager

Name

Type

Required

Description

actionNames

array of strings

Yes, or actionName

The names of the actions to run, from List the available actions.

actionName

string

No

Deprecated. The name of one action. Ignored if actionNames has a value.

packageIds

array of strings

One of three

The IDs of the packages.

criteria

QueryCriteria

One of three

A query that finds the packages.

allPackages

boolean

One of three

Set to true to run on every package in the archive.

On each package, the actions run in the order of the actionNames list. If an action ends in FAILURE on a package, the next actions don't run on that package.

Caution: Check the action names before you start a run. A name that isn't an enabled action still gives 202, but then none of the actions runs on any package, and no execution reports appear.

Tip: To run an action on a package set, list its packages with the Package sets API, and send their IDs in packageIds.

Bash
curl -X POST "https://archive.example.com/v2/preservation-action/execute" \
  -H "Authorization: Bearer $TOKEN" \
  -H "tenant: example-tenant" \
  -H "Content-Type: application/json" \
  -d '{
    "actionNames": ["fixityInformationPlugin", "pdfValidationPlugin"],
    "packageIds": ["HR-2019-0042", "HR-2019-0043"]
  }'

Response: 202 Accepted with a BulkPreservationActionResult. The actions are queued, not done. Keep the executionId to follow the run.

JSON
{
  "executionId": "6f1c2a9e-4b7d-4f0e-9a51-3c2d8e7b1a40",
  "status": "PENDING",
  "totalPackages": 0,
  "processedPackages": 0,
  "errorCount": 0
}
  • 400 with REQUIRED_FIELD: there's no action name, or you didn't pick any packages.

  • 400 with MUTUALLY_EXCLUSIVE_FIELDS: you used more than one of packageIds, criteria, and allPackages.

  • 400: the criteria isn't valid. The reason and details say which rule: UNKNOWN_QUERY_FIELD, OPERATOR_NOT_ALLOWED, INVALID_QUERY_CRITERIA, REQUIRED_FIELD, INVALID_VALUE, INVALID_DATE, or INVALID_FORMAT.

Follow a run

Returns the progress of a run that you started with Run actions on packages or Run a schedule now. Call it every few seconds until status is COMPLETED or FAILED.

GET /v2/preservation-action/bulk/{executionId}

Required role: archive-content-manager

Name

Type

Required

Description

executionId

string

Yes

The executionId from the response that started the run.

Response: 200 OK with a BulkPreservationActionResult.

  • 404 with EXECUTION_NOT_FOUND: the archive doesn't know this executionId.

List execution reports

Each time an action runs on a package, the archive records the result in an execution report. You can list these reports for all packages, and filter them.

GET /v2/preservation-action/reports

Required role: archive-content-manager

Name

Type

Required

Description

actionName

array of strings

No

Only reports for these actions. Separate the names with commas, or repeat the parameter.

status

array of strings

No

Only reports with these results: SUCCESS, WARNING, FAILURE. Not case-sensitive. Separate the values with commas, or repeat the parameter.

packageId

string

No

Only reports for this package.

from

string

No

Only reports from this moment on. Use 2026-01-15, 2026-01-15T09:30:00 (UTC), or 2026-01-15T09:30:00Z.

to

string

No

Only reports up to this moment. Same formats as from. A date without a time includes that whole day.

sortBy

string

No

pluginName, status, or packageId. Leave it out to sort by the execution date.

sortOrder

string

No

asc or desc. Default: desc.

page

integer

No

The page number, starting at 0. Default: 0.

pageSize

integer

No

The number of reports per page. Default: 100.

Response: 200 OK with a PreservationActionReportList.

JSON
{
  "totalResults": 1,
  "page": 0,
  "pageSize": 100,
  "items": [
    {
      "actionName": "pdfValidationPlugin",
      "packageId": "HR-2019-0042",
      "status": "WARNING",
      "executionDate": "2026-09-30T14:02:11Z",
      "message": "contract.pdf isn't valid PDF/A"
    }
  ]
}
  • 400 with UNSUPPORTED_VALUE: a status value isn't one of the three results.

  • 400 with INVALID_DATE: from or to isn't in one of the formats.

Export execution reports

Downloads the execution reports as a CSV file. It takes the same filters as List execution reports, and returns every matching report, without pages.

GET /v2/preservation-action/reports/export

Required role: archive-content-manager

Query parameters: actionName, status, packageId, from, and to, as in List execution reports.

Response: 200 OK with a text/csv file. The first line holds the column names:

pluginName,packageId,status,executionDate,message

The pluginName column holds the action name.

Schedule actions

A schedule runs one or more actions on the packages that match a query, at the times that you set. The archive starts the schedule's runs on its own, and you can also start one at any time.

When a schedule runs

Set the schedule field to a Quartz cron expression, for example:

  • 0 0 2 * * ?: every day at 2 AM.

  • 0 30 1 ? * SUN: every Sunday at 1:30 AM.

  • 0 0 3 1 * ?: on the first day of every month at 3 AM.

An expression has six or seven fields, from the seconds to an optional year. The archive refuses an expression that isn't valid or that has a value out of range, such as 61 minutes.

A run that a schedule starts on its own isn't limited by what you can manage. It covers every package that matches the query.

List schedules

GET /v2/preservation-action/schedules

Required role: archive-content-manager

Response: 200 OK with a PreservationScheduleList, sorted by name.

Get a schedule

GET /v2/preservation-action/schedules/{scheduleId}

Required role: archive-content-manager

Name

Type

Required

Description

scheduleId

string

Yes

The ID of the schedule.

Response: 200 OK with a PreservationSchedule.

  • 404: there's no schedule with this ID.

Create a schedule

Sets up a schedule. It starts running at the next time that matches schedule.

POST /v2/preservation-action/schedules

Required role: archive-content-manager

Name

Type

Required

Description

name

string

Yes

The name of the schedule.

description

string

No

A description.

plugins

array of strings

Yes

The names of the actions to run, from List the available actions. At least one. On each package, they run in this order.

criteria

QueryCriteria

Yes

A query that finds the packages. The archive runs it again each time the schedule runs, so packages that match later are included.

schedule

string

Yes

When to run, as a Quartz cron expression. See When a schedule runs.

enabled

boolean

No

If false, the schedule doesn't run on its own. You can still run it now. Default: true.

JSON
{
  "name": "Monthly fixity check",
  "description": "Recalculates fixity for packages older than a year",
  "plugins": ["fixityInformationPlugin"],
  "criteria": {
    "combinator": "AND",
    "rules": [
      { "field": "dc:created", "operator": "OLDER_THAN", "value": "P1Y" }
    ]
  },
  "schedule": "0 0 3 1 * ?",
  "enabled": true
}

Response: 201 Created with the PreservationSchedule.

  • 400 with REQUIRED_FIELD: name, plugins, criteria, or schedule is missing.

  • 400 with INVALID_CRON: schedule isn't a valid cron expression.

  • 400: the criteria isn't valid. The reason says which rule, as in Run actions on packages.

Update a schedule

Replaces the schedule with the body that you send. The body has the same fields as Create a schedule, so send all of them, not only the ones that change.

PUT /v2/preservation-action/schedules/{scheduleId}

Required role: archive-content-manager

Response: 200 OK with the updated PreservationSchedule.

Delete a schedule

Deletes the schedule.

DELETE /v2/preservation-action/schedules/{scheduleId}

Required role: archive-content-manager

Response: 204 No Content.

  • 404: there's no schedule with this ID.

Run a schedule now

Starts the schedule's actions on its packages straight away, whether or not the schedule is enabled.

POST /v2/preservation-action/schedules/{scheduleId}/run

Required role: archive-content-manager

Response: 202 Accepted with a BulkPreservationActionResult. To follow the run, see Follow a run.

  • 404: there's no schedule with this ID.

Schemas

PreservationAction

Field

Type

Description

name

string

The name of the action. Use it in actionNames and plugins.

enabled

boolean

Whether the action is enabled.

order

integer

Where the action comes in the archive's own sequence. The actionNames list decides the order of a run that you start.

properties

object

The action's settings, as name and value pairs. Left out if the action has none.

PreservationActionList

Field

Type

Description

items

array of PreservationAction

The actions.

BulkPreservationActionResult

Field

Type

Description

executionId

string

The ID of the run. Use it to follow the run.

status

string

PENDING: the run is waiting to start. RUNNING: the archive is processing the packages. COMPLETED: the run is over. FAILED: the run was stopped before the end.

totalPackages

integer

The number of packages in the run.

processedPackages

integer

The number of packages processed so far.

errorCount

integer

The number of errors that the archive counted in the run. An action that fails on a package isn't counted. To see whether an action passed, check the execution reports.

PreservationActionReport

Field

Type

Description

actionName

string

The name of the action.

packageId

string

The ID of the package.

status

string

SUCCESS: the action finished without problems. WARNING: the action finished, but found something to look at. FAILURE: the action didn't finish, or one of its checks didn't pass.

executionDate

string (date-time)

When the action ran.

message

string

What the action reported.

PreservationActionReportList

Field

Type

Description

totalResults

number

The number of reports that match the filters.

page

number

The page number.

pageSize

number

The page size.

items

array of PreservationActionReport

The reports in the page of results.

PreservationSchedule

Field

Type

Description

scheduleId

string

The ID of the schedule.

name

string

The name of the schedule.

description

string

The description.

plugins

array of strings

The names of the actions that the schedule runs.

criteria

QueryCriteria

The query that finds the packages.

schedule

string

When the schedule runs, as a Quartz cron expression.

enabled

boolean

Whether the schedule runs on its own.

createdAt

string (date-time)

When the schedule was created.

modifiedAt

string (date-time)

When the schedule was last changed.

PreservationScheduleList

Field

Type

Description

items

array of PreservationSchedule

The schedules.