Getting Started
Read public Goodreads books, reviews, authors, quotes, series and lists as structured JSON. No Goodreads account and no developer key — just your FetchLayer key.
1. Get your API key
Create an account and generate a FetchLayer API key from your dashboard. The same key works on every platform.
Create free account →2. Find a book
Search by title, author, ISBN or keywords. Every result carries its id, rating and series.
curl -X POST https://api.fetchlayer.dev/goodreads/search-books \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"query":"project hail mary","limit":10}'3. Read the book
By id, link or ISBN: description, genres, the 1–5 star breakdown, series, awards, edition details and how many readers want to read it.
curl -X POST https://api.fetchlayer.dev/goodreads/book-detail \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"book":5907,"includeSimilarBooks":true}'4. Read what readers say
Reviews in Goodreads' popular order, or newest first, narrowed by stars, language or words in the text. 1 credit per 30 reviews returned.
curl -X POST https://api.fetchlayer.dev/goodreads/book-reviews \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"book":5907,"rating":1,"sort":"newest","limit":30}'Continue with cursor
hasNextPage is true, pass the response's nextCursor back as cursor, with the same other parameters, to continue where it stopped. 5. List an author's books
Every book with its rating, first publication year and number of editions, by popularity, title, newest first, rating or length. /author-profile has the biography and follower count.
curl -X POST https://api.fetchlayer.dev/goodreads/author-books \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"author":656983,"sort":"newest","limit":30}'Resolving a pasted link
/resolve-url tells you whether a goodreads.com link is a book, an author, a series, a list or something else, with its id and the route and arguments that read it. It is free.
curl -X POST https://api.fetchlayer.dev/goodreads/resolve-url \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"url":"https://www.goodreads.com/book/show/5907.The_Hobbit"}'Errors and retries
A 400 names the field to fix, including any field the route does not take. A 404 means the book, author, series, list, review or tag does not exist or is not public. A 503 is worth retrying after a short wait. A 502 means Goodreads' answer could not be read; retry later.
Error responses
Every error, on every route, is JSON in one shape: error (what went wrong, in words), status, code, retryable and requestId, which also comes as the X-Request-Id header. Branch on code and retryable rather than on the text; on a 5xx the text is generic. Quote requestId when reporting a problem.
{
"error": "Missing required parameter: url",
"status": 400,
"missing": ["url"],
"code": "invalid_input",
"retryable": false,
"requestId": "922874e3-c0d0-40d8-8866-d198af132420"
}| code | Status | Retryable | Meaning |
|---|---|---|---|
| invalid_input | 400 | no | The request needs fixing; error names the field. A missing required parameter also lists it in missing. |
| unauthorized | 401 | no | The API key is missing or not valid. |
| insufficient_credits | 402 | no | Nothing left to spend: no credits, a used-up free trial, or a monthly allowance and credit balance both spent. error says which. Waiting does not help; topping up does. |
| forbidden | 403 | no | This key or account is not allowed this request. |
| not_found | 404 | no | What the request names does not exist or is not public. |
| expired | 410 | no | What the request refers to is no longer available; ask for it afresh. |
| quota_exceeded | 429 | no | A request-rate limit was reached; error says which. Slow down before sending more. |
| cancelled | 499 | no | The caller closed or cancelled the request before it finished. The work was stopped and nothing was charged. |
| time_limit | 503 | yes | Your timeoutMs ran out before there was anything to return; ask again, or allow more time. |
| temporarily_unavailable | 503 | yes | Not available right now; ask again shortly. |
| posts_unavailable | 403 | no | TikTok user videos: TikTok is not showing this account’s posts publicly right now. Asking again at once returns the same answer; nothing is charged. |
| store_unreachable | 503 | yes | Store routes (Shopify, WooCommerce): the store itself can’t be reached right now — it may be offline. Ask again later. Where a store route doesn’t say so yet, an offline store is temporarily_unavailable. |
| upstream_error | 502 | yes | The source answered in a way that could not be used; ask again later. |
| internal_error | 500 | yes | Something failed on our side; ask again later, and quote requestId if it persists. |
| tool_error | — | no | MCP only: a tool call failed in a way no other code describes; error says what. |
More codes may be added; treat one you do not recognise by its retryable flag. Over MCP, a tool error carries the same fields in structuredContent, and as a JSON text block beside the message.