Repository navigation
v2.0.0
MAJOR. An Audible outage used to come back as a 404, the same status as "this does not exist". It is now a 503. That changes a status code callers could observe, so it is a breaking release, and the first MAJOR. Bulk GET /book also gains a notFetched list and narrows what notFound means, described below. Everything else in the published shape is unchanged or only added to.
Changed
- Every Audible outage is now
503, not404. When Libex could not reach Audible and had no stored or cached copy to answer from, the response is503withRetry-After: 30andCache-Control: no-store. The body is{"error": ..., "status_code": 503, "code": "upstream_unavailable", "retryAfter": 30};retryAfteris the same number of seconds as the header and appears only on503bodies. Before, the same situation was a404carryingcode: "upstream_unavailable"(since 1.27.0), which a client that reads only the status could not tell from a missing record. A404now always means Audible or Libex's own store was asked and has no such record; retrying a404will not change it, retrying a503should. - The
503applies to every route that calls Audible, not only to a failed first page. It covers single-book, chapters, series and author lookups, searches, narrators, new releases, coming soon and categories, and bulkGET /book. It also covers a total failure partway through a multi-step route:GET /author/books?name=when fetching the full details of the books it found fails outright,GET /author/books/{asin}when either its walk through the author's catalogue or the fetching of the books' details fails outright, and the series books routes when the book details cannot be fetched. A response that is only partly short is not an error: it stays200withX-Libex-Complete: falseand the reason inX-Libex-Incomplete-Reason, as before. - The
404thatGET /author/books?name=gave for an Audible outage on the first page, noted as unchanged in 1.28.0, is now503. The 1.28.0 entry said that route still answered404for it; that no longer holds. - Bulk
GET /booknow separates ASINs Audible confirmed absent from ASINs Libex could not look up.notFoundused to hold both. It now holds only the ASINs Audible confirmed it has no record of. A newnotFetchedfield holds the ASINs Libex could not look up because Audible was unreachable and neither the stored copy nor the cache had them. If your code readsnotFoundas "worth retrying later" or as "treat as missing for now", it must now look atnotFetchedfor the retryable ones; an ASIN left innotFoundwill not resolve on retry.books,notFound,placeholderRecordsandnotFetchednever share an ASIN, and the ASINs in each are given as you sent them, in request order. If Audible is unreachable and nothing at all can be served, the request is the503described above rather than a404.
Added
notFetchedon the bulkGET /bookresponse. It is always present and is an empty list when nothing failed to be fetched. When it is not empty,X-Libex-CompleteisfalseandX-Libex-Incomplete-Reasonishydration-failed, as it already was for an ASIN a failed chunk left uncovered.- The
503is documented in the OpenAPI schema on the routes that can return it, including theRetry-Afterheader.
Fixed
- The
/docsdescription ofX-Libex-Incomplete-Reasonno longer saysdiscovery-incompleteis never emitted.GET /author/books?name=has emitted it since 1.28.0, when its walk through Audible's results stops early. The description now says so.
libex_core 0.8.0
Added
BulkBookResponse.notFetched, a list of the requested ASINs that could not be looked up because Audible was unreachable and no stored or cached copy covered them. It defaults to an empty list, so code that builds aBulkBookResponsewithout it is unaffected, and it serializes always-present likeplaceholderRecords.
Changed
- The documented meaning of
BulkBookResponse.notFoundnarrows to ASINs Audible confirmed it has no record of. The field, its type and its position are unchanged, but it no longer holds ASINs that could not be fetched; those belong innotFetched. An embedder that fillsnotFounditself and treated it as "missing or unfetched" should move the unfetched ones tonotFetched. The field description (visible in the generated schema) was reworded to match.