Using the API

Chronopolis provides an HTTP API for accessing its Ingest Server, which contains a registry of information for what data Chronopolis contains and where that data is held. In order to access the API, normal authorization and authentication protocols should be used as described below.

Authentication

The authentication method used is just Basic Auth, which requires you to have a user and password for connecting. This is done in the form of a base64 encoded string passed in the Authorization header.

User Roles

Depending on the actions you will be taking, you might need certain roles granted (e.g. only ROLE_ADMIN can create resources). If elevated roles are necessary, you will need to speak to the administrator of the Ingest Server in order to get proper roles set for your service.

Currently there are three roles:

Available Roles
Role HTTP Constraints Description

ROLE_SERVICE

GET

Read only user for querying the API

ROLE_USER

GET, PUT

General user which can update resources, but not create

ROLE_ADMIN

GET, PUT, POST

Administrative user which can update and create resources

Responses

The API will return HTTP 200: Ok or HTTP 201: Created on successful operations. The content-type will normally be application/json with a few exceptions.

Error Responses

  • HTTP 400: Bad Request - Check the payload which was sent to the server

  • HTTP 401: Unauthorized - Check the user information

  • HTTP 403: Forbidden - Check the user roles or the resource trying to be modified

  • HTTP 404: Not Found - The requested resource does not exist

  • HTTP 409: Conflict - The request resource already exists

  • HTTP 500: Internal Server Error - The server failed during it’s processing; please report the incident

Pagination

Pagination in the API was originally provided by Spring through its Page and PageImpl classes. Though these can change over time, they provide a set of data which looks roughly like:

{
  "content" : [{}, {}, ...],
  "pageable" : {
    "sort" : {
      "sorted" : true,
      "unsorted" : false,
      "empty" : false
    },
    "pageSize" : 25,
    "pageNumber" : 2,
    "offset" : 50,
    "unpaged" : false,
    "paged" : true
  },
  "last" : true,
  "totalPages" : 3,
  "totalElements" : 59,
  "first" : false,
  "sort" : {
    "sorted" : true,
    "unsorted" : false,
    "empty" : false
  },
  "numberOfElements" : 9,
  "size" : 25,
  "number" : 2,
  "empty" : false
}

Our clients use a SpringPage class which allows them to deserialize the Paging json without requiring the Spring Data Commons dependency.

HTTP API

States and Enums

There are various states which are tracked through enum types for the models in the API. In addition in order to control some of the vocabulary other enum types are used for Fixity Algorithm support.

Any enum which is used on an API model will be defined in package org.chronopolis.rest.models.enums, however some which are used as discriminator types (e.g. Bag Staging Type) may be found elsewhere.

Bag Status

BagStatus.kt | Describes the state which a Bag is in.

BagStatus Enum Values

DEPOSITED

The Bag was registered with Ingest

INITIALIZED

The Bag has had all Files and Fixity registered

TOKENIZED

The Bag has had all ACE Tokens registered and written a Token Store to Ingest’s storage

REPLICATING

Replications have been made for a set of Chronopolis Nodes

PRESERVED

All Replications succeeded successfully

DEPRECATED

The Bag is no longer actively tracked by ACE at each Chronopolis node

DELETED

The Bag has been removed from disk at each Chronopolis Node

ERROR

An error occurred while processing the Bag

Replication Status

ReplicationStatus.kt | Describes the state a Replication is in

ReplicationStatus Enum Values

PENDING

A Replication has been requested but not yet acted on

STARTED

A Replication has been added to the queue to be worked on

TRANSFERRED

Both the ACE Token Store and Bag have been transferred into a Chronopolis Node’s preservation storage

ACE_REGISTERED

The Bag associated with the Replication has been registered in a Node’s ACE AM

ACE_TOKEN_LOADED

The Token Storage has been imported into a Node’s ACE AM for the Bag

ACE_AUDITING

The initial audit was triggered for the Bag in a Node’s ACE AM

SUCCESS

The initial audit passed indicating that no files were corrupt on transfer

FAILURE

General failure of the replication

FAILURE_TOKEN_STORE

The hash of the token store was incorrect after transfer

FAILURE_TAG_MANIFEST

The hash of the Bag’s tagmanifest was incorrect after transfer

FAILURE_ACE_AUDIT

The audit had an error which was unable to be resolved

Repair Status

RepairStatus.kt | Describes the state a Repair is in

RepairStatus Enum Values

REQUESTED

A Repair was requested

STAGING

A Repair was picked up for fulfillment and is being staged at the Fulfilling Node

READY

A Repair is ready to be transferred from the Fulfilling Node

TRANSFERRED

A Repair was successfully transferred from the Fulfilling Node

REPAIRED

A Repair operation completed successfully

FAILED

A Repair operation was not able to be completed

Audit Status

AuditStatus.kt | The state of an ACE AM audit for a Repair

AuditStatus Enum Values

PRE

An audit is not yet ready to be triggered

AUDITING

An audit is active

SUCCESS

