β₯ API Reference
Public HTTP endpoints
The endpoints below power our own surfaces (search, leaderboards, profile pages). They're publicly callable β no API key for read-only routes. Auth-required routes use the same Supabase session cookie our web app does; if you want third-party access we can issue a bearer token; contact us.
Search
/api/search?q=<query>&kind=<surface?>PUBLICFull-text search across lessons, glossary, cheatsheets, guides, projects, and learning paths. Scores title > module > body, with small per-surface boost. Top 30 with <mark>-wrapped snippet. Optional `&kind=lesson|glossary|cheatsheet|guide|project|path` filter.
REQUEST
# query length must be between 2 and 80 chars curl "https://learnpython.academy/api/search?q=list+comprehension"
RESPONSE
{
"results": [
{
"id": "lesson-66",
"title": "List comprehensions",
"url": "/lesson/lesson-66",
"kind": "lesson",
"trackId": "foundations",
"trackName": "Python Foundations",
"moduleTitle": "Module 4 Β· Strings & comprehensions",
"type": "write",
"is_free": false,
"score": 15,
"snippet": "β¦use <mark>list comprehension</mark> instead of map+lambdaβ¦"
}
],
"total": 13
}- Edge-cached 5 minutes.
- No API key needed.
- Index covers ~1,350 lessons + 60 glossary terms + 8 cheatsheets + 7 guides + 12 projects + 9 paths.
Leaderboards
/api/leaderboardPUBLICTop 50 learners by total XP. Only display_name + counters β no PII.
REQUEST
curl "https://learnpython.academy/api/leaderboard"
RESPONSE
{
"entries": [
{ "id": "uuid", "display_name": "Ada K.", "xp_total": 12450, "streak_days": 18 },
β¦
]
}- Edge-cached 60s.
- Requires migration 20260517_public_leaderboard.sql to be applied.
/api/challenges/leaderboard?challenge_id=<slug>PUBLICPer-challenge ranking. Score column varies by kind (perf=ms ASC, golf=chars ASC, speed=correct DESC).
REQUEST
curl "https://learnpython.academy/api/challenges/leaderboard?challenge_id=perf-fizzbuzz"
RESPONSE
{
"entries": [
{
"user_id": "uuid",
"display_name": "Bob M.",
"execution_ms": 0.74,
"correct_count": null,
"char_count": null,
"rank": 1,
"created_at": "2026-05-18T14:23:00Z"
}
]
}- Edge-cached 30s.
Profiles
/u/<handle>PUBLICHTML profile page for an opted-in learner. Returns 404 when handle missing or profile not public.
REQUEST
# HTML page β no JSON variant. Use it in an iframe or scrape. curl "https://learnpython.academy/u/ada-k"
RESPONSE
<!doctype html>β¦
Feeds
/blog/rss.xmlPUBLICRSS 2.0 feed of every blog post. Auto-discovered by Feedly / NetNewsWire / Reeder.
REQUEST
curl "https://learnpython.academy/blog/rss.xml"
RESPONSE
<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0">β¦
/sitemap.xmlPUBLICStandard XML sitemap covering 1000+ URLs β lessons, tracks, paths, projects, blog, public profile pages.
REQUEST
curl "https://learnpython.academy/sitemap.xml"
RESPONSE
<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">β¦
Glossary
/api/glossaryPUBLICFlat list of every Python term in the CodeMentor glossary β definition, category, linked lesson, public URL. CORS open, edge-cached 1 hour.
REQUEST
curl "https://learnpython.academy/api/glossary"
RESPONSE
{
"items": [
{
"term": "Decorator",
"slug": "decorator",
"definition": "A higher-order function that wraps another to add behavior β logging, caching, auth. `@cache` is one.",
"category": "Functions",
"lesson": "lesson-115",
"url": "https://learnpython.academy/glossary/decorator"
}
],
"total": 60
}- CORS open.
- Edge-cached 1 hour.
/api/glossary/<slug>PUBLICSingle term by slug. Same shape as one item from /api/glossary, plus an `example` code snippet when available.
REQUEST
curl "https://learnpython.academy/api/glossary/decorator"
RESPONSE
{
"term": "Decorator",
"slug": "decorator",
"definition": "A higher-order function that wraps anotherβ¦",
"category": "Functions",
"lesson": "lesson-115",
"example": "@functools.cache\ndef fib(n): ...",
"url": "https://learnpython.academy/glossary/decorator"
}- 404 if slug not in the glossary.
Cheatsheets
/api/cheatsheetPUBLICIndex of every cheatsheet β title, group count, entry count, public URL. CORS open, edge-cached 1 hour.
REQUEST
curl "https://learnpython.academy/api/cheatsheet"
RESPONSE
{
"items": [
{
"slug": "fastapi",
"title": "FastAPI cheatsheet β routes, Pydantic, auth, async, deploy",
"track_id": "fastapi",
"emoji": "β‘",
"updated": "2026-05",
"group_count": 6,
"entry_count": 17,
"url": "https://learnpython.academy/cheatsheet/fastapi"
}
],
"total": 8
}/api/cheatsheet/<slug>PUBLICFull structured cheatsheet body β every group + every snippet (label, why, code).
REQUEST
curl "https://learnpython.academy/api/cheatsheet/fastapi"
RESPONSE
{
"slug": "fastapi",
"title": "FastAPI cheatsheet β β¦",
"groups": [
{
"title": "Hello + routing",
"entries": [
{ "label": "Minimal app", "why": "Spins up a server immediately.", "code": "from fastapi import FastAPI\napp = FastAPI()\nβ¦" }
]
}
]
}- 404 if slug not in the cheatsheet collection.
Embeds
/api/embed/lesson/<id>PUBLICJSON metadata for a single lesson β title, task, type, quiz options + correctIndex (for quiz/predict lessons), and links back to the full lesson + iframe URL. CORS open, edge-cached 5 minutes.
REQUEST
curl "https://learnpython.academy/api/embed/lesson/lesson-01"
RESPONSE
{
"id": "lesson-01",
"title": "Hello, World!",
"type": "write",
"is_free": true,
"xp_reward": 75,
"task": "Print Hello, World!",
"track": { "id": "foundations", "name": "Python Foundations", "emoji": "π" },
"quiz": null,
"embed_url": "https://learnpython.academy/embed/lesson/lesson-01",
"lesson_url": "https://learnpython.academy/lesson/lesson-01"
}- CORS open (Access-Control-Allow-Origin: *).
- Edge-cached 5 minutes.
/embed/lesson/<id>PUBLICIframe-ready HTML page for a single lesson. No nav, no footer, minimal UI. For quiz/predict types it includes a working check-answer flow. Frame-ancestors *, so it embeds anywhere.
REQUEST
<iframe src="https://learnpython.academy/embed/lesson/lesson-66" width="100%" height="520" style="border:1px solid var(--border);border-radius:12px" ></iframe>
RESPONSE
<!doctype html>β¦
- Includes a 'Try full lesson β' link back to /lesson/<id>?ref=embed.
- Resize via the iframe height attribute; the embed is responsive.
User data (auth required)
/api/progressAUTHList of lesson IDs the authenticated user has completed.
REQUEST
# Auth via Supabase session cookie. No external API key.
RESPONSE
{ "completed": ["lesson-1", "lesson-2", β¦] }/api/bookmarksAUTHUser's saved-for-later lessons.
REQUEST
# Auth required.
RESPONSE
{ "bookmarks": [{ "lesson_id": "lesson-66", "created_at": "β¦" }] }/api/achievementsAUTHUnlocked badges + the snapshot of metrics used to compute them.
REQUEST
# Auth required.
RESPONSE
{
"badges": [{ "id": "ten-lessons", "tier": "bronze", "icon": "π" }],
"snapshot": {
"completed_count": 12,
"xp_total": 850,
"streak_days": 4,
"missions_completed": 1,
β¦
}
}/api/bookmarksAUTHAdd a bookmark.
REQUEST
curl -X POST "https://learnpython.academy/api/bookmarks" \
-H "Content-Type: application/json" \
-d '{"lesson_id": "lesson-66"}'RESPONSE
{ "ok": true }Need a webhook? Bulk export? Bearer-token API access? Email support@learnpython.academy and tell us what you're building β we'll wire something up.
Rate limits: ~60 reqs/min/IP on /api/search; everything else is edge-cached. Abuse β throttled or blocked.