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:
- distribute metadata about a publication
- provide the rights and terms associated to each license that the library acquired
- check the status of each license
- lend a digital publication
- check the status of that loan
This version:
Editors:
- Hadrien Gardeur
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:
- Acquisition Feed
- An Atom Feed whose Atom Entries are exclusively OPDS Catalog Entries.
- Acquisition Link
- An atom:link element with a relation that begins with
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. - Complete Catalog Entry
- An OPDS Catalog Entry that includes all known metadata about the described Publication and is referenced by a Partial Catalog Entry.
- Navigation Feed
- An Atom Feed whose Atom Entries are not OPDS Catalog Entries but instead links to other Navigation Feeds, Acquisition Feeds, or other Resources to establish a hierarchical, browsable presentation of the OPDS Catalog.
- OPDS Catalog Entry
- An Atom Entry that provides a representation of an available Publication and includes an Acquisition Link. They are serialized as OPDS Catalog Entry Documents.
- Partial Catalog Entry
- An OPDS Catalog Entry that includes the minimal required metadata about the described Publication but no other metadata and links to the Complete Catalog Entry.
- Publication
- An electronic document, typically available as a single file. OPDS Catalogs are agnostic about the particular format of Publications.
ODL terms
In addition this specification defines the following terms:
- Checkout Link
- A URI template from which a library can generate a loan for a patron.
- License
- A set of terms and rights and a Checkout Link from which a loan can be created.
- License Info Document
- A JSON document providing additional information about the current status of a license.
- ODL Feed
- An OPDS Feed from which a library can harvest metadata, copies and links.
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:
- the [OPDS] specification states that: "Each OPDS Catalog Entry Document must include at least one Acquisition Link, which is an atom:link element with a relation that begins "http://opds-spec.org/acquisition"."
- in the context of an Open Distribution to Libraries Feed this is changed to: "Each OPDS Catalog Entry Document must include at least one Open-Access Acquisition Link (http://opds-spec.org/acquisition/open-access) or a License."
-
In the case where an Acquisition Entry has both an
atom:summary
and anatom:content
it must include both in its Partial Catalog Entry -
If an OPDS Catalog Entry Document has a Partial Catalog Entry it should contain as much metadata as possible and assume that not all clients will access the Complete Catalog Entry
If the ODL Feed is serialized using [OPDS-2]:
- It must be a valid OPDS Feed as defined in [OPDS-2] with one difference:
- The requirement for the presence of an Acquisition Link is relaxed
- Instead, each Publication listed in
publications
must either contain alicenses
subcollection or an Open-Access Acquisition Link (http://opds-spec.org/acquisition/open-access)
- It must contain
publications
- It must not contain
groups
,facets
ornavigation
Licenses are serialized using:
odl:license
in [OPDS] whereodl:license
is repeated for each License availablelicenses
in [OPDS-2] which contains one or more Full Collections (a Collection that contains bothmetadata
andlinks
)
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:
- its
rel
value must beself
- its
type
value must beapplication/vnd.odl.info+json
A License Info Document must:
- be a valid [JSON] document
- return the
application/vnd.odl.info+json
media type in its HTTP headers
The 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:
- its
rel
value must behttp://opds-spec.org/acquisition/borrow
- its
type
value must beapplication/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
- In order to create a Checkout, an ODL client must send a
POST
request to the Checkout Link with all the required parameters. - In the case of a successful interaction with a Checkout Link, the server must return a valid Readium License Status Document as defined in [LSD] with a
201
HTTP status code. - If a Checkout with the same
id
andcheckout_id
was created before, the server must return a303
HTTP status code, with theLocation
header pointing to the Readium License Status Document that was previously created.
The server must not update the Checkout with the new parameters sent by the client in this case.
The Readium License Status Document returned by the server must contain at least two links:
- a link identified by the
self
relation, that points back to this LCP Status Document - at least one link to acquire the Checkout's license file, identified by the
license
relation
Failure 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:
- send a
POST
request to the notification URI provided through the Checkout Link - include a minimal Readium License Status Document in the body of the request
The 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.
- [JSON] The application/json Media Type for JavaScript Object Notation (JSON).
- [LSD] Readium License Status Document.
- [OPDS] OPDS Catalog 1.2
- [OPDS-2] OPDS Catalog 2.0
- [RFC2119] Key words for use in RFCs to Indicate Requirement Levels.
- [RFC3987] Internationalized Resource Identifiers (IRIs).
- [RFC4287] The Atom Syndication Format.
- [RFC6570] URI Template.
- [RFC7807] Problem Details for HTTP APIs.
- [URI-Template] URI Template.