In order to distribute digital publications from multiple sources, a library needs to be able to easily harvest metadata and lend such publications to patrons.
This specification, Open Distribution to Libraries 1.0 (referenced as ODL in the rest of this specification) defines a standard way to:
This version:
Editors:
Participate:
This document is a draft of the 1.0 version of the ODL specification.
OPDS terms
This specification adopts terms defined in [OPDS]. Important terms used include:
http://opds-spec.org/acquisition
and refers to the Resource which holds the content of the described Publication or the Resource through which it may be acquired for any OPDS Catalog Entry. See the Sections Acquisition Relations and Acquiring Publications. They are serialized as OPDS Catalog Feed Documents.ODL terms
In addition this specification defines the following terms:
In order to provide compatibility with [OPDS], this specification introduces the odl
XML namespace: http://drafts.opds.io/odl-1.0#
.
The keywords must, must not, required, shall, shall not, should, should not, recommended, may, and optional in this document are to be interpreted as described in [RFC2119].
All sections of this specification are normative except where identified by the informative status label “This section is informative”. The application of informative status to sections and appendices applies to all child content and subsections they may contain.
All examples in this specification are informative.
Open Distribution to Libraries is based on the Open Publication Distribution System specification and fully compatible with both [OPDS] and [OPDS-2].
All of the information are distributed through an OPDS Feed.
If the ODL Feed is serialized using [OPDS]:
It must be a valid OPDS Acquisition Feed as defined in [OPDS] with one difference:
atom:summary
and an atom:content
it must include both in its Partial Catalog EntryIf the ODL Feed is serialized using [OPDS-2]:
publications
must either contain a licenses
subcollection or an Open-Access Acquisition Link (http://opds-spec.org/acquisition/open-access)publications
groups
, facets
or navigation
Licenses are serialized using:
odl:license
in [OPDS] where odl:license
is repeated for each License availablelicenses
in [OPDS-2] which contains one or more Full Collections (a Collection that contains both metadata
and links
)In [OPDS], both the description and the links associated to a License are listed directly inside odl:license
.
In [OPDS-2], the description of the License is expressed in metadata
while all interactions (License Info Document and Checkouts) are listed under links
.
A License must contain the following metadata:
OPDS 2.0 | OPDS 1.2 | Semantics | Format |
---|---|---|---|
identifier |
dcterms:identifier |
Unique identifier for the License | URI |
format |
dcterms:format |
Format of the publication associated to the License | MIME type |
created |
created |
Date and time when the License was issued | ISO 8601 |
A License should also contain the following metadata:
OPDS 2.0 | OPDS 1.2 | Semantics | Format |
---|---|---|---|
terms |
odl:terms |
Terms associated to the License | See Section 3.3 |
protection |
odl:protection |
Protection associated to the Publication associated to the License | See Section 3.4 |
Finally, a License may also contain the following metadata:
OPDS 2.0 | OPDS 1.2 | Semantics | Format |
---|---|---|---|
price |
opds:price |
Price at which the library acquired the License | As defined in [OPDS] and [OPDS-2] |
source |
dcterms:source |
Source of the license | URI |
The terms
element may contain the following elements:
OPDS 2.0 | OPDS 1.2 | Semantics | Format | Default Value |
---|---|---|---|---|
checkouts |
total_checkouts |
Number of Checkouts before a License expires | Integer | Unlimited |
expires |
expires |
Expiration date of the License | ISO 8601 | None |
concurrency |
concurrent_checkouts |
Number of concurrent Checkouts allowed | Integer | Unlimited |
length |
maximum_checkout_length |
Maximum length in time allowed for a single Checkout in seconds | Integer | Unlimited |
The protection
element may contain the following elements:
OPDS 2.0 | OPDS 1.2 | Semantics | Format | Default Value |
---|---|---|---|---|
format |
dcterms:format |
Format of the DRM used to protect the Publication | MIME type | None |
devices |
devices |
Number of devices allowed for a single Checkout | Integer | Unlimited |
copy |
copy |
Indicates if the protection allows the user to copy content from the Publication | Boolean | True |
print |
print |
Indicates if the protection allows the user to print content from the Publication | Boolean | True |
tts |
tts |
Indicates if the protection allows the user to use text to speech | Boolean | True |
Example 1: Simple license in OPDS 1.2
<odl:license>
<dcterms:identifier xsi:type="dcterms:URI">urn:uuid:f7847120-fc6f-11e3-8158-56847afe9799</dcterms:identifier>
<dcterms:format>application/epub+zip</dcterms:format>
<opds:price currencycode="USD">7.99</opds:price>
<created>2014-04-25T12:25:21+02:00</created>
<odl:terms>
<odl:total_checkouts>30</odl:total_checkouts>
<odl:expires>2016-04-25T12:25:21+02:00</odl:expires>
<odl:concurrent_checkouts>10</odl:concurrent_checkouts>
<odl:max_checkout_length>5097600</odl:max_checkout_length>
</odl:terms>
<odl:protection>
<dcterms:format>application/vnd.adobe.adept+xml</dcterms:format>
<odl:devices>6</odl:devices>
<odl:copy>false</odl:copy_paste>
<odl:print>false</odl:print>
<odl:tts>false</odl:tts>
</odl:protection>
<odl:tlink rel="http://opds-spec.org/acquisition/borrow"
href="http://www.example.com/get{?id,checkout_id,expires,patron_id,notification_url}"
type="application/vnd.readium.license.status.v1.0+json" />
<link rel="self"
href="http://www.example.com/status/294024"
type="application/vnd.odl.info+json" />
</odl:license>
Example 2: License in OPDS 2.0 with two DRM options available
"licenses": [
{
"metadata": {
"identifier": "urn:uuid:f7847120-fc6f-11e3-8158-56847afe9799",
"format": "application/epub+zip",
"price": {
"currency": "USD",
"value": 7.99
},
"created": "2014-04-25T12:25:21+02:00",
"terms": {
"checkouts": 30,
"expires": "2016-04-25T12:25:21+02:00",
"concurrency": 10,
"length": 5097600
},
"protection": {
"format": [
"application/vnd.adobe.adept+xml",
"application/vnd.readium.lcp.license.v1.0+json"
],
"devices": 6,
"copy": false,
"print": false,
"tts": false
}
},
"links": [
{
"rel": "http://opds-spec.org/acquisition/borrow",
"href": "http://www.example.com/get{?id,checkout_id,expires,patron_id,passphrase,hint,hint_url,notification_url}",
"type": "application/vnd.readium.license.status.v1.0+json",
"templated": true
},
{
"rel": "self",
"href": "http://www.example.com/status/294024",
"type": "application/vnd.odl.info+json"
}
]
}
]
In order to provide information about the current state of a License, this specification defines the License Info Document.
Each License in an ODL Feed must contain a link to a License Info Document where:
rel
value must be self
type
value must be application/vnd.odl.info+json
A License Info Document must:
application/vnd.odl.info+json
media type in its HTTP headersThe License Info Document must contain the following keys:
Key | Semantics | Format |
---|---|---|
identifier |
Unique identifier for the License | URI |
status |
Indicates the status of a license | preorder , available or unavailable |
checkouts |
Provides information about the availability of checkouts | Checkouts Object |
The Checkouts Object must have the following keys:
Key | Semantics | Format |
---|---|---|
left |
Total number of checkouts left for a License | Integer |
available |
Number of concurrent checkouts currently available | Integer |
active |
Contains one or more active loans associated to the License | One or more Loan Object |
The Loan Object must have the following keys:
Key | Semantics | Format |
---|---|---|
href |
Location of the LCP License Status Document associated to the loan | URI |
id |
Unique identifier for the loan | String |
patron_id |
Unique identifier for the patron | String |
expires |
Date and time for the expiration of the loan | ISO 8601 |
In addition, the License Info Document may also include the information available for a License in an ODL Feed:
Key | Semantics | Format |
---|---|---|
format |
Format of the publication associated to the License | MIME type |
created |
Date and time when the License was issued | ISO 8601 |
terms |
Terms associated to the License | See Section 3.3 |
protection |
Protection associated to the Publication associated to the License | See Section 3.4 |
price |
Price at which the library acquired the License | As defined in [OPDS-2] |
source |
Source of the license | URI |
Example 3: a License Info Document with 18 total remaining checkouts, 8 available checkouts and 2 active ones
{
"identifier": "3363f6c2-ed7d-11e3-b722-56847afe9799"
"status": "available",
"checkouts": {
"left": 18,
"available": 8,
"active": [
{
"href": "https://www.example.com/3363f6c2-ed7d-11e3-b722-56847afe9799?transaction_id=36563230-0ef4-4659-a70e-cd6dcd0aeb9e",
"patron_id": "f7847120-fc6f-11e3-8158-56847afe9799",
"expires": "2014-06-24T11: 47: 54Z",
"id": "36563230-0ef4-4659-a70e-cd6dcd0aeb9e"
},
{
"href": "https://www.example.com/3363f6c2-ed7d-11e3-b722-56847afe9799?transaction_id=36563230-0ef4-4659-a70e-cd6dcd0aeb9d",
"patron_id": "f7847120-fc6f-11e3-8158-56847afe9799",
"expires": "2014-06-24T11: 47: 54Z",
"id": "36563230-0ef4-4659-a70e-cd6dcd0aeb9d"
}
]
}
}
A Checkout Link is a URI template that returns a Readium License Status Document, through which a library can obtain a publication.
Each License in an ODL Feed must contain a Checkout Link where:
rel
value must be http://opds-spec.org/acquisition/borrow
type
value must be application/vnd.readium.license.status.v1.0+json
In order to check out a Publication, this specification introduces a new element based on the link
element in [RFC4287]: the tlink
element.
The tlink
element inherits the semantics and syntax of the link element with the following modification to section 4.2.7.1. The “href” Attribute:
“The “href” attribute contains the link’s IRI. atom:link elements must have an href attribute, whose value must be a IRI reference [RFC3987] or a IRI template [RFC6570].”
This specification defines a set of well-known parameters associated to the URI template of a Checkout Link.
A Checkout Link must have the following parameters:
Parameter | Semantics | Format |
---|---|---|
id |
Unique identifier for the License | String |
checkout_id |
Unique identifier for the Checkout | String |
patron_id |
Unique identifier for the patron | String |
A Checkout Link may also have the following parameters:
Parameter | Semantics | Format | Required if present? |
---|---|---|---|
expires |
Expiration date for the Checkout | ISO 8601 | Yes |
hint |
Hint displayed to the user when opening an LCP protected publication | String | Yes |
hint_url |
Hint URL available to the user when opening an LCP protected publication | URL | Yes |
notification_url |
URL where the library will be notified that the status of the Checkout changed | URL | No |
passphrase |
Hash of the passphrase that the patron will need to enter for an LCP protected publication | String | Yes |
Example 4: Checkout Link in OPDS 1.2
<odl:tlink rel="http://opds-spec.org/acquisition/borrow"
href="http://library_example.com/loan{?id,checkout_id,expires,patron_id,notification_url}"
type="application/vnd.readium.license.status.v1.0+json" />
Example 5: Checkout Link in OPDS 2.0
"links": [
{
"rel": "http://opds-spec.org/acquisition/borrow",
"href": "http://library_example.com/loan{?id,checkout_id,expires,patron_id,notification_url}",
"type": "application/vnd.readium.license.status.v1.0+json",
"templated": true
}
]
Expected Behavior
POST
request to the Checkout Link with all the required parameters.201
HTTP status code.id
and checkout_id
was created before, the server must return a 303
HTTP status code, with the Location
header pointing to the Readium License Status Document that was previously created.The Readium License Status Document returned by the server must contain at least two links:
self
relation, that points back to this LCP Status Documentlicense
relationFailure Modes
A server must respond with a Problem Details JSON Object as defined in [RFC7807] whenever a 4xx
or a 5xx
HTTP status code is sent back to the client.
This specification defines the following list of supported types:
Type | Description | HTTP Status Code |
---|---|---|
http://opds-spec.org/odl/error | Generic error when a specific type can’t be tied to the error. | 4xx 5xx |
http://opds-spec.org/odl/error/checkout/id | Incorrect or missing License identifier. | 400 |
http://opds-spec.org/odl/error/checkout/checkout_id | Incorrect or missing Checkout identifier. | 400 |
http://opds-spec.org/odl/error/checkout/patron_id | Incorrect or missing patron identifier. | 400 |
http://opds-spec.org/odl/error/checkout/expires | Incorrect or missing expiration date. | 400 |
http://opds-spec.org/odl/error/checkout/notification_url | Incorrect notification URL (usually means that it’s not a URL). | 400 |
http://opds-spec.org/odl/error/checkout/passphrase | Incorrect or missing passphrase. | 400 |
http://opds-spec.org/odl/error/checkout/hint | Incorrect or missing hint. | 400 |
http://opds-spec.org/odl/error/checkout/hint_url | Incorrect or missing URL hint. | 400 |
http://opds-spec.org/odl/error/checkout/expired | The License has expired. | 403 |
http://opds-spec.org/odl/error/checkout/unavailable | The License has reached its concurrent or total Checkouts limit. | 403 |
A client can get at anytime the status of a Checkout by doing an HTTP GET
request to the self
link included in the Readium License Status Document initially returned after checking out a Publication.
The Readium License Status Document contains a status
element and a timestamps
element that are both relevant to tracking changes.
Notifications should be sent for the following status changes of a checkout:
active
returned
cancelled
revoked
A notification may be sent for the following status change:
expired
In order to notify such changes, the source for the ODL feed must:
POST
request to the notification URI provided through the Checkout LinkThe minimal LCP Status Document must contain at least the following elements:
id
status
Example 6: Minimal Readium License Status Document used for a notification:
{
"id": "3c649cda-d8c5-4d48-bd80-85aff3fcb734",
"status": "returned"
}
A successful request must return a 204
HTTP status code, with no additional body content to the response.
If another HTTP status is returned, additional attempts to send a notification should be made.
In order to secure the ability to harvest Licenses and create Checkouts, an ODL server should use either Basic Authentication or a Bearer Token to limit the access to the ODL feed.
All interactions with an ODL server must use TLS 1.2 or later.