An audit succeeded

FAIL

An audit failed

Fulfillment Type

FulfillmentType.kt | The different types of transfer workflows for fulfilling a Repair

FulfillmentType Enum Values

ACE

Fulfill a Repair through a remote ACE Audit Manager

NODE_TO_NODE

Fulfill a repair through another Chronopolis Node

Fixity Algorithm

FixityAlgorithm.kt | The supported hashing algorithms

FixityAlgorithm Enum Values

SHA_256

Identifier for the SHA-256 algorithm

UNSUPPORTED

Indication that the algorithm found is not supported

Data Type

DateType.kt | The Data which a StorageRegion is holding

DataType Enum Values

BAG

The StorageRegion is used for staging Bags

TOKEN

The StorageRegion is used for staging ACE Token Stores

Storage Type

StorageType.kt | Value for describing where a StorageRegion is located

StorageType Enum Values

LOCAL

The StorageRegion is on a server local to the Chronopolis Node

Storage Unit

StorageUnit.kt | Basic byte units for simplifying form input

StorageUnit Enum Values

B

Byte

KiB

Kibibyte

MiB

Mibibye

GiB

Gibibyte

TiB

Tebibyte

PiB

Pebibyte

OOB

Out of bounds

Bag Staging Type

StagingDao.java | Discriminator Strings for StagingStorage API paths

Staging Enum Discriminators

BAG

The Staging used is for a Bag

TOKEN_STORE

The Staging used is for an ACE Token Store


Bag Operations

The Bag operations are endpoints which have actions on Bags, which are the main way of packaging data in Chronopolis. This means that each Bag correlates to a single unit of preservation.

This section uses the enum Bag Status

Get Bag

GET /api/bags/:id

Retrieve a single Bag that Chronopolis tracks, identified by its id. Includes staging information if present.

Response
HTTP 200; Content-Type: application/json
{
  "id" : Long,
  "size" : Long,
  "totalFiles" : Long,
  "name" : String,
  "creator" : String,
  "depositor" : String,
  "status" : BagStatus,
  "replicatingNodes" : [ String ],
  "bagStorage" : {
    "active" : Boolean,
    "size" : Long,
    "region" : Long,
    "totalFiles" : Long,
    "path" : String,
    "fixities" : [  ]
  },
  "tokenStorage" : {
    "active" : Boolean,
    "size" : Long,
    "region" : Long,
    "totalFiles" : Long,
    "path" : String,
    "fixities" : [ ]
  },
  "createdAt" : ISO-8601 DateTime at UTC-0,
  "updatedAt" : ISO-8601 DateTime at UTC-0
}

List Bags

GET /api/bags

Return a pageable list of all Bags tracked by Chronopolis

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

name

String

The exact name of the bag to search for

creator

String

The creator of the bag to search for

depositor

String

The depositor of the bag to search for

status

BagStatus

A BagStatus state to search on

Response
HTTP 200; Content-Type: application/json
{
  "content" : [ {
    "id" : Long,
    "size" : Long,
    "totalFiles" : Long,
    "name" : String,
    "creator" : String,
    "depositor" : String,
    "status" : BagStatus,
    "replicatingNodes" : [ String ],
    "createdAt" : ISO-8601 DateTime at UTC-0,
    "updatedAt" : ISO-8601 DateTime at UTC-0
  },... ],
  "pageable" : {
    "sort" : {
      "sorted" : Boolean,
      "unsorted" : Boolean,
      "empty" : Boolean
    },
    "pageSize" : Integer,
    "pageNumber" : Integer
    "offset" : Integer
    "unpaged" : Boolean,
    "paged" : Boolean
  },
  "last" : Boolean,
  "totalPages" : Integer,
  "totalElements" : Integer,
  "first" : Boolean,
  "sort" : {
    "sorted" : Boolean,
    "unsorted" : Boolean,
    "empty" : Boolean
  },
  "numberOfElements" : Integer,
  "size" : Integer,
  "number" : Integer
  "empty" : Boolean
}

Create Bag

POST /api/bags

Create a Bag which Chronopolis should keep track of

Request Body
Content-Type: application/json
{
  "name": String,
  "size": Long,
  "totalFiles": Long,
  "depositor": String
}
Response Body
HTTP 201; Content-Type: application/json
{
  "id": Long,
  "size": Long,
  "totalFiles": Long,
  "name": String,
  "creator": String,
  "depositor": String,
  "status": BagStatus,
  "replicatingNodes": [],
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0
}

File Operations

It is required that each Bag in Chronopolis has the Files that track both its payload and its metadata registered. This includes information about the files themselves and additional Fixity information.

This section uses the Fixity Algorithm enum

Get File

GET /api/files/:file_id

Get a single file identified by its file_id

Response Body
{
  "id": Long,
  "filename": String,
  "size": Long,
  "fixities": [
    {
      "value": String,
      "algorithm": FixityAlgorithm,
      "createdAt": ISO-8601 DateTime at UTC-0
    }
  ],
  "bag": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0
}

