ReadingList API Documentation
Public REST API · v1 · CORS open · No auth required (free tier)
What this API serves
ReadingList exposes a free, public, read-only REST API over its source-cited K-12 reading-list dataset. Six endpoints serve book metadata, curriculum and state reading lists, and grade-appropriate recommendations. The API is designed for AI tutors integrating grade-level book suggestions, ed-tech apps building reading-companion features, library systems doing collection development, and researchers studying assigned reading.
Every response references the classification standard — the public 6-dimension methodology that documents how each field is sourced and verified.
Authentication & rate limits
Free tier (current). No authentication required. Recommended client-side rate limit: ≤100 requests per day per IP. Server-side rate limit enforcement is not yet live; please honor the cap so the free tier remains available to everyone.
Paid tiers (coming). Pro tier (1,000/day) and Enterprise tier (10,000+/day with SLA) ship alongside auth in a future release. Token-based authentication via Bearer headers; pricing will be published on the pricing page when tiers go live.
Rate limit headers appear on every response: X-RateLimit-Tier, X-RateLimit-Daily-Limit, X-RateLimit-Pro-Tier-Daily, X-RateLimit-Enterprise-Tier-Daily.
Conventions
- All endpoints respond with
application/json. No XML, no HTML, no GraphQL. - CORS is open (
Access-Control-Allow-Origin: *) so the API can be called directly from browser-side code. - Responses are edge-cached;
Cache-Controlheaders indicate freshness (typically 1 hour browser, 1 day edge). - Errors return a JSON envelope with
{ error, message, documentation_url }plus the appropriate HTTP status (400 / 404 / 500). - Slugs are lowercase, hyphenated, and stable. The slug for a book / curriculum / state / grade matches its canonical page URL on the site.
- Field semantics follow the classification standard. When a book has no data for a dimension, the field is empty or null — never fabricated.
Quick start — code samples
Integrate the recommendation endpoint in any language. The examples below all hit /api/v1/recommend with the same filter (grade 9, Common Core, exclude-banned, 5 books) and parse the JSON response. Other endpoints follow the same pattern — swap the path, rebuild the query string.
Bash (curl + jq)
# Pretty-print recommendations for grade 9 Common Core, exclude banned
curl -s 'https://readinglist.school/api/v1/recommend?grade=9&curriculum=common-core&exclude_banned=true&limit=5' \
| jq '.books[] | { title, author, lexile, permalink }'Python (requests)
import requests
BASE = "https://readinglist.school/api/v1"
def recommend(grade, curriculum=None, state=None, lexile_max=None,
exclude_banned=False, limit=10):
"""Fetch grade-appropriate book recommendations.
Returns a list of dicts with title/author/lexile/permalink/etc.
See https://readinglist.school/standard for classification methodology.
"""
params = {"grade": grade, "limit": limit}
if curriculum: params["curriculum"] = curriculum
if state: params["state"] = state
if lexile_max is not None: params["lexile_max"] = lexile_max
if exclude_banned: params["exclude_banned"] = "true"
r = requests.get(f"{BASE}/recommend", params=params, timeout=10)
r.raise_for_status()
return r.json()["books"]
books = recommend(grade="9", curriculum="common-core",
exclude_banned=True, limit=5)
for b in books:
print(f"{b['title']:30s} Lexile {b['lexile']:>4}L {b['permalink']}")Node.js / JavaScript (fetch)
// Works in modern Node (18+) and any browser. No dependencies.
async function recommend({ grade, curriculum, state, lexileMax,
excludeBanned = false, limit = 10 }) {
const params = new URLSearchParams({ grade, limit: String(limit) });
if (curriculum) params.set('curriculum', curriculum);
if (state) params.set('state', state);
if (lexileMax != null) params.set('lexile_max', String(lexileMax));
if (excludeBanned) params.set('exclude_banned', 'true');
const url = `https://readinglist.school/api/v1/recommend?${params}`;
const res = await fetch(url);
if (!res.ok) throw new Error(`API ${res.status}: ${await res.text()}`);
const data = await res.json();
return data.books;
}
const books = await recommend({
grade: '9',
curriculum: 'common-core',
excludeBanned: true,
limit: 5,
});
for (const b of books) {
console.log(`${b.title.padEnd(30)} Lexile ${b.lexile}L ${b.permalink}`);
}TypeScript (typed client)
// Generate full typed bindings from /api/openapi via openapi-typescript:
// npx openapi-typescript https://readinglist.school/api/openapi -o api.d.ts
// Then import:
import type { components } from "./api";
type Book = components["schemas"]["Book"];
type RecommendResponse = components["schemas"]["RecommendResponse"];
async function recommend(
filters: { grade: string; curriculum?: string; limit?: number }
): Promise<Book[]> {
const params = new URLSearchParams(filters as Record<string, string>);
const res = await fetch(
`https://readinglist.school/api/v1/recommend?${params}`
);
const data: RecommendResponse = await res.json();
return data.books;
}The full OpenAPI 3.1 spec at /api/openapi auto-generates clients in 50+ languages via openapi-generator (Java, Go, Ruby, PHP, Rust, C#, Swift, etc.).
Endpoints
Six endpoints. The newest (and most flexible) is /api/v1/recommend.
- GET /api/v1/recommend — Grade-appropriate book recommendations with optional filters
- GET /api/book/{slug} — Single-book detail with all assignments + sources
- GET /api/curriculum/{slug} — Books cited in a curriculum framework (all grades)
- GET /api/curriculum/{slug}/grade/{gradeSlug} — Curriculum × grade intersection
- GET /api/state/{stateSlug} — Books cited at the state level (all grades)
- GET /api/state/{stateSlug}/grade/{gradeSlug} — State × grade intersection (includes national curricula)
GET /api/v1/recommend
Grade-appropriate book recommendations with optional filters
Returns up to 50 books matching grade × optional curriculum × optional state × optional Lexile range × optional banned-state exclusion. Designed for AI tutors integrating grade-level reading suggestions.
Parameters
- graderequired
- Grade slug — K, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, or 12.
- stateoptional
- State slug (e.g. california, texas, new-york). Filters to books cited in that state's ELA framework or DOE list (national curricula included).
- curriculumoptional
- Curriculum slug (e.g. common-core, ap-literature, ib-dp-english-literature, cambridge-igcse-english-lit).
- lexile_minoptional
- Minimum Lexile measure (non-negative integer). Books below this filtered out.
- lexile_maxoptional
- Maximum Lexile measure (non-negative integer). Books above this filtered out.
- exclude_bannedoptional
- Set to 'true' to exclude books with any documented banning or removal record per PEN America's Index.
- limitoptional
- Maximum books returned. Default 10, max 50. Higher values silently capped at 50.
Example
curl 'https://readinglist.school/api/v1/recommend?grade=9&curriculum=common-core&exclude_banned=true&limit=5'Response shape
{
"version": "v1",
"generated_at": "2026-04-30T...",
"filters": { "grade": "9", "curriculum": "common-core", "state": null,
"lexile_min": null, "lexile_max": null,
"exclude_banned": true, "limit": 5 },
"methodology_url": "https://readinglist.school/standard",
"methodology_summary": "Recommendations derive from the 6-dimension classification standard...",
"rate_limit": { "tier": "free", "daily_limit": 100, ... },
"count": 5,
"books": [
{
"slug": "lord-of-the-flies",
"title": "Lord of the Flies",
"author": "William Golding",
"isbn13": "9780399501487",
"lexile": 770,
"lexile_range_min": 770,
"lexile_range_max": 770,
"grade_min": 9,
"grade_max": 12,
"themes": ["civilization", "human nature", "morality"],
"banned_in_states": [],
"permalink": "https://readinglist.school/book/lord-of-the-flies",
"api_url": "https://readinglist.school/api/book/lord-of-the-flies"
},
{ ... }
]
}GET /api/book/{slug}
Single-book detail with all assignments + sources
Returns the full book record (title, author, ISBNs, Lexile, grade band, themes, banning records, cover URL) and every documented assignment (curriculum, state, grade, source URL).
Parameters
- {slug}required
- Book slug from the canonical book URL, e.g. to-kill-a-mockingbird.
Example
curl 'https://readinglist.school/api/book/to-kill-a-mockingbird'Response shape
{
"book": { "slug", "title", "author", "isbn13", "lexile", ... },
"assignments": [ { "curriculum_slug", "state_slug", "grade_slug",
"source_url", "source_document", "context" }, ... ]
}GET /api/curriculum/{slug}
Books cited in a curriculum framework (all grades)
Returns every book cited under the named curriculum, aggregated across all grade levels. Use this to seed a curriculum-aligned reading list at any grade.
Parameters
- {slug}required
- Curriculum slug — common-core, ap-literature, ap-language, ib-dp-english-literature, cambridge-igcse-english-lit, etc.
Example
curl 'https://readinglist.school/api/curriculum/common-core'Response shape
{
"curriculum": { "slug", "name", "type", "publisher", ... },
"count": N,
"books": [ { "slug", "title", "author", "lexile", "grade_min",
"grade_max", ... }, ... ]
}GET /api/curriculum/{slug}/grade/{gradeSlug}
Curriculum × grade intersection
Narrower than the curriculum-only endpoint. Returns books cited under the curriculum at the specific grade level.
Parameters
- {slug}required
- Curriculum slug.
- {gradeSlug}required
- Grade slug — K through 12.
Example
curl 'https://readinglist.school/api/curriculum/ap-literature/grade/11'Response shape
{
"curriculum": {...}, "grade": {...}, "count": N, "books": [...]
}GET /api/state/{stateSlug}
Books cited at the state level (all grades)
Returns books documented in a US state's ELA framework, summer-reading list, or DOE guidance. Aggregated across all grades.
Parameters
- {stateSlug}required
- State slug — california, texas, florida, new-york, etc.
Example
curl 'https://readinglist.school/api/state/california'Response shape
{
"state": { "slug", "abbr", "name", "standards_name", "doe_url" },
"count": N,
"books": [...]
}GET /api/state/{stateSlug}/grade/{gradeSlug}
State × grade intersection (includes national curricula)
Books cited at the state level for the specific grade, including national curricula (Common Core, AP, IB, Cambridge) that apply nationally — these are surfaced alongside state-tagged rows.
Parameters
- {stateSlug}required
- State slug.
- {gradeSlug}required
- Grade slug — K through 12.
Example
curl 'https://readinglist.school/api/state/california/grade/9'Response shape
{
"state": {...}, "grade": {...}, "count": N, "books": [...]
}Error reference
All error responses share the same JSON envelope:
{
"error": "stable_error_code",
"message": "Human-readable explanation.",
"documentation_url": "https://readinglist.school/standard#section"
}The error field is a stable code suitable for programmatic branching (it never changes for a given failure mode). The message field is for humans and may evolve. The documentation_url points to the relevant classification standard section explaining the methodology behind the failing dimension.
Stable error codes
| HTTP | error code | When it fires | Fix |
|---|---|---|---|
| 400 | missing_required_param | Required query parameter absent. Currently only grade on /api/v1/recommend. | Add ?grade= to the URL with a valid grade slug (K, 1, ..., 12). |
| 400 | invalid_lexile_param | lexile_min or lexile_max provided but not a non-negative integer. | Pass an integer ≥0 (typical 0L-2000L). Strings or negatives reject. |
| 404 | grade_not_found | Grade slug doesn’t match any record. Valid slugs: K, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12. | Use one of the documented slugs. Remember K not 0 for kindergarten. |
| 404 | state_not_found | State slug doesn’t match. Valid slugs come from /api/state (50 US states + Washington DC). | Use lowercase hyphenated state name — california, not CA or California. |
| 404 | curriculum_not_found | Curriculum slug doesn’t match. Valid slugs: common-core, ap-literature, ap-language, ib-dp-english-literature, cambridge-igcse-english-lit, etc. | Look up the canonical slug at /curriculum. |
| 404 | Book not found | Returned by /api/book/{slug} when the book slug doesn’t match a tracked record. | Look up the canonical slug at /book pages or via /api/v1/recommend first to discover slugs. |
| 5xx | (transient) | Upstream database hiccup or platform-level outage. Rare; not envelope-formatted (Vercel / Next.js default error page). | Retry with exponential backoff (1s → 2s → 4s). If persistent >5 min, check Vercel status or contact us via /contact. |
| 429 | (future) | Rate limit exceeded. Server-side enforcement ships with auth in Phase 3 (Pro / Enterprise tiers). Currently free-tier limits are client-honor only. | Reduce request rate to ≤100/day. Pro tier (1k/day) and Enterprise (10k+/day) become available alongside auth in a future release. |
Programmatic handling
Branch on error field, not on message string content. Example:
async function recommend(filters) {
const params = new URLSearchParams(filters);
const res = await fetch(
`https://readinglist.school/api/v1/recommend?${params}`
);
if (res.ok) return (await res.json()).books;
const err = await res.json();
switch (err.error) {
case 'missing_required_param':
throw new Error('Bug — grade param missing in client code');
case 'grade_not_found':
case 'state_not_found':
case 'curriculum_not_found':
// User typed an invalid filter. Surface inline, not as crash.
return { invalidFilter: err.error, message: err.message };
case 'invalid_lexile_param':
throw new Error('Coerce lexile to integer before passing');
default:
// 5xx or unknown — retry with backoff
throw new Error(`API ${res.status}: ${err.message}`);
}
}Machine-readable spec
The full API contract is published as an OpenAPI 3.1 specification at /api/openapi. Run it through Postman / Stoplight Studio / openapi-generator / Swagger Codegen to auto-generate a client in any language. Stable contract under /api/v1/; breaking changes will land under /api/v2/ with a 12-month deprecation window.
Versioning
The newer recommendation endpoint is namespaced /api/v1/ to allow forward-compatible evolution. Breaking changes will land under /api/v2/ with a deprecation window for v1 (typically 12 months). The non-versioned endpoints (/api/book, /api/curriculum, /api/state) are treated as stable v1 contracts and changes follow the same policy.
Citation
Researchers, journalists, ed-tech developers, and AI tutors are welcome to cite this API in derivative work. Suggested citation: ReadingList (readinglist.school) Classification Standard v1.0, 2026, accessed via /api/v1/recommend. The canonical methodology URL is https://readinglist.school/standard.
Bug reports, feature requests, and integration questions go through the contact page.