Holds API
The Holds API is used to manage and place holds for a specific patron.
Note: The examples below show our production API URL. If you're using our integration environment, use https://integration-patron.api.overdrive.com. For more information on the integration environment, please see our Getting started guide.
Using the Holds API
Using POST, GET, and DELETE commands, you can use the Holds API to retrieve a list of a user's holds, place a hold on a user's behalf, or remove an existing hold.
Available endpoint functions
- Place a hold: Use a POST request to the holds endpoint to place holds on behalf of a patron.
- GET patron holds: Make this request to list a patron's current holds or find a specific held title.
- Update a hold: Use a PUT request to update the patron's email address for a specific hold.
- Suspend a hold: Use a POST request to suspend a hold that a patron has placed on a title.
- Remove a hold: Use a DELETE request to remove a specific hold from a patron's account.
Place a hold (POST)
To place a hold, make a POST request to the /v1/patrons/me/holds endpoint with the following fields:
Field | Explanation |
---|---|
id Required |
The title's unique identifier. Can be either the title's reserveId or crossRefId. |
emailAddress Required |
The patron's email address, where they'll be notified when the title is available to borrow. |
ignoreHoldEmail Optional |
When set to true, a patron will not need to include an emailAddress to place a title on hold (and the parameter will not need to be passed in the POST request). |
You may want to use ignoreHoldEmail if your website or app needs an option for COPPA compliance. If this is the case, you won't have to supply an email address in the POST request, but you'll still be able to place the title on hold for the user.
Here's an example of a simple holds request:
POST https://patron.api.overdrive.com/v1/patrons/me/holds User-Agent: {Your application} Authorization: Bearer {OAuth patron access token} Content-Type: application/json; charset=utf-8 Host: patron.api.overdrive.com Content-Length: 178 Expect: 100-continue { "fields": [ { "name": "id", "value": "0D85564B-A4B3-43D5-875D-1DF3CA06AE65" }, { "name": "emailAddress", "value": "YourEmailHere@overdrive.com" } ] }
When you've successfully placed a hold, you'll get a POST response that includes specific hold information for the title, which looks something like this:
201 Created Pragma: no-cache X-Frame-Options: deny Content-Length: 694 Cache-Control: no-cache Content-Type: application/json; charset=utf-8 Date: Mon, 03 Jan 2022 17:22:16 GMT Expires: -1 Location: https://patron.api.overdrive.com/v1/patrons/me/holds/0D85564B-A4B3-43D5-875D-1DF3CA06AE65 { "reserveId": "0D85564B-A4B3-43D5-875D-1DF3CA06AE65", "crossRefId": 25475, "emailAddress": "YourEmailHere@overdrive.com", "holdListPosition": 1, "numberOfHolds": 1, "holdPlacedDate": "2013-09-27T13:22:17.087", "links": { "self": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/0D85564B-A4B3-43D5-875D-1DF3CA06AE65", "type": "application/vnd.overdrive.content.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/P1BPg0AAA24/products/0D85564B-A4B3-43D5-875D-1DF3CA06AE65/metadata", "type": "application/vnd.overdrive.api+json" } }, "actions": { "removeHold": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/0D85564B-A4B3-43D5-875D-1DF3CA06AE65", "method": "delete" } } }
GET a list of a patron's holds
Send a GET command to the holds endpoint to get a list of current holds on a patron's account as shown below.
GET https://patron.api.overdrive.com/v1/patrons/me/holds User-Agent: {Your application} Authorization: Bearer {OAuth patron access token} Host: patron.api.overdrive.com Connection: Keep-Alive
This GET response includes a list of titles that the authenticated user currently has on hold from his or her library.
200 OK Pragma: no-cache X-Frame-Options: deny Content-Length: 2854 Cache-Control: no-cache Content-Type: application/json; charset=utf-8 Date: Mon, 03 Jan 2022 20:11:14 GMT Expires: -1 { "totalItems": 2, "holds": [ { "reserveId": "AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD", "crossRefId": 217936, "emailAddress": "yourEmailHere@overdrive.com", "holdListPosition": 2, "numberOfHolds": 2, "holdSuspension": { "suspensionType": "indefinite", "numberOfDays": 0 }, "holdPlacedDate": "2021-12-31T11:49:39Z", "links": { "self": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD", "type": "application/vnd.overdrive.circulation.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/v1P2BAwAAAMMEAAA18/products/AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD/metadata", "type": "application/vnd.overdrive.api+json" } }, "actions": { "editHold": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD", "type": "application/vnd.overdrive.circulation.api+json", "method": "put", "fields": [ { "name": "emailAddress", "type": "text", "optional": true } ] }, "removeHold": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD", "method": "delete" }, "addSuspension": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD/suspension", "method": "post", "fields": [ { "name": "suspensionType", "type": "text", "value": "", "options": [ "indefinite", "limited" ], "optional": false }, { "name": "numberOfDays", "type": "number", "value": "", "optional": true } ] }, "releaseSuspension": { "href": "https://patron.api.overdrive.com.oddev/v1/patrons/me/holds/AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD/suspension", "method": "delete" } } }, { "reserveId": "622708F6-78D7-453A-A7C5-3FE6853F3167", "crossRefId": 789876, "emailAddress": "yourEmailHere@overdrive.com", "holdListPosition": 1, "numberOfHolds": 1, "holdPlacedDate": "2021-07-14T10:44:35Z", "holdExpires": "2022-07-16T14:49:48Z", "links": { "self": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/622708F6-78D7-453A-A7C5-3FE6853F3167", "type": "application/vnd.overdrive.circulation.api+json" }, "metadata": { "href": "https://api.overdrive.com/v1/collections/v1P2BAwAAAMMEAAA18/products/622708F6-78D7-453A-A7C5-3FE6853F3167/metadata", "type": "application/vnd.overdrive.api+json" } }, "actions": { "removeHold": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/622708F6-78D7-453A-A7C5-3FE6853F3167", "method": "delete" }, "checkout": { "href": "https://patron.api.overdrive.com/v1/patrons/me/checkouts", "type": "application/vnd.overdrive.circulation.api+json", "method": "post", "fields": [ { "name": "reserveId", "type": "text", "value": "622708F6-78D7-453A-A7C5-3FE6853F3167" }, { "name": "formatType", "type": "text", "value": "", "options": [ "ebook-overdrive", "ebook-kindle" ], "optional": true } ] } } } ], "links": { "self": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds", "type": "application/vnd.overdrive.circulation.api+json" } } }
Take special note of the holdListPosition and numberOfHolds values. In the first title listed in the response above, the holdListPosition is "2." The numberOfHolds is also "2." That means this user is the 2nd person in line for the title, and there are a total of two people who have the title on hold.
The second title in the example above is ready to borrow because the holdListPosition is "1" and checkout appears within the list of available actions, letting you know that the title can be checked out.
Update a hold (PUT)
You can update a user's emailAddress for a specific hold by sending a PUT request to the holds endpoint. You'll need to include the id from the original hold and the new emailAddress.
Two quick notes:
- You won't be able to change the ignoreHoldEmail value after it's set in the original POST request.
- Once the title on hold becomes available to check out, you won't be able to update it using a PUT request.
Here's an example of what your request may look like if you wanted to update a user's email address:
PUT https://patron.api.overdrive.com/v1/patrons/me/holds/AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD Content-Type: application/json Authorization: Bearer {OAuth patron access token} Host: patron.api.overdrive.com Content-Length: 428 { "fields": [ { "name": "id", "value": "AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD" }, { "name": "emailAddress", "value": "newEmailAddress@overdrive.com" }, ] }
If your request was successful, you'll be returned a simple 204 NoContent response:
204 NoContent Pragma: no-cache X-Frame-Options: deny Cache-Control: no-cache Date: Wed, 05 Jan 2022 13:41:15 GMT Expires: -1
Suspending a hold (POST)
To suspend a hold on a title, make a POST request that includes the id (reserveId or crossRefId), emailAddress, and suspensionType. If you're defining a "limited" suspension, you'll also need to include a duration for the numberOfDays value.
Note: Suspending a hold is useful for end users that want some control over when a title will become available for them to borrow. It's like waiting in line at the grocery store until you get to the front and then holding your place until you're ready while letting the people behind you go past to check out.
In your POST request, emailAddress is the email address that was originally used to place the hold. There are also two types of suspensions (suspensionType): "indefinite" and "limited." The URL must include the id for the title that's on hold.
Here's an example of an indefinite suspension POST request:
POST: https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584/suspension User-Agent:{Your application} Authorization: Bearer {OAuth patron access token} Content-Type: application/json; charset=utf-8 Host: patron.api.overdrive.com Content-Length: 114 Expect: 100-continue { "fields": [ { "name": "emailAddress", "value": "YourEmailHere@overdrive.com" }, { "name": "suspensionType", "value": "indefinite" } ] }
Note the "indefinite" value for suspensionType. This means the suspension won't expire. Instead, it must be removed for the title to become available for the user. The response returned from a successful indefinite suspension request looks like this:
201 CREATED Pragma: no-cache X-Frame-Options: deny Content-Length: 736 Cache-Control: no-cache Content-Type: application/json; charset=utf-8 Date: Mon, 03 Jan 2022 13:50:29 GMT Expires: -1 { "reserveId": "76C1B7D0-17F4-4C05-8397-C66C17411584", "crossRefId": 784864, "emailAddress": "YourEmailHere@overdrive.com", "holdListPosition": 2, "numberOfHolds": 2, "holdSuspension": { "suspensionType": "indefinite", "numberOfDays": 0 }, "holdPlacedDate": "2021-12-02T09:49:48Z", "links": { "self": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584", "type": "application/vnd.overdrive.circulation.api+json" } }, "actions": { "removeHold": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584", "method": "delete" }, "releaseSuspension": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584/suspension", "method": "delete" } } }
If you want to suspend a hold for a specific amount of time, define numberOfDays and set the suspensionType to "limited" as shown in this example:
POST: https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584/suspension User-Agent:{Your application} Authorization: Bearer {OAuth patron access token} Content-Type: application/json; charset=utf-8 Host: patron.api.overdrive.com Content-Length: 147 Expect: 100-continue { "fields": [ { "name": "emailAddress", "value": "YourEmailHere@overdrive.com" }, { "name": "suspensionType", "value": "limited" }, { "name": "numberOfDays", "value": "2" } ] }
The numberOfDays field has a value of "2," which means this POST will put a suspension on the hold for two days. Here's an example of a successful response:
201 Created Pragma: no-cache X-Frame-Options: deny Content-Length: 733 Cache-Control: no-cache Content-Type: application/json; charset=utf-8 Date: Mon, 03 Jan 2022 13:50:23 GMT Expires: -1 { "reserveId": "76C1B7D0-17F4-4C05-8397-C66C17411584", "crossRefId": 784864, "emailAddress": "YourEmailHere@overdrive.com", "holdListPosition": 2, "numberOfHolds": 2, "holdSuspension": { "suspensionType": "limited", "numberOfDays": 2 }, "holdPlacedDate": "2021-12-02T09:49:48Z", "links": { "self": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584", "type": "application/vnd.overdrive.circulation.api+json" } }, "actions": { "removeHold": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584", "method": "delete" }, "releaseSuspension": { "href": "https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584/suspension", "method": "delete" } } }
Updating a suspended hold (PUT)
If you need to change any value for a suspended hold, you can do so by sending a PUT request to the holds suspension endpoint. Here's how you'll structure the URL:
https://patron.api.overdrive.com/v1/patrons/me/holds/{id}/suspension
The id in the URL is the same ID as the original hold request (either a reserveId or crossRefId).
Like the original suspension POST, you'll need to provide all three fields (emailAddress, suspensionType, and numberOfDays) in this PUT request.
In this example request, we're updating both the emailAddress and numberOfDays fields from the example above:
PUT https://patron.api.overdrive.com/v1/patrons/me/holds/AEC21DDE-BF3B-422A-B0EF-1B9D1D146FFD/suspension User-Agent: {Your application} Content-Type: application/json Authorization: Bearer {OAuth patron access token} Host: patron.api.overdrive.com Content-Length: 312 { "fields": [ { "name": "emailAddress", "value": "newEmailAddress@overdrive.com" }, { "name": "suspensionType", "value": "limited" }, { "name": "numberOfDays", "value": "5" } ] }
When you've successfully updated your suspended hold, you'll see a response like this:
204 NoContent Pragma: no-cache X-Frame-Options: deny Cache-Control: no-cache Date: Wed, 05 Jan 2022 13:39:44 GMT Expires: -1
Deleting a suspended hold
If you want to remove a hold suspension, you can do it with a DELETE request sent to the suspension endpoint. This will not remove the hold, only the hold suspension. Users will maintain their place in the holds waiting list once the suspension is removed.
Here's an example of a hold suspension DELETE request:
DELETE: https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584/suspension User-Agent:{Your application} Authorization: Bearer {OAuth patron access token} Content-Type: application/json; charset=utf-8 Host: integration-patron.api.overdrive.com
A successful DELETE request will return a response like this:
204 NoContent Pragma: no-cache X-Frame-Options: deny Cache-Control: no-cache Date: Wed, 02 Jul 2014 13:50:37 GMT Expires: -1
Removing a hold (DELETE)
Make a DELETE request to the holds endpoint to completely remove a hold from a patron's account as shown in the example below.
DELETE https://patron.api.overdrive.com/v1/patrons/me/holds/76C1B7D0-17F4-4C05-8397-C66C17411584 User-Agent: {Your application} Authorization: Bearer {OAuth patron access token} Host: patron.api.overdrive.com Connection: Keep-Alive
This returns a simple 204 NoContent response when you've successfully removed a hold:
204 NoContent Pragma: no-cache X-Frame-Options: deny Cache-Control: no-cache Date: Wed, 25 Sep 2013 13:25:11 GMT Expires: -1