List Files

GET /api/files

Get a pageable list of all Files

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

fixity

String

The fixity (hash) to search for

algorithm

String

The fixity algorithm to query on

bag

Long

The id of the Bag

sizeLess

Long

Query only on files smaller than the given size

sizeGreater

Long

Query only on files larger than the given size

createdBefore

ZonedDateTime

Query for files created before a given DateTime

createdAfter

ZonedDateTime

Query for files created after a given DateTime

updatedBefore

ZonedDateTime

Query for files created before a given DateTime

updatedAfter

ZonedDateTime

Query for files created after a given DateTime

Response Body
{
  "content": [
    {
      "id": Long,
      "filename": String,
      "size": Long,
      "fixities": [
        {
          "value": String,
          "algorithm": FixityAlgorithm,
          "createdAt": ISO-8601 DateTime at UTC-0
        }
      ],
      "bag": Long,
      "createdAt": ISO-8601 DateTime at UTC-0,
      "updatedAt": ISO-8601 DateTime at UTC-0
    }, ...
  ],
  "pageable": {
    "sort": {
      "sorted": Boolean,
      "unsorted": Boolean,
      "empty": Boolean
    },
    "pageSize": Integer,
    "pageNumber": Integer
    "offset": Integer
    "unpaged": Boolean,
    "paged": Boolean
  },
  "last": Boolean,
  "totalPages": Integer,
  "totalElements": Integer,
  "first": Boolean,
  "sort": {
    "sorted": Boolean,
    "unsorted": Boolean,
    "empty": Boolean
  },
  "numberOfElements": Integer,
  "size": Integer,
  "number": Integer
  "empty": Boolean
}

Get File In Bag

GET /api/bags/:bag_id/files/:file_id

Retrieve a single file that belongs to a Bag

Response Body
{
  "id": Long,
  "filename": String,
  "size": Long,
  "fixities": [
    {
      "value": String,
      "algorithm": FixityAlgorithm,
      "createdAt": ISO-8601 DateTime at UTC-0
    }
  ],
  "bag": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0
}

List Files In Bag

GET /api/bags/:bag_id/files

Retrieve a pageable list of all files within a Bag

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

fixity

String

The fixity (hash) to search for

algorithm

String

The fixity algorithm to query on

bag

Long

The id of the Bag

sizeLess

Long

Query only on files smaller than the given size

sizeGreater

Long

Query only on files larger than the given size

createdBefore

ZonedDateTime

Query for files created before a given DateTime

createdAfter

ZonedDateTime

Query for files created after a given DateTime

updatedBefore

ZonedDateTime

Query for files created before a given DateTime

updatedAfter

ZonedDateTime

Query for files created after a given DateTime

Response Body
{
  "content": [
    {
      "id": Long,
      "filename": String,
      "size": Long,
      "fixities": [
        {
          "value": String,
          "algorithm": FixityAlgorithm,
          "createdAt": ISO-8601 DateTime at UTC-0
        }
      ],
      "bag": Long,
      "createdAt": ISO-8601 DateTime at UTC-0,
      "updatedAt": ISO-8601 DateTime at UTC-0
    }, ...
  ],
  "pageable": {
    "sort": {
      "sorted": Boolean,
      "unsorted": Boolean,
      "empty": Boolean
    },
    "pageSize": Integer,
    "pageNumber": Integer
    "offset": Integer
    "unpaged": Boolean,
    "paged": Boolean
  },
  "last": Boolean,
  "totalPages": Integer,
  "totalElements": Integer,
  "first": Boolean,
  "sort": {
    "sorted": Boolean,
    "unsorted": Boolean,
    "empty": Boolean
  },
  "numberOfElements": Integer,
  "size": Integer,
  "number": Integer
  "empty": Boolean
}

Create File

POST /api/bags/:bag_id/file

Create a single File for a Bag

Request Body
{
  "filename": String
  "size": Long,
  "fixity": String,
  "fixityAlgorithm": FixityAlgorithm,
  "bag": Long | Null
}
Response Body
{
  "id": Long,
  "filename": String,
  "size": Long,
  "fixities": [
    {
      "value": String,
      "algorithm": FixityAlgorithm,
      "createdAt": ISO-8601 DateTime at UTC-0
    }
  ],
  "bag": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0
}

Create Files

POST /api/bags/:bag_id/files

Request Body
FILENAME,SIZE,FIXITY_VALUE,FIXITY_ALGORITHM
String,Long,String,String
...

Download File List

GET /api/bags/:bag_id/download

Download a listing of Filenames associated with a Bag. As this is meant to be consumed as a non-paged resource, it returns text/plain instead of application/json. This allows for less processing by consumers as there is no json which needs to be parsed and the listing can be downloaded with a single call rather than retrieving each page for a Bag. It is expected that each line contains a filename terminated by a newline.

Response Body
String
String
...

Get Fixity For File

GET /api/bags/:bag_id/files/:file_id/fixity/:algorithm

