Avalon API

A simple API for working with Avalon objects.

Authentication

All API methods are protected by token authentication. A specified token is passed through http header 'Avalon-Api-Key'. A matching token must be configured in in Avalon's database. Creating and viewing tokens can be done via rake tasks.  Every token is associated with an Avalon user. User sessions authenticated against an API token will assume the same authorization rights as the associated user.

$ rake avalon:token:generate username=archivist email=archivist1@example.com 37ebd7d86d406e925ba2da4315903440b2439f671dc58c2a36dc827e454d263fdcfd0bf8ad5cea7f5dce5516f2ffe63ee02debf6881b7b466a8600d321b0a01c $ rake avalon:token:list 37ebd7d86d406e925ba2da4315903440b2439f671dc58c2a36dc827e454d263fdcfd0bf8ad5cea7f5dce5516f2ffe63ee02debf6881b7b466a8600d321b0a01c|archivist $ rake avalon:token:revoke username=archivist Token `37ebd7d86d406e925ba2da4315903440b2439f671dc58c2a36dc827e454d263fdcfd0bf8ad5cea7f5dce5516f2ffe63ee02debf6881b7b466a8600d321b0a01c` (archivist) revoked.



Media Objects

GET /media_objects/:id.json

Retrieves a subset of the mods for the specified media object (parameter :include_structure specifies if structure should be included in response)

GET /media_objects.json

Retrieves a paged list of media_objects (parameters :page and :per_page specify page number and number per page for pagination)

POST /media_objects.json

Creates an media object

PUT /media_objects/:id.json

Updates an media object

DELETE /media_objects/:id.json

Deletes a media object



Parameters for POST and PUTS:

collection_id: id of owning admin collection (optional),

fields: mods converted to JSON hash. Required fields: title, date_issued

      title (* required),
      date_issued (* required),
      creator (multiple),
      alternative_title (multiple),
      translated_title (multiple),
      uniform_title (multiple),
      statement_of_responsibility,
      date_created,
      copyright_date,
      abstract,
      note (multiple): requires note_type from controlled vocabulary to be present also,
      format,
      resource_type (multiple),
      contributor (multiple),
      publisher (multiple),
      genre (multiple),
      subject (multiple),
      related_item_url (multiple): requires related_item_label to be present also,
      geographic_subject (multiple),
      temporal_subject (multiple),
      topical_subject (multiple),
      bibliographic_id,
      language (multiple),
      terms_of_use,
      table_of_contents (multiple),
      physical_description,
      other_identifier (multiple): requires other_identifier_type from controlled vocabulary to be present also,
      comment (multiple)

files: an array of masterfile hashes. Optional: label, structure, and captions.

      label (optional),
      id,
      title,
      file_location,
      file_checksum,
      file_size,
      duration,
      display_aspect_ratio,
      original_frame_size,
      file_format,
      poster_offset,
      thumbnail_offset,
      date_digitized,
      structure (optional): structure xml as a string,
      captions(optional): captions text from vtt or srt file as a string,
      captions_type (optional): required if captions are present,
      other_identifier (multiple),
      comment (multiple),
      workflow_name,
      date_digitized,
      files: an array of derivative hashes

            label,
            id,
            url,
            hls_url,
            duration,
            mime_type,
            audio_bitrate,
            audio_codec,
            video_bitrate,
            video_codec,
            width,
            height

import_bib_record (optional boolean):

If true, fields must include value for :bibliographic_id and may include value from controlled vocabulary for :bibliographic_id_label)
Bib import failure will result in a JSON response: {errors: ['Bib import failed', e.message]}, status: 422

replace_masterfiles (optional boolean):

Relevant only if the media object already exists and it has masterfiles. If true, existing masterfiles will be replaced by those sent. If false, sent masterfiles will be appended to existing list.

publish (optional boolean):

If true, mediaobject will automatically enter a published state with avalon_publisher='REST API'



Example Requests



GET /media_objects/:id.json
curl -H 'Avalon-Api-Key:abcdef123456' https://mallorn.dlib.indiana.edu/media_objects/1g05fb83r.json



