OverDrive APIs in the Real World
Here you'll find Amanda's story. She's a developer who would like to design an app for her library: The Common Local Library, or "CLL." She's already applied for OverDrive APIs and has been granted access to each one.
This story should give you an idea of how OverDrive APIs can be used in real world applications. It will show you how hypermedia links serve to guide you from one API to another, and how you can utilize that relationship to make your app work.
What does Amanda's app need to do?
- Enable users to browse the entire CLL digital collection.
- Allow users to search for specific titles.
- Get detailed metadata (title, author, format, etc.) for specific titles.
- Check to see whether a title is available for checkout.
Where does Amanda start?
First, Amanda needs to get the CLL’s account information. The library ID she was given is 1225, which she includes in the URL she needs to access the Library Account API:
https://api.overdrive.com/v1/libraries/1225
Note: If you need to know your library ID, contact support.
Getting an OAuth Access Token
Attempting to call an OverDrive API with a missing, invalid, or expired OAuth access token will result in a “401 Access Denied” response. Knowing this, Amanda obtains a valid access token by supplying her client key and client secret to OverDrive's OAuth endpoint.
Using Basic Authentication, she performs the following POST request to the OverDrive OAuth endpoint at https://oauth.overdrive.com/token.
Here's how Amanda makes the POST request:
- She combines her client key and client secret like this: clientKey:clientSecret.
- Then she uses her languages libraries to encode the combined secret and key using a Base64 algorithm.
- She applies the string to the “Authorization” header like this: Basic [Base64 string] (see the example below).
POST /token HTTP/1.1 Host: oauth.overdrive.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded;charset=UTF-8 grant_type=client_credentials
Because Amanda’s credentials are valid, the following response is returned:
{ "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"Bearer", "expires_in":3600, "scope":"LIB META SRCH AVAIL" }
Amanda extracts the “access_token” and “token_type” values from this response and includes them in all OverDrive API calls as part of the “Authorization” header as shown below:
GET /v1/libraries/1225 HTTP/1.1 Host: api.overdrive.com Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA User-Agent: CLL Browser X-Forwarded-For: (Client IP Address)
Amanda also includes the name of her app and the IP of the client using her app in the request header. This helps us better understand how our APIs are used so we can keep making them better.
The Library Account API response
When Amanda accesses the Library Account API with a valid OAuth token, she gets the following JSON response.
Note: All API responses are UTF-8 encoded.
{ "id": 1225, "name": "Common Community Consortium (OH)", "type": "Library", "links": { "self": { "href": "https://api.overdrive.com/v1/libraries/1225/accounts", "type": "application/vnd.overdrive.api+json" }, "products": { "href": "https://api.overdrive.com/v1/collections/L1BAAEAAA2i/products/", "type": "application/vnd.overdrive.api+json" }, "advantageAccounts": { "href": "https://api.overdrive.com/v1/libraries/1225/advantageAccounts", "type": "application/vnd.overdrive.api+json" } }, "formats": [ { "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "audiobook-mp3", "name": "OverDrive MP3 Audiobook" }] }
This provides several bits of very important information:
- A products link that returns a library's digital collection. This is the starting point for the Search API.
- An advantageAccounts link that returns a list of consortium libraries with Advantage accounts.
- A list of OverDrive formats supported by the library.
Since the CLL has Advantage titles, patrons have access to additional content that the library has purchased to supplement the consortium's digital collection. Amanda has to be sure that she is searching the library's full Advantage catalogue as well as its consortium titles.
Getting the Advantage products link
Amanda needs to use the link for advantageAccounts to get the right products link to search the CLL's Advantage collection. The hypermedia link for advantageAccounts was supplied in Library Account API response above.
Note: Each time an OverDrive API is accessed, a valid OAuth token must be used. If Amanda's last token has expired, or she does not include one when accessing any API, the request will fail.
https://api.overdrive.com/v1/libraries/1225/advantageAccounts
This returns a list of libraries that have advantage accounts in the Common Community Consortium.
{ "id": 1225, "links": { "self": { "href": "https://api.overdrive.com/v1/libraries/1225/advantageAccounts", "type": "application/vnd.overdrive.api+json" } }, "advantageAccounts": [{ "id": 3, "name": "The Other Side of Town Library", "type": "Library Advantage Account", "links": { "self": { "href": "https://api.overdrive.com/v1/libraries/1225/advantageAccounts/3", "type": "application/vnd.overdrive.api+json" }, "products": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAK8BAAA1x/products", "type": "application/vnd.overdrive.api+json" } }, "formats": [ { "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "ebook-overdrive", "name": "OverDrive Read" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook" }, { "id": "ebook-kindle", "name": "Kindle Book" }, { "id": "audiobook-mp3", "name": "OverDrive MP3 Audiobook" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook" }] }, { "id": 9, "name": "The Common Community Library", "type": "Library Advantage Account", "links": { "self": { "href": "https://api.overdrive.com/v1/libraries/1225/advantageAccounts/9", "type": "application/vnd.overdrive.api+json" }, "products": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products", "type": "application/vnd.overdrive.api+json" } }, "formats": [ { "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "ebook-overdrive", "name": "OverDrive Read" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook" }, { "id": "ebook-kindle", "name": "Kindle Book" }, { "id": "audiobook-mp3", "name": "OverDrive MP3 Audiobook" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook" }] }], "totalItems": 2 }
From the response, Amanda sees that the CLL is the second library on the list. Now she has the products link for the CLL's collection, which includes both Advantage and consortium titles.
Using Search to return a complete digital collection
The CLL wants its users to be able to browse through its entire digital collection, so Amanda needs a way to return a full list of titles. No problem. Using the products link she got from the response above, she can access the Search API.
https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products
This returns a complete digital collection since no parameters were specified. By default, results are limited to 25 titles per request.
{ "limit": 25, "offset": 0, "totalItems": 8230, "id": "L2B2gAAAKoBAAA1B", "products": [{ "id": "76c1b7d0-17f4-4c05-8397-c66c17411584", "mediaType": "eBook", "title": "The Adventures of Sherlock Holmes", "series": "Sherlock Holmes", "primaryCreator": { "role": "Author", "name": "Sir Arthur Conan Doyle" }, "formats": [{ "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook" }, { "id": "ebook-kindle", "name": "Kindle Book" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook" }], "images": { "thumbnail": { "href": "https://images.contentreserve.com/ImageType-200/2389-1/{76C1B7D0-17F4-4C05-8397-C66C17411584}Img200.jpg", "type": "image/jpeg" } }, "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584", "type": "application/vnd.overdrive.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/metadata", "type": "application/vnd.overdrive.api+json" }, "availability": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/availability", "type": "application/vnd.overdrive.api+json" } } }, { "id": "ee013a9b-53cc-45d2-95da-ec50360b8e80", "mediaType": "eBook", "title": "20,000 Leagues under the Sea", "series": "Voyages Extraordinaires", "primaryCreator": { "role": "Author", "name": "Jules Verne" }, "formats": [{ "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook" }], "images": { "thumbnail": { "href": "https://images.contentreserve.com/ImageType-200/2389-1/{EE013A9B-53CC-45D2-95DA-EC50360B8E80}Img200.jpg", "type": "image/jpeg" } }, "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/EE013A9B-53CC-45D2-95DA-EC50360B8E80", "type": "application/vnd.overdrive.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/EE013A9B-53CC-45D2-95DA-EC50360B8E80/metadata", "type": "application/vnd.overdrive.api+json" }, "availability": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/EE013A9B-53CC-45D2-95DA-EC50360B8E80/availability", "type": "application/vnd.overdrive.api+json" } } }, { "id": "76c1b7d0-17f4-4c05-8397-c66c17411584", "mediaType": "eBook", "title": "The Adventures of Sherlock Holmes", "series": "Sherlock Holmes", "primaryCreator": { "role": "Author", "name": "Sir Arthur Conan Doyle" }, "formats": [{ "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook" }, { "id": "ebook-kindle", "name": "Kindle Book" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook" }], "images": { "thumbnail": { "href": "https://images.contentreserve.com/ImageType-200/2389-1/{76C1B7D0-17F4-4C05-8397-C66C17411584}Img200.jpg", "type": "image/jpeg" } }, "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584", "type": "application/vnd.overdrive.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/metadata", "type": "application/vnd.overdrive.api+json" }, "availability": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/availability", "type": "application/vnd.overdrive.api+json" } } }, { "id": "ee013a9b-53cc-45d2-95da-ec50360b8e80", "mediaType": "eBook", "title": "20,000 Leagues under the Sea", "series": "Voyages Extraordinaires", "primaryCreator": { "role": "Author", "name": "Jules Verne" }, "formats": [{ "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook" }], "images": { "thumbnail": { "href": "https://images.contentreserve.com/ImageType-200/2389-1/{EE013A9B-53CC-45D2-95DA-EC50360B8E80}Img200.jpg", "type": "image/jpeg" } }, "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/EE013A9B-53CC-45D2-95DA-EC50360B8E80", "type": "application/vnd.overdrive.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/EE013A9B-53CC-45D2-95DA-EC50360B8E80/metadata", "type": "application/vnd.overdrive.api+json" }, "availability": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/EE013A9B-53CC-45D2-95DA-EC50360B8E80/availability", "type": "application/vnd.overdrive.api+json" } } }, { "id": "76c1b7d0-17f4-4c05-8397-c66c17411584", "mediaType": "eBook", "title": "The Adventures of Sherlock Holmes", "series": "Sherlock Holmes", "primaryCreator": { "role": "Author", "name": "Sir Arthur Conan Doyle" }, "formats": [{ "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook" }, { "id": "ebook-kindle", "name": "Kindle Book" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook" }], "images": { "thumbnail": { "href": "https://images.contentreserve.com/ImageType-200/2389-1/{76C1B7D0-17F4-4C05-8397-C66C17411584}Img200.jpg", "type": "image/jpeg" } }, "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584", "type": "application/vnd.overdrive.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/metadata", "type": "application/vnd.overdrive.api+json" }, "availability": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/availability", "type": "application/vnd.overdrive.api+json" } } }], "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products?limit=25&offset=0", "type": "application/vnd.overdrive.api+json" }, "first": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products?limit=25&offset=0", "type": "application/vnd.overdrive.api+json" }, "next": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products?limit=25&offset=25", "type": "application/vnd.overdrive.api+json" }, "last": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products?limit=25&offset=8225", "type": "application/vnd.overdrive.api+json" } } }
Now Amanda has all she needs to narrow search results, view metadata, and check library availability.
What if a user wants to search for a specific title?
Searching for specific titles or groups of titles is as simple as adding parameters to the Search API. If a user wants to search for The Adventures of Sherlock Holmes by Sir Arthur Conan Doyle, all Amanda has to do is add query parameters to the Search API like this:
https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products?q=The%20Adventures%20of%20Sherlock%20Holmes&limit=10&sort=creator:asc
This would search for The Adventures of Sherlock Holmes sorted by creator. Here's how that breaks down:
- q=The Adventures of Sherlock Holmes is a search that looks through title, creator, and keyword.
- limit=10 means that only 10 titles will be shown per page.
- sort=creator:asc means that the results will be alphabetically sorted by creator.
Note: You can see a full list of query parameters and their functions on the Search API page.
Here's the response:
{ "limit": 10, "offset": 0, "totalItems": 1, "id": "L2B2gAAAKoBAAA1B", "products": [{ "id": "76c1b7d0-17f4-4c05-8397-c66c17411584", "mediaType": "eBook", "title": "The Adventures of Sherlock Holmes", "series": "Sherlock Holmes", "primaryCreator": { "role": "Author", "name": "Sir Arthur Conan Doyle" }, "formats": [{ "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook" }, { "id": "ebook-kindle", "name": "Kindle Book" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook" }], "images": { "thumbnail": { "href": "https://images.contentreserve.com/ImageType-200/2389-1/{76C1B7D0-17F4-4C05-8397-C66C17411584}Img200.jpg", "type": "image/jpeg" } }, "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584", "type": "application/vnd.overdrive.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/metadata", "type": "application/vnd.overdrive.api+json" }, "availability": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/availability", "type": "application/vnd.overdrive.api+json" } } }], "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/?limit=20&offset=0&q=%22Adventures%20of%20Sherlock%20Holmes%22&formats=ebook-epub-open&sort=title:asc", "type": "application/vnd.overdrive.api+json" }, "first": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/?limit=20&offset=0&q=%22Adventures%20of%20Sherlock%20Holmes%22&formats=ebook-epub-open&sort=title:asc", "type": "application/vnd.overdrive.api+json" }, "last": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/?limit=20&offset=0&q=%22Adventures%20of%20Sherlock%20Holmes%22&formats=ebook-epub-open&sort=title:asc", "type": "application/vnd.overdrive.api+json" } } }
Accessing the Metadata API from the hypermedia link in the search results
Amanda wants her users to see detailed information on any title they select. With that in mind, she uses the metadata hypermedia link from the search results to access the Metadata API. Here is a metadata request for The Adventures of Sherlock Holmes:
https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/metadata
Here's the detailed response Amanda gets:
{ "id": "76c1b7d0-17f4-4c05-8397-c66c17411584", "mediaType": "eBook", "title": "The Adventures of Sherlock Holmes", "sortTitle": "Adventures of Sherlock Holmes", "series": "Sherlock Holmes", "publisher": "Duke Classics", "creators": [{ "role": "Author", "name": "Sir Arthur Conan Doyle", "fileAs": "Conan Doyle Sir Arthur" }], "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/metadata", "type": "application/vnd.overdrive.api+json" } }, "images": { "thumbnail": { "href": "https://images.contentreserve.com/ImageType-200/2389-1/{76C1B7D0-17F4-4C05-8397-C66C17411584}Img200.jpg", "type": "image/jpeg" }, "cover": { "href": "https://images.contentreserve.com/ImageType-100/2389-1/{76C1B7D0-17F4-4C05-8397-C66C17411584}Img100.jpg", "type": "image/jpeg" } }, "languages": [{ "code": "en", "name": "English" }], "isPublicDomain": false, "isPublicPerformanceAllowed": false, "shortDescription": "<p><i>The Adventures of Sherlock Holmes</i> collects Sir Arthur Conan Doyle's first twelve short stories about his famous London detective. It begins with the first meeting of Holmes and his sidekick Watson, who narrates the stories. Doyle was the first to employ the sidekick technique, thereby creating a character in just as much suspense and awe as his readership at the mental escapades of the erratic, terrifyingly intelligent Holmes.", "fullDescription": "<p><i>The Adventures of Sherlock Holmes</i> collects Sir Arthur Conan Doyle's first twelve short stories about his famous London detective. It begins with the first meeting of Holmes and his sidekick Watson, who narrates the stories. Doyle was the first to employ the sidekick technique, thereby creating a character in just as much suspense and awe as his readership at the mental escapades of the erratic, terrifyingly intelligent Holmes.", "starRating": 4.0, "popularity": 4592, "subjects": [{ "value": "Classic Literature" }, { "value": "Fiction" }, { "value": "Mystery" }], "formats": [{ "id": "ebook-pdf-adobe", "name": "Adobe PDF eBook", "fileName": "AdventuresofSherlockHolmes9781620115091", "fileSize": 1521697, "partCount": 0, "onSaleDate": "2/20/2012 12:00:00 AM" }, { "id": "ebook-epub-adobe", "name": "Adobe EPUB eBook", "fileName": "AdventuresofSherlockHolmes9781620115091", "fileSize": 383229, "partCount": 0, "onSaleDate": "2/20/2012 12:00:00 AM" }, { "id": "ebook-kindle", "name": "Kindle Book", "fileName": "AdventuresofSherlockHolmes9781620115091", "identifiers": [{ "type": "ASIN", "value": "B0031RS42A" }], "fileSize": 0, "partCount": 0, "onSaleDate": "2/20/2012 12:00:00 AM" }, { "id": "ebook-pdf-open", "name": "Open PDF eBook", "fileName": "AdventuresofSherlockHolmes9781620115091", "identifiers": [{ "type": "ASIN", "value": "B0031RS42A" }], "fileSize": 1520364, "partCount": 0, "onSaleDate": "2/20/2012 12:00:00 AM" }, { "id": "ebook-epub-open", "name": "Open EPUB eBook", "fileName": "AdventuresofSherlockHolmes9781620115091", "identifiers": [{ "type": "ASIN", "value": "B0031RS42A" }], "fileSize": 379267, "partCount": 0, "onSaleDate": "2/20/2012 12:00:00 AM" }] }
With the Metadata in hand, Amanda can pick and choose what she wants her users to see, giving as much or as little information as she needs.
The user has found a title and looked at the details. Now what?
Amanda wants to be able to check whether a title is available for checkout right from her app. She doesn’t want her users discovering titles they want to check out only to find that they are unavailable at the library. This is where the Library Availability API comes into play.
Using the availability hypermedia link from her search response, Amanda accesses the Availability API:
https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/availability
The response:
{ "id": "76c1b7d0-17f4-4c05-8397-c66c17411584", "links": { "self": { "href": "https://api.overdrive.com/v1/collections/L2B2gAAAKoBAAA1B/products/76c1b7d0-17f4-4c05-8397-c66c17411584/availability", "type": "application/vnd.overdrive.api+json" } }, "available": true, "copiesOwned": 10, "copiesAvailable": 8, "numberOfHolds": 0 }
The CLL owns 10 copies, has 8 available, and there are no holds. So the user can feel comfortable browsing to the library website for checkout.
More to come
This is only the beginning of Amanda's story. OverDrive is working on new APIs that will allow her (and you) to explore greater functionality. Stay tuned to see where Amanda goes from here.