Retrieve a single Fixity value associated with a File, identified by the algorithm used to calculate the Fixity

Response Body
{
  "id": Long
  "value": String,
  "algorithm": FixityAlgorithm,
  "file": File,
  "createdAt": ISO-8601 DateTime at UTC-0
}

List Fixities For File

GET /api/bags/:bag_id/files/:file_id/fixity

Retrieve a list of all Fixity values associated with a File. Not paginated.

Response Body
[
  {
    "id": Long
    "value": String,
    "algorithm": FixityAlgorithm,
    "file": File,
    "createdAt": ISO-8601 DateTime at UTC-0
  }, ...
]

Create Fixity For File

PUT /api/bags/:bag_id/files/:file_id/fixity

Create a Fixity record associated with a File

Request Body
{
  "algorithm": FixityAlgorithm,
  "value": String
}
Response Body
{
  "id": Long
  "value": String,
  "algorithm": FixityAlgorithm,
  "file": File,
  "createdAt": ISO-8601 DateTime at UTC-0
}

Token Operations

ACE Tokens are an important part of the lifecycle of Files in the Chronopolis Ingest process. Currently only single operations are facilitated, with batch operations being a future goal.

Get AceToken

GET /api/tokens/:token_id

Retrieve a single AceToken identified by its id

Response Body
{
  "id": Long,
  "bagId": Long,
  "round": Long,
  "proof": String,
  "imsHost": String,
  "filename": String,
  "algorithm": String,
  "imsService": String,
  "createDate": ISO-8601 DateTime at UTC-0
}

List AceTokens

Retrieve a pageable list of AceTokens held by the Ingest Server

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

bagId

Long

The bagId to query on

algorithm

String

The algorithm to filter on

filename

String

The filename to search for

Response Body
{
  "content": [
    {
      "id": Long,
      "bagId": Long,
      "round": Long,
      "proof": String,
      "imsHost": String,
      "filename": String,
      "algorithm": String,
      "imsService": String,
      "createDate": ISO-8601 DateTime at UTC-0
    }, ...
  ],
  "pageable": {
    "sort": {
      "sorted": Boolean,
      "unsorted": Boolean,
      "empty": Boolean
    },
    "pageSize": Integer,
    "pageNumber": Integer
    "offset": Integer
    "unpaged": Boolean,
    "paged": Boolean
  },
  "last": Boolean,
  "totalPages": Integer,
  "totalElements": Integer,
  "first": Boolean,
  "sort": {
    "sorted": Boolean,
    "unsorted": Boolean,
    "empty": Boolean
  },
  "numberOfElements": Integer,
  "size": Integer,
  "number": Integer,
  "empty": Boolean
}

Get AceToken For Bag

GET /api/bags/:bag_id/files/:file_id/token

Get a single AceToken associated with a File in a Bag

Response Body
{
  "id": Long,
  "bagId": Long,
  "round": Long,
  "proof": String,
  "imsHost": String,
  "filename": String,
  "algorithm": String,
  "imsService": String,
  "createDate": ISO-8601 DateTime at UTC-0
}

List AceTokens For Bag

GET /api/bags/:bag_id/tokens

Retrieve a pageable list of AceTokens which are associated with Files in a Bag

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

bagId

Long

The bagId to query on

algorithm

String

The algorithm to filter on

filename

String

The filename to search for

Response Body
{
  "content": [
    {
      "id": Long,
      "bagId": Long,
      "round": Long,
      "proof": String,
      "imsHost": String,
      "filename": String,
      "algorithm": String,
      "imsService": String,
      "createDate": ISO-8601 DateTime at UTC-0
    }, ...
  ],
  "pageable": {
    "sort": {
      "sorted": Boolean,
      "unsorted": Boolean,
      "empty": Boolean
    },
    "pageSize": Integer,
    "pageNumber": Integer
    "offset": Integer
    "unpaged": Boolean,
    "paged": Boolean
  },
  "last": Boolean,
  "totalPages": Integer,
  "totalElements": Integer,
  "first": Boolean,
  "sort": {
    "sorted": Boolean,
    "unsorted": Boolean,
    "empty": Boolean
  },
  "numberOfElements": Integer,
  "size": Integer,
  "number": Integer,
  "empty": Boolean
}

Create AceToken For Bag

POST /api/bags/:bag_id/tokens

Create an AceToken for a Bag

Request Body
{
  "bagId": Long,
  "round": Long,
  "createdAte": DateTime,
  "proof": String,
  "imsHost": String,
  "filename": String,
  "algorithm": String,
  "imsService": String
}
Response Body
{
  "id": Long,
  "bagId": Long,
  "round": Long,
  "proof": String,
  "imsHost": String,
  "filename": String,
  "algorithm": String,
  "imsService": String,
  "createDate": ISO-8601 DateTime at UTC-0
}

Create AceToken For File

POST /api/bags/:bag_id/files/:file_id/token

Create an AceToken for a File in a Bag