Example Response
{ "id": "1g05fb83r", "title": "Test", "collection": "7.0 testing", "unit": "Default Unit", "main_contributors": [], "publication_date": null, "published_by": null, "published": false, "summary": null, "visibility": "private", "read_groups": [], "files": [ { id: "1c18df984", "workflow_name": "avalon", "percent_complete": "100.0", "status_code": "COMPLETED", "structure": null, "label": "", "thumbnail_offset": 2000, "poster_offset": 2000, "physical_description": null, "file_location": "/srv/avalon/Archiver_spool/avalon/1c18df984-SampleVideo.mp4", "file_size": "1055736", "duration": "5312", "date_digitized": "2019-12-10T18:33:41Z", "file_checksum": null, "file_format": "Moving image", "other_identifier": [], "captions": null, "captions_type": null, "comment": [], "display_aspect_ratio": "1.7777777777777777", "original_frame_size": "1280x720", "width": 1280, "height": 720, "files": [ { "label": "quality-medium", "id": "26d00ae1-44b9-4306-a310-158b3e39a7c5", "url": "rtmp://mallorn.dlib.indiana.edu:1935/avalon/mp4:ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-medium", "hls_url": "https://mallorn.dlib.indiana.edu:8980/avalon/ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-medium.mp4/index.m3u8", "duration": 5336, "mime_type": null, "audio_bitrate": 128078, "audio_codec": "mp4a-40-2", "video_bitrate": 1500000, "video_codec": "avc1", "width": "1280.0", "height": "720.0", "location": "rtmp://mallorn.dlib.indiana.edu:1935/avalon/mp4:ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-medium", "track_id": "12532-medium", "hls_track_id": null, "managed": false, "derivativeFile": "file:///srv/avalon/rtmp_streams/ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-medium.mp4" }, { "label": "quality-high", "id": "e87804de-916b-40f9-aa28-69b8ce6dbcb4", "url": "rtmp://mallorn.dlib.indiana.edu:1935/avalon/mp4:ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-high", "hls_url": "https://mallorn.dlib.indiana.edu:8980/avalon/ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-high.mp4/index.m3u8", "duration": 5336, "mime_type": null, "audio_bitrate": 192000, "audio_codec": "mp4a-40-2", "video_bitrate": 3000000, "video_codec": "avc1", "width": "1280.0", "height": "720.0", "location": "rtmp://mallorn.dlib.indiana.edu:1935/avalon/mp4:ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-high", "track_id": "12532-high", "hls_track_id": null, "managed": false, "derivativeFile": "file:///srv/avalon/rtmp_streams/ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-high.mp4" }, { "label": "quality-low", "id": "6cc0e00a-eaf4-4fb7-9be6-64772a5b258a", "url": "rtmp://mallorn.dlib.indiana.edu:1935/avalon/mp4:ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-low", "hls_url": "https://mallorn.dlib.indiana.edu:8980/avalon/ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-low.mp4/index.m3u8", "duration": 5336, "mime_type": null, "audio_bitrate": 128078, "audio_codec": "mp4a-40-2", "video_bitrate": 500000, "video_codec": "avc1", "width": "852.0", "height": "480.0", "location": "rtmp://mallorn.dlib.indiana.edu:1935/avalon/mp4:ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-low", "track_id": "12532-low", "hls_track_id": null, "managed": false, "derivativeFile": "file:///srv/avalon/rtmp_streams/ececa279-0217-45b4-92fb-daf49d552f33/outputs/SampleVideo-low.mp4" } ] } ], "fields": { "duration": "5312", "avalon_resource_type": [ "moving image" ], "avalon_publisher": null, "avalon_uploader": "archivist1@example.com", "identifier": [], "title": "Lease Test", "alternative_title": [], "translated_title": [], "uniform_title": [], "statement_of_responsibility": null, "creator": [], "date_created": null, "date_issued": "2020", "copyright_date": null, "abstract": null, "format": [ "video/mp4" ], "resource_type": [], "contributor": [], "publisher": [], "genre": [], "subject": [], "geographic_subject": [], "temporal_subject": [], "topical_subject": [], "terms_of_use": null, "table_of_contents": [], "physical_description": [], "record_identifier": [ "http://127.0.0.1:8984/fedora4/rest/1g/05/fb/83/1g05fb83r" ], "comment": [], "bibliographic_id": null, "bibliographic_id_label": null, "note": null, "note_type": null, "language": null, "related_item_url": null, "related_item_label": null, "other_identifier": null, "other_identifier_type": null, "rights_statement": null } }



GET /media_objects.json



Example Response



POST /media_objects.json



Example Request Data (data.json)



Example Response



PUT /media_objects/:id.json



Example Request Data (data.json)



Example Response



DELETE /media_objects/:id.json



Example Response



Admin Collection


GET /admin/collections.json

Retrieves a paginated list of all collections (parameters :page and :per_page specify page number and number per page for pagination)

GET /admin/collections/:id.json

Retrieves information on the specified collection

GET /admin/collections/:id/items.json

