Holds API
The Holds API is used to manage and place holds for a specific user.
Note: The examples below show our production API URL. If you're using our integration environment, use https://integration-patron.api.overdrive.com.
Using the Holds API
Using POST, GET, PUT, 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.
Resource URL
https://patron.api.overdrive.com/v1/patrons/me/holds
Available endpoint actions
- Place a hold (POST): This request places holds on behalf of a user.
- GET user holds: This request lists a user's current holds or finds a specific held title.
- Update a hold (PUT): This request updates the user's email address for a specific hold.
- Suspend a hold (POST): This request suspends a hold that a user has placed on a title, which delays the hold from becoming available.
- Remove the suspension from a hold (DELETE): This request reactivates the hold for a user so they can borrow it as soon as it's available.
- Remove a hold (DELETE): This request removes a specific hold from a user'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 user's email address, where they'll be notified when the title is available to borrow. |
| ignoreHoldEmail Optional | When set to true, a user 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:
Example 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": "50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6"
},
{
"name": "emailAddress",
"value": "YourEmailHere@overdrive.com"
}
]
}When you've successfully placed a hold, you'll get a response that includes specific hold information for the title:
Example response
201 Created
Location: https://patron.api.overdrive.com/v1/patrons/me/holds/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6
Date: Wed, 22 May 2024 17:39:46 GMT
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Length: 1329
Content-Type: application/json; charset=utf-8
{
"reserveId": "50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6",
"crossRefId": 3280473,
"emailAddress": "YourEmailHere@overdrive.com",
"holdListPosition": 1,
"estimatedWaitDays": 14,
"numberOfHolds": 1,
"holdPlacedDate": "2024-05-22T17:39:46Z",
"links": {
"self": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6",
"type": "application/vnd.overdrive.circulation.api+json"
},
"metadata": {
"href": "https://api.overdrive.com/v1/collections/v1L1BYwAAAA2Q/products/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6/metadata",
"type": "application/vnd.overdrive.api+json"
}
},
"actions": {
"editHold": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6",
"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/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6",
"method": "DELETE"
},
"addSuspension": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6/suspension",
"method": "POST"
}
}
}GET a list of a user's holds
Send a GET request to the holds endpoint to get a list of current holds on a user's account as shown below.
Example request
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
The response includes a list of titles that the authenticated user currently has on hold from their library or school.
Example response
200 OK
Date: Wed, 22 May 2024 17:50:35 GMT
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Length: 2781
Content-Type: application/json; charset=utf-8
{
"totalItems": 2,
"holds": [
{
"reserveId": "50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6",
"crossRefId": 3280473,
"emailAddress": "YourEmailHere@overdrive.com",
"holdListPosition": 2,
"estimatedWaitDays": 28,
"numberOfHolds": 2,
"holdPlacedDate": "2024-05-22T17:39:46Z",
"links": {
"self": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6",
"type": "application/vnd.overdrive.circulation.api+json"
},
"metadata": {
"href": "https://api.overdrive.com/v1/collections/v1L1BYwAAAA2Q/products/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6/metadata",
"type": "application/vnd.overdrive.api+json"
}
},
"actions": {
"editHold": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6",
"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/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6",
"method": "DELETE"
},
"addSuspension": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/50a5ee33-4ca2-4366-a3ed-28b80c0a5cf6/suspension",
"method": "POST"
}
}
},
{
"reserveId": "82ef8ec3-386b-4561-8f65-2d59433b9358",
"crossRefId": 1381708,
"holdListPosition": 1,
"numberOfHolds": 1,
"holdPlacedDate": "2024-05-17T21:01:11Z",
"links": {
"self": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/82ef8ec3-386b-4561-8f65-2d59433b9358",
"type": "application/vnd.overdrive.circulation.api+json"
},
"metadata": {
"href": "https://api.overdrive.com/v1/collections/v1L1BYwAAAA2Q/products/82ef8ec3-386b-4561-8f65-2d59433b9358/metadata",
"type": "application/vnd.overdrive.api+json"
}
},
"actions": {
"removeHold": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/82ef8ec3-386b-4561-8f65-2d59433b9358",
"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": "82ef8ec3-386b-4561-8f65-2d59433b9358"
},
{
"name": "formatType",
"type": "text",
"value": "",
"options": [
"ebook-overdrive",
"ebook-kindle"
],
"optional": true
}
]
},
"addSuspension": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/82ef8ec3-386b-4561-8f65-2d59433b9358/suspension",
"method": "POST"
}
}
}
],
"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 second person in line for the title, and there are two people who have the title on hold.
The second title in the example above is ready to borrow because checkout appears within the list of available actions.
Note: If you see a holdListPosition of "0," that means all copies of the title have expired. Holds will begin to advance if the library purchases more copies. You may also see a holdListPosition of "0" when a hold becomes available for checkout. However, the checkout action is the best indicator that a hold is available.
Note that when a hold becomes available for a user, they'll have three days (72 hours) to borrow it or suspend it if they're not ready to borrow. If the user misses the pickup window one time, the hold will be automatically suspended. If they miss the pickup window again, the hold will be canceled.
Learn more about hold suspensions under "Suspending a hold" below.
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 request to update a user's email address:
Example request
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:
Example response
204 NoContent Date: Wed, 22 May 2024 18:21:41 GMT X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains
Suspending a hold (POST)
Suspending a hold lets a user keep their place in line for a title until they're ready to read it. If the hold is already available, suspending it passes the user's copy to the next person in line. Hold suspensions lasts until the user decides to remove it. However, if a hold is suspended for 365 days in a row, it will be canceled automatically.
To suspend a hold on a title, make a POST request that includes:
- The reserveId or crossRefId for the hold (in the URL).
- An emailAddress field with the email address that was used to place the hold.
Tip: Suspending a hold is useful for end users that want more control over when their hold is delivered. 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.
Here's an example of a suspension POST request:
Example 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"
}
]
}If you don't use email addresses or you don't have the user's email address, you can send the POST request with an empty body.
A successful response looks like this:
Example response
201 Created
Location: https://patron.api.overdrive.com/v1/patrons/me/holds/76c1b7d0-17f4-4c05-8397-c66c17411584/suspension
Date: Wed, 22 May 2024 18:27:06 GMT
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Length: 1545
Content-Type: application/json; charset=utf-8
{
"reserveId": "76c1b7d0-17f4-4c05-8397-c66c17411584",
"crossRefId": 784864,
"emailAddress": "yourEmailHere@overdrive.com",
"holdListPosition": 2,
"numberOfHolds": 2,
"holdSuspension": {
"suspensionType": "limited",
"numberOfDays": 365
},
"holdPlacedDate": "2024-05-22T17:39:46Z",
"links": {
"self": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/76c1b7d0-17f4-4c05-8397-c66c17411584",
"type": "application/vnd.overdrive.circulation.api+json"
},
"metadata": {
"href": "https://api.overdrive.com/v1/collections/v1L1BYwAAAA2Q/products/76c1b7d0-17f4-4c05-8397-c66c17411584/metadata",
"type": "application/vnd.overdrive.api+json"
}
},
"actions": {
"editHold": {
"href": "https://patron.api.overdrive.com/v1/patrons/me/holds/76c1b7d0-17f4-4c05-8397-c66c17411584",
"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/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"
}
}
}Removing the suspension on a hold (DELETE)
If you want to remove a hold suspension, you can send a DELETE request 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:
Example 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: patron.api.overdrive.comA successful DELETE request will return a "204 NoContent" response:
Example response
204 NoContent Date: Fri, 31 May 2024 18:18:46 GMT X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains
Removing a hold (DELETE)
Make a DELETE request with the title's id to the holds endpoint to completely remove a hold from a user's account.
Example request
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-AliveThis returns a simple "204 NoContent" response when you've successfully removed a hold:
Example response
204 NoContent Date: Fri, 31 May 2024 18:27:33 GMT X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000; includeSubDomains