Request Body
{
  "bagId": Long,
  "round": Long,
  "createdAte": DateTime,
  "proof": String,
  "imsHost": String,
  "filename": String,
  "algorithm": String,
  "imsService": String
}
Response Body
{
  "id": Long,
  "bagId": Long,
  "round": Long,
  "proof": String,
  "imsHost": String,
  "filename": String,
  "algorithm": String,
  "imsService": String,
  "createDate": ISO-8601 DateTime at UTC-0
}

Bag Staging Operations

In order to transfer Bags throughout the Chronopolis Network, staging information needs to be added to the Ingest Server. Typically staging information for the Bag will be added first, followed by staging information for the ACE Token Store. This is from the requirement that the ACE Tokens need the Bag to exist as a resource in the Ingest Server before being generated.

When Replications pull from the staging storage, no order is required for operations, though the ACE Token Store will normally be pulled first.

Upon success of all Replications, the staging storage will be deactivated to reflect that the storage can be reclaimed.

This section uses the Bag Staging Type discriminator values

Get Bag Staging

GET /api/bags/:bag_id/storage/:type

Retrieve the active staging resource for a Bag identified by the given type

Response Body
{
  "active": Boolean,
  "size": Long,
  "region": Long
  "totalFiles": Long,
  "path": String,
  "fixities": [
    {
      "value": String,
      "algorithm": String,
      "createdAt": ISO-8601 DateTime at UTC-0
    }
  ]
}

Create Bag Staging

PUT /api/bags/:bag_id/storage/:type

Create a new staging resource for a Bag

Request Body
{
  "location": String,
  "validationFile": String,
  "storageRegion": Long,
  "totalFiles": Long,
  "size": Long,
  "storageUnit": StorageUnit
}
Response Body
{
  "active": Boolean,
  "size": Long,
  "region": Long
  "totalFiles": Long,
  "path": String,
  "fixities": [
    {
      "value": String,
      "algorithm": String,
      "createdAt": ISO-8601 DateTime at UTC-0
    }
  ]
}

Toggle Bag Staging

PUT /api/bags/:bag_id/storage/:type/active

Toggle the staging resource for a Bag indicating that it is no longer active

Response Body
{
  "active": Boolean,
  "size": Long,
  "region": Long
  "totalFiles": Long,
  "path": String,
  "fixities": [
    {
      "value": String,
      "algorithm": String,
      "createdAt": ISO-8601 DateTime at UTC-0
    }
  ]
}

Replication Operations

Replications are how data flow is controlled within Chronopolis. Each Replication is an action is to be taken on a single Bag.

This section uses the Replication Status enum

When Replications reach either a SUCCESS state or a FAILURE state, they become read only.

Get Replication

GET /api/replications/:id

Retrieve a single Replication

Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "status": ReplicationStatus,
  "bagLink": String,
  "tokenLink": String,
  "protocol": String,
  "receivedTagFixity": String | Null,
  "receivedTokenFixity": String | Null,
  "node": String,
  "bag": Bag
}

List Replications

GET /api/replications/

Retrieve a pageable list of Replications

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

node

String

Query on Replications belonging to a Node identified by its username

bag

String

Query on the Replications belonging to a Bag identified by its name

status

ReplicationStatus

Query on Replication by their ReplicationStatus

Response Body
{
  "content": [
    {
      "id": Long,
      "createdAt": ISO-8601 DateTime at UTC-0,
      "updatedAt": ISO-8601 DateTime at UTC-0,
      "status": ReplicationStatus,
      "bagLink": String,
      "tokenLink": String,
      "protocol": String,
      "receivedTagFixity": String,
      "receivedTokenFixity": String,
      "node": String,
      "bag": Bag
    }, ...
  ],
  "pageable": {
    "sort": {
      "sorted": Boolean,
      "unsorted": Boolean,
      "empty": Boolean
    },
    "pageSize": Integer,
    "pageNumber": Integer
    "offset": Integer
    "unpaged": Boolean,
    "paged": Boolean
  },
  "last": Boolean,
  "totalPages": Integer,
  "totalElements": Integer,
  "first": Boolean,
  "sort": {
    "sorted": Boolean,
    "unsorted": Boolean,
    "empty": Boolean
  },
  "numberOfElements": Integer,
  "size": Integer,
  "number": Integer
  "empty": Boolean
}

Create Replication

POST /api/replications/

Request that a Replication is made for a Bag to a Chronopolis Node

Request Body

{
  "bagId": Long,
  "nodeId": Long
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "status": ReplicationStatus,
  "bagLink": String,
  "tokenLink": String,
  "protocol": String,
  "receivedTagFixity": String | Null,
  "receivedTokenFixity": String | Null,
  "node": String,
  "bag": Bag
}

Update Replication

PUT /api/replications/:id

Update specific fields on a Replication in one operation

Request Body

{
  "status": ReplicationStatus,
  "receivedTagFixity": String | Null,
  "receivedTokenFixity": String | Null,
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "status": ReplicationStatus,
  "bagLink": String,
  "tokenLink": String,
  "protocol": String,
  "receivedTagFixity": String | Null,
  "receivedTokenFixity": String | Null,
  "node": String,
  "bag": Bag
}

Update Replication Status

PUT /api/replications/:id/status

Update the value for Replication::status

Request Body

{
  "status": ReplicationStatus
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "status": ReplicationStatus,
  "bagLink": String,
  "tokenLink": String,
  "protocol": String,
  "receivedTagFixity": String | Null,
  "receivedTokenFixity": String | Null,
  "node": String,
  "bag": Bag
}

Update Replication TokenStore Fixity

PUT /api/replications/:id/tokenstore

Update the value for Replication::receivedTokenFixity

Request Body

{
  "fixity": String
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "status": ReplicationStatus,
  "bagLink": String,
  "tokenLink": String,
  "protocol": String,
  "receivedTagFixity": String | Null,
  "receivedTokenFixity": String | Null,
  "node": String,
  "bag": Bag
}

Update Replication Tagmanifest Fixity

PUT /api/replications/:id/tagmanifest

Update the value for Replication::receivedTagFixity

Request Body

{
  "fixity": String
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "status": ReplicationStatus,
  "bagLink": String,
  "tokenLink": String,
  "protocol": String,
  "receivedTagFixity": String | Null,
  "receivedTokenFixity": String | Null,
  "node": String,
  "bag": Bag
}

Fail Replication

PUT /api/replications/:id/failure

Notify that a Replication has had a fatal error and cannot be finished

Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "status": ReplicationStatus,
  "bagLink": String,
  "tokenLink": String,
  "protocol": String,
  "receivedTagFixity": String | Null,
  "receivedTokenFixity": String | Null,
  "node": String,
  "bag": Bag
}

Repair Operations

In the event that data becomes corrupt at a Chronopolis Node, there are a set of actions which are taken in order to Repair the data. There are two ideas in these operations: the Repair itself, and the fulfillment of the repair. The Repair is requested by a Node and the fulfillment is handled by a separate Node.

There are three enum types associated with Repairs: FulfillmentType, AuditStatus, and RepairStatus

The FulfillmentType can be chosen based on what a fulfilling Node is comfortable exposing:

Implemented and Available
  • NODE_TO_NODE - Requires ssh keys to be exchanged between nodes so that an rsync can be run on the content. Currently stages data by creating symbolic links to each file requested for repair.

Not Implemented, Specification Available
  • INGEST - Pushes data up to the Ingest Server’s staging rather than transfer from the Node’s preservation storage.

  • ACE - Proxies data through the Node’s ACE Audit Manager.

This section uses the Fulfillment Type, Audit Status, and Repair Status enums

Get Repair

GET /api/repairs/:repair_id

Retrieve a single Repair by its id

Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String | Null,
  "type": FulfillmentType | Null,
  "credentials": AceStrategy | RsyncStrategy | Null
}

List Repairs

GET /api/repairs/

Retrieve a pageable list of Repairs

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

node

String

The Node::username who is requesting a Repair

fulfillingNode

String

The Node::username who is acting as a fulfilling Node

status

RepairStatus

The RepairStatus to query on

auditStatus

AuditStatus

The AuditStatus to query on

Response Body
{
  "content": [
    {
      "id": Long,
      "createdAt": ISO-8601 DateTime at UTC-0,
      "updatedAt": ISO-8601 DateTime at UTC-0,
      "cleaned": Boolean,
      "replaced": Boolean,
      "validated": Boolean,
      "audit": AuditStatus,
      "status": RepairStatus,
      "to": String,
      "requester": String,
      "depositor": String,
      "collection": String,
      "files": [
        String, ...
      ],
      "from": String | Null,
      "type": FulfillmentType | Null,
      "credentials": AceStrategy | RsyncStrategy | Null
    }, ...
  ],
  "pageable": {
    "sort": {
      "sorted": Boolean,
      "unsorted": Boolean,
      "empty": Boolean
    },
    "pageSize": Integer,
    "pageNumber": Integer
    "offset": Integer
    "unpaged": Boolean,
    "paged": Boolean
  },
  "last": Boolean,
  "totalPages": Integer,
  "totalElements": Integer,
  "first": Boolean,
  "sort": {
    "sorted": Boolean,
    "unsorted": Boolean,
    "empty": Boolean
  },
  "numberOfElements": Integer,
  "size": Integer,
  "number": Integer
  "empty": Boolean
}

Create Repair Request

POST /api/repairs

Create a Repair for a given data set

Request Body
{
  "to": String,
  "depostior": String,
  "collection": String,
  "files": [ String, ... ]
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ]
}

Fulfill a Repair

POST /api/repairs/:repair_id/fulfill

Offer to fulfill a Repair

Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String,
  "type": FulfillmentType | Null,
  "credentials": AceStrategy | RsyncStrategy | Null
}

Mark Repair as Ready

POST /api/repairs/:repair_id/ready

Update to mark that transfer of a Repair fulfillment can now be initiated

There are multiple ways that the transfer can happen, and as such this method can handle different request bodies

Request Body
Rsync Fulfillment
{
  "type": "NODE_TO_NODE",
  "link": String
}
ACE Fulfillment
{
  "type": "ACE",
  "apiKey": String,
  "url": String
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String,
  "type": FulfillmentType,
  "credentials": AceStrategy | RsyncStrategy
}

Mark Repair as Validated

PUT /api/repairs/:repair_id/validated

Set Repair::validated to true indicating that the transferred content was able to be validated according to the Repairing Node’s ACE Audit Manager.

Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String,
  "type": FulfillmentType,
  "credentials": AceStrategy | RsyncStrategy
}

Mark Repair as Replaced in Preservation Storage

PUT /api/repairs/:repair_id/replaced

Set Repair::replaced to true indicating that the transferred content has replaced the corrupt content in the Repairing Node’s preservation storage.

Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String,
  "type": FulfillmentType,
  "credentials": AceStrategy | RsyncStrategy
}

Update Repair Audit Status

PUT /api/repairs/:repair_id/audit

Set Repair::audit to the given value depending on the state of the audit for the Repairing Node’s ACE Audit Manager.

Request Body
{
  "status": AuditStatus
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String,
  "type": FulfillmentType,
  "credentials": AceStrategy | RsyncStrategy
}

Update Repair Cleaning Status

PUT /api/repairs/:repair_id/cleaned

Set Repair::cleaned to true indicating that the transferred content has been removed from the Repairing Node’s temporary storage.

Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String,
  "type": FulfillmentType,
  "credentials": AceStrategy | RsyncStrategy
}

Mark Repair as Complete

PUT /api/repairs/:repair_id/complete

Set Repair::status to RepairStatus::REPAIRED indicating that a Repair has finished successfully.

Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String,
  "type": FulfillmentType,
  "credentials": AceStrategy | RsyncStrategy
}

Update Repair Status

PUT /api/repairs/:repair_id/status

A general update endpoint to indicate a status change in the Repair. Can be used to reflect RepairStatus::FAILURE.

Request Body
{
  "status": RepairStatus
}
Response Body
{
  "id": Long,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "cleaned": Boolean,
  "replaced": Boolean,
  "validated": Boolean,
  "audit": AuditStatus,
  "status": RepairStatus,
  "to": String,
  "requester": String,
  "depositor": String,
  "collection": String,
  "files": [
    String, ...
  ],
  "from": String,
  "type": FulfillmentType,
  "credentials": AceStrategy | RsyncStrategy
}

Depositor Operations

Depositors are the entities which are pushing data to Chronopolis which is to be preserved. We provide a few operations for viewing and updating them as needed.

Get Depositor

GET /api/depositors/:namespace

Retrieve a single Depositor identified by their Depositor::namespace

Response Body
{
  "id": Long,
  "namespace": String,
  "sourceOrganization": String,
  "organizationAddress": String,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "replicatingNodes": [
    String,
    ...
  ],
  "contacts": [
    {
      "contactName": String,
      "contactEmail": String,
      "contactPhone": String,
    },...
  ]
}

List Depositor

GET /api/depositors/

Retrieve a pageable list of Depositors

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

namespace

String

The Depositor::namespace the query for

