Metadata-Version: 2.4
Name: vooks-catalog
Version: 1.0.0
Summary: Official client for the Vooks Public Catalog API: search children's read-along titles by age, topic and language, and read published subscription pricing.
Project-URL: Homepage, https://www.vooks.com/developers
Project-URL: Documentation, https://www.vooks.com/developers
Project-URL: Bug Tracker, https://www.vooks.com/developers
Author-email: "Vooks, Inc." <support@vooks.com>
License: SEE LICENSE IN https://www.vooks.com/terms-of-service/
Keywords: api,books,catalog,children,read-along,sdk,vooks
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# vooks-catalog

Official Python client for the [Vooks](https://www.vooks.com) Public Catalog API: a
library of ad-free animated read-along storybooks, audiobooks and ebooks for children
roughly ages 2 to 8.

**Reads need no credential.** No key, no registration, no form. A token only raises the
rate limit from 600 to 3,000 requests a minute and unlocks catalog exports.

No runtime dependencies. A dependency in a published SDK is a dependency in every
project that installs it, and `urllib` is enough for nine reads and one write.

```bash
pip install vooks-catalog
```

```python
from vooks_catalog import VooksCatalog

vooks = VooksCatalog()

page = vooks.list_titles(q="dinosaurs", age=4, limit=5)
for title in page["data"]:
    print(title["title"], title["url"])
```

## Pagination

`list_titles`, `list_topics` and `titles` are cursor-paginated. `list_plans` is not:
there are four plans and it returns them all.

`titles()` follows the cursor for you. Prefer `list_titles` when you only need the first
page, because this makes a request per page.

```python
for title in vooks.titles(language="spanish"):
    print(title["title"])
```

## Errors

An HTTP error response raises `VooksApiError`, carrying the API's stable
machine-readable `code`. Branch on that, not on the message.

A transport failure, where the request never got an answer, raises whatever `urllib`
raised: there is no status or code to report, so wrapping it would invent one.

```python
from vooks_catalog import VooksApiError

try:
    vooks.get_title("no-such-slug")
except VooksApiError as error:
    if error.code == "not_found":
        ...
    print(error.status, error.code, error.retry_after_seconds)
```

`retry_after_seconds` is set when the server sent a `Retry-After`, in either form RFC
9110 allows. A date rounds up, so a date 400ms away gives `1`, never `0`. A literal
`Retry-After: 0` is kept as `0`. It is `None` when the server sent no header, when the
value will not parse, or when the date has already passed, because "said nothing" and
"retry now" are different answers.

## Sandbox

A fixed, tiny catalog that never changes and never touches the live library.

```python
from vooks_catalog import VooksCatalog, SANDBOX_BASE_URL

sandbox = VooksCatalog(base_url=SANDBOX_BASE_URL)
```

## Command line

```bash
vooks search dinosaurs --age 4
vooks title 10-little-fish
vooks topics
vooks plans
vooks search bedtime --json
```

## Reading on

- [Developer guide](https://www.vooks.com/developers)
- [OpenAPI 3.1](https://www.vooks.com/openapi.json)
- [Agent index](https://www.vooks.com/llms.txt)
- [Node and TypeScript client](https://www.npmjs.com/package/@vooks/catalog)