Retrieves a paginated list of all items in the specified collection (parameters :page and :per_page specify page number and number per page for pagination)

POST /admin/collections.json

Creates a collection

PUT /admin/collections/:id.json

Updates a collection



Parameters for POST and PUT:

admin_collection: 

      name: collection name, 
      description (optional): collection description, 
      unit: collection unit from controlled vocabulary, 
      managers: array of Avalon user ids or emails



GET /admin/collections.json



Example Response



GET /admin/collections/:id.json



Example Response



GET /admin/collections/:id/items.json



Example Response



POST /admin/collections.json



Example Request Data (data.json)



Example Response



PUT /admin/collections/:id.json



Example Request Data (data.json)



Example Response



Units

In Avalon, units are part of a controlled vocabulary. To add a new unit, a call to the vocabulary is required.

GET /vocabulary.json

Retrieves a hash of avalon controlled vocabularies, { units: [ 'Default Unit' , ...], ... }

GET /vocabulary/:vocab.json

Retrieves values contained in specified controlled vocabulary

POST /vocabulary/:vocab.json

Updates specified vocab by adding the value contained in the :entry parameter 



GET /vocabulary.json



Example Response



GET /vocabulary/:vocab.json



Example Response



POST /vocabulary/:vocab.json



Example Request Data (data.json)



Example Response

 

Supplemental Files

When uploading binary content you should provide the mime type in the curl request like in the examples. This attribute should be optional, but some flaky/weird behavior may result in the SupplementalFile content type not always being saved properly unless the type=mimetype attribute is included with the file in the curl request. Required mime types for captions: text/vtt or text/srt.

POST /master_files/#{fedora_id}/supplemental_files: Add new supplemental file to masterfile

PUT /master_files/#{fedora_id}//supplemental_files/#{id}: replace existing supplemental file with a new binary file

GET /master_files/#{fedora_id}//supplemental_files/#{id}.json: Get data on supplemental file

GET /master_files/#{fedora_id}//supplemental_files/#{id}.json

PUT /master_files/#{fedora_id}//supplemental_files/#{id}.json: Update data on supplemental file

PUT /master_files/#{fedora_id}//supplemental_files/#{id}.json

GET /master_files/#{id}/supplemental_files.json: Get listing of supplemental files on masterfile

GET /master_files/ns064602j/supplemental_files.json
Returns an array of supplemental files

Request: Delete supplemental file

DELETE /master_files/#{fedora_id}//supplemental_files/#{id}
Deletes a supplemental file from the masterfile

Examples

Request: Add new supplemental file to masterfile

Create with file and metadata:

Create with file and inline metadata:

Create with just file:

Create with just metadata:

Create with just metadata inline:

Response:
{ "id": :supplemental_file_id }

Request: replace existing supplemental file with a new binary file

Update attached file:

Response:
{"id": :supplemental_file_id}

Request: Get data on supplemental file

Response:

Request: Update data on supplemental file

Updating metadata requires ALL existing fields except language to be included in the payload. Any existing non-language metadata field that is left out of the payload will be removed.

Update metadata:

Payload file:

Update metadata inline:

Response:
{"id": :supplemental_file_id}

Request: Get listing of supplemental files on masterfile

Returns an array of supplemental files

Paginated:

Returns array containing per_page results:

Request: Delete supplemental file

Deletes a supplemental file from the masterfile

Response Codes


Code

Description

Code

Description

200

Okay. For GET, the relevant JSON will be contained in response body. For PUTS and POST response body will contain id of created/updated item.

201

<Not used> Created

202

<Not used> Accepted, Queued

400

Bad request

401

Auth Failure. No token present in request header 'Avalon-Api-Key'

403

Forbidden. Invalid token in request header 'Avalon-Api-Key'

404

Resource Not Found. If object is not found for requested id.

405

<Not used> Method Prohibited

409

<Not used> Conflict/Other Error. Conflict ex: id in use

422

Processing failed. Response body will contain JSON hash with :errors key pointing to a list of error message strings.



Version History



Version

Date

Description

Version

Date

Description

0.1

13 October 2015

Initial Draft

0.2

16 December 2015

API as implemented

0.3
(Avalon 7.0)

03 January 2020

Authorization scheme enhanced
status_code, percent_complete, percent_succeeded, and percent_failed fields removed from Media Object parameters

0.4
(Avalon 7.1)

26 March 2020

MediaObject - add masterfile ids, derivative ids are actual ids instead of track ids now, structure can be inlined with query param
Collection items are proper JSON instead of JSON strings