Response Body
{
  "content": [
    {
      "id": Long,
      "namespace": String,
      "sourceOrganization": String,
      "organizationAddress": String,
      "createdAt": ISO-8601 DateTime at UTC-0,
      "updatedAt": ISO-8601 DateTime at UTC-0,
      "replicatingNodes": [
        String,
        ...
      ],
      "contacts": [
        {
          "contactName": String,
          "contactEmail": String,
          "contactPhone": String,
        },...
    }, ...
  ],
  "pageable": {
    "sort": {
      "sorted": Boolean,
      "unsorted": Boolean,
      "empty": Boolean
    },
    "pageSize": Integer,
    "pageNumber": Integer
    "offset": Integer
    "unpaged": Boolean,
    "paged": Boolean
  },
  "last": Boolean,
  "totalPages": Integer,
  "totalElements": Integer,
  "first": Boolean,
  "sort": {
    "sorted": Boolean,
    "unsorted": Boolean,
    "empty": Boolean
  },
  "numberOfElements": Integer,
  "size": Integer,
  "number": Integer
  "empty": Boolean
}

Create Depositor

POST /api/depositors/

Create a Depositor

Request Body
{
  "namespace": String,
  "sourceOrganization": String | Null,
  "organizationAddress": String | Null,
  "contacts": [ DepositorContactCreate, ... ],
  "replicatingNodes": [ String, ...]
}
Response Body
{
  "id": Long,
  "namespace": String,
  "sourceOrganization": String,
  "organizationAddress": String,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "replicatingNodes": [
    String,
    ...
  ],
  "contacts": [
    {
      "contactName": String,
      "contactEmail": String,
      "contactPhone": String,
    },...
  ]
}

Create Depositor Contact

POST /api/depositors/:namespace/contacts

Create contact information for a Depositor

Request Body
{
  "contactName": String,
  "contactEmail": String,
  "contactPhone":
  {
     "number": String,
     "countryCode": String
  },
}
Response Body
{
  "contactName": String,
  "contactEmail": String,
  "contactPhone": String,
}

Delete Depositor Contact

DELETE /api/depositors/:namespace/contacts

Remove contact information for a Depositor

Response Body
{
  "id": Long,
  "namespace": String,
  "sourceOrganization": String,
  "organizationAddress": String,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "replicatingNodes": [
    String,
    ...
  ],
  "contacts": [
    {
      "contactName": String,
      "contactEmail": String,
      "contactPhone": String,
    },...
  ]
}

Create Depositor Distribution to Node

POST /api/depositors/:namespace/nodes/:username

Create a Distribution record that indicates a Depositor’s content should be transferred to a Chronopolis Node identified by Node::username

Response Body
{
  "id": Long,
  "namespace": String,
  "sourceOrganization": String,
  "organizationAddress": String,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "replicatingNodes": [
    String,
    ...
  ],
  "contacts": [
    {
      "contactName": String,
      "contactEmail": String,
      "contactPhone": String,
    },...
  ]
}

Delete Depositor Distribution to Node

DELETE /api/depositors/:namespace/nodes/:username

Remove a Distribution record for a Depositor identified by Node::username

Response Body
{
  "id": Long,
  "namespace": String,
  "sourceOrganization": String,
  "organizationAddress": String,
  "createdAt": ISO-8601 DateTime at UTC-0,
  "updatedAt": ISO-8601 DateTime at UTC-0,
  "replicatingNodes": [
    String,
    ...
  ],
  "contacts": [
    {
      "contactName": String,
      "contactEmail": String,
      "contactPhone": String,
    },...
  ]
}

Get Ingested Bag for Depositor

GET /api/depositors/:namespace/bags/:bag-name

Retrieve a single Bag a Depositor sent identified by Bag::name

Response Body

see BagOperations::getBag

List Ingested Bags for Depositor

GET /api/depositors/:namespace/bags

Retrieve a pageable list of Bags sent by a Depositor

see List Bags for Query Parameters and Response Body

StorageRegion Operations

StorageRegions identify spaces in Chronopolis where data can be staged for transfers and how data can be transferred

This section uses the Data Type, Storage Type, and Storage Unit enums

Get a StorageRegion

GET /api/storage/:region_id

Response Body
{
  "id": Long,
  "node": String,
  "note": String,
  "capacity": Long,
  "dataType": DataType,
  "storageType": StorageType,
  "replicationConfig": {
    "region": Long,
    "path": String,
    "server": String,
    "username": String
  }
}

List StorageRegions

GET /api/storage

Query Parameters
Parameter Type Description

page

Int

The page number to query

orderBy

String

The field to order on

dir

String

The order to retrieve results, ASC or DESC

type

StorageType

The StorageType to query for

name

String

Query for StorageRegions belonging to a Node based on the username

capacityLess

Long

Query for StorageRegions with a capacity less than the given parameter

capacityGreater

Long

Query for StorageRegions with a capacity greater than the given parameter

Response Body
{
  "content": [
    {
      "id": Long,
      "node": String,
      "note": String,
      "capacity": Long,
      "dataType": DataType,
      "storageType": StorageType,
      "replicationConfig": {
        "region": Long,
        "path": String,
        "server": String,
        "username": String
      }
    }, ...
  ],
  "pageable": {
    "sort": {
      "sorted": Boolean,
      "unsorted": Boolean,
      "empty": Boolean
    },
    "pageSize": Integer,
    "pageNumber": Integer
    "offset": Integer
    "paged": Boolean,
    "unpaged": Boolean
  },
  "last": Boolean,
  "totalPages": Integer,
  "totalElements": Integer,
  "first": Boolean,
  "sort": {
    "sorted": Boolean,
    "unsorted": Boolean,
    "empty": Boolean
  },
  "numberOfElements": Integer,
  "size": Integer,
  "number": Integer
  "empty": Boolean
}

Create a StorageRegion

POST /api/storage

Create a new StorageRegion. When issuing this call, the unit (StorageUnit) annotating the StorageRegion::capacity can be given. Possible values are B, KiB, MiB, GiB, TiB, and PiB.

Request Body
{
  "note": String | Null,
  "node": String,
  "capacity": Long,
  "dataType": DataType,
  "storageUnit": StorageUnit,
  "storageType": StorageType,
  "replicationPath": String,
  "replicationServer": String,
  "replicationUser": String
}
Response Body
{
  "id": Long,
  "node": String,
  "note": String,
  "capacity": Long,
  "dataType": DataType,
  "storageType": StorageType,
  "replicationConfig": {
    "region": Long,
    "path": String,
    "server": String,
    "username": String
  }
}

Version Operations

Get Version

GET /api/version

Retrieve the current version of the API

Response Body
{
  "version" : String
}