CodeTrain / Developers
CodeTrain developer API
A public, read-only HTTP API over the CodeTrain course catalog, changelog and
roadmap. No account, no key, no signup. Base URL https://api.codetrain.ai.
Quickstart
$ curl -s https://api.codetrain.ai/v1/catalog
That is the whole setup. Every endpoint below is a GET, returns
JSON, and needs no credentials. If you would rather read prose than JSON, every page on this site
also serves markdown: ask for it with Accept: text/markdown.
$ curl -s -H "Accept: text/markdown" https://codetrain.ai/learn/
Endpoints
| Method | Path | Returns |
|---|---|---|
GET | /v1/health | Liveness and the current API version. |
GET | /v1/catalog | Every published course, its classes and their lessons. |
GET | /v1/courses/{course_id} | One course with its live classes. |
GET | /v1/lessons/{lesson_id} | Metadata for one curated lesson: title, blurb, language and step count. Never the step content, because writing the steps is what the learner is here to do. |
GET | /v1/changelog | What shipped, newest first. The same entries as /changelog/. |
GET | /v1/roadmap | Roadmap items grouped by stage. The same data as /roadmap/. |
GET | /v1/referrals/{code} | Whether a Conductor Network referral code belongs to somebody. A bare boolean and nothing else: no name, no id. |
Each endpoint in full
GET /v1/health
Liveness and the current API version.
$ curl -s https://api.codetrain.ai/v1/health
{"status": "ok", "version": "v1"}
GET /v1/catalog
Every published course, its classes and their lessons.
$ curl -s https://api.codetrain.ai/v1/catalog
{"courses": [{"id": "python-intro", "title": "...", "classes": [...]}]}
GET /v1/courses/{course_id}
One course with its live classes.
$ curl -s https://api.codetrain.ai/v1/courses/python-intro
{"id": "python-intro", "title": "...", "classes": [...]}
GET /v1/lessons/{lesson_id}
Metadata for one curated lesson: title, blurb, language and step count. Never the step content, because writing the steps is what the learner is here to do.
$ curl -s https://api.codetrain.ai/v1/lessons/python-basics
{"id": "python-basics", "title": "...", "lang": "python", "steps": 4}
GET /v1/changelog
What shipped, newest first. The same entries as /changelog/.
$ curl -s https://api.codetrain.ai/v1/changelog
{"entries": [{"id": "open-skill-sync-2026-10-13", "date": "2026-10-13", "kind": "feature"}]}
GET /v1/roadmap
Roadmap items grouped by stage. The same data as /roadmap/.
$ curl -s https://api.codetrain.ai/v1/roadmap
{"stages": [{"key": "shipped", "label": "Shipped", "items": [...]}]}
GET /v1/referrals/{code}
Whether a Conductor Network referral code belongs to somebody. A bare boolean and nothing else: no name, no id.
$ curl -s https://api.codetrain.ai/v1/referrals/ada
{"valid": true}
Authentication
The /v1 endpoints listed above need none. Everything they return is
already published as a web page on this domain, so putting a key in front of it would protect
nothing and stop an agent reading it.
CodeTrain does have an authenticated API behind the dashboard and the CLI, and it
is not part of this public contract. It is versioned separately, changes without
notice, and is not documented here on purpose: it is an implementation detail of our own clients
rather than an integration surface. If you need something from it, write to
support@codetrain.ai and tell us the job you are trying
to do, and we will either add it to /v1 or explain why not.
Rate limits
Read endpoints allow 120 requests per minute per IP address, and how much of that you get depends on what kind of client you are. The referral lookup allows 60 per hour per IP address whoever is asking, because it answers a question about real people to a stranger.
| Client | Reads per minute | How we tell |
|---|---|---|
| Verified agent | 480 | You signed the request with HTTP Message
Signatures (RFC 9421) and a Signature-Agent whose key directory we could read.
The most room, on purpose: a signed agent is one we can name. |
| Declared agent | 120 | Your User-Agent says what you
are. Honest and unproven, so the ordinary budget. |
| Browser | 120 | A person, or a page a person has open. |
| Anything else | 30 | No signature, no name. Slower, never blocked. Sign your requests or name yourself and this goes away. |
Every response carries the current state of your budget, so a client can slow down before it is refused rather than after:
| Header | Meaning |
|---|---|
RateLimit-Limit | Requests allowed in the current window. |
RateLimit-Remaining | Requests left in the current window. |
RateLimit-Reset | Seconds until the window resets. |
RateLimit-Policy | The window itself, for example
120;w=60. |
Retry-After | Sent only with a 429. Seconds to wait.
Honour this one and you will not see another 429. |
Versioning and deprecation
- The major version is in the path.
/v1is the only version today. - Additive changes ship without a version bump. New endpoints and new fields on an existing response can appear at any time, so parse defensively and ignore what you do not recognise.
- Nothing is removed or renamed inside a version. A breaking change means
/v2, and/v1keeps working. - When an endpoint is on its way out it answers with a
Deprecationheader and aSunsetheader giving the date it stops. The gap is at least 90 days, and the same notice goes in the changelog. - Errors are JSON with a
detailstring and a real HTTP status. A missing course or lesson is a404, never a200with an empty body.
Which CodeTrain is which?
CodeTrain is one product with one account, and there are two ways in today: the website at codetrain.ai and the CodeTrain CLI on your own machine. CodeTrain Open Skill is a separate, free tool that needs no account.
| Best for | Who teaches | Where your code goes | Account needed | |
|---|---|---|---|---|
| CodeTrain website (codetrain.ai) | Learning in your browser, on any topic you name, on any public GitHub repository, or from curated courses. The homepage also runs a real lesson with no account. | CodeTrain's tutor, which writes the lesson. | Python and JavaScript run in your browser; languages a browser cannot run, such as bash, run on CodeTrain's servers. Code you submit, and files you attach, reach CodeTrain's servers and the model provider, and are stored in your lesson. | A CodeTrain account, with a free plan and no card. |
| CodeTrain CLI | Working on the repository in your current folder, or on a practice project, from your own machine. | CodeTrain's tutor, running on your machine and serving its interface on 127.0.0.1. | Your repository stays on your machine: the CodeTrain CLI reads the checkout in place, and only the prompt snippets needed for one tutoring turn go to the model provider. CodeTrain never copies or stores the repository. Lessons stay in your project folder. | Signs in to your CodeTrain account, and your plan's limits apply. With your own model key in its config file, model calls go straight to your provider. |
| CodeTrain Open Skill | Learning inside the coding agent you already use, such as Claude Code or OpenCode. | Your agent's own model, teaching with CodeTrain's method: you write every line, and it sets the steps, gives hints and reviews your work. | The lesson page runs on 127.0.0.1. Your agent sends what it reads, your code included, to its own model provider, as it does for any task. Python runs in your browser. | No account, and nothing goes to CodeTrain: no telemetry either. Free and open source, Apache 2.0. |
Command line
The CodeTrain CLI runs the tutor locally and serves its own interface on
127.0.0.1. Install it either way round:
$ pip install codetrain-cli
$ curl -fsSL https://codetrain.ai/install.sh | sh
Both put the CodeTrain CLI in the same place and install the same launcher, so it does not matter which you pick, and using both does no harm. It keeps itself current: once a day it checks whether the published bundle changed and replaces its own copy if it did. There is nothing to reinstall to get a newer CodeTrain CLI.
Four commands need no account at all, which makes them safe for a script to call before anything is set up:
$ codetrain doctor # is the service up, is this install healthy. --json, exit 0 or 1
$ codetrain version # installed agent bundle against the published one
$ codetrain catalog # the curated courses
$ codetrain update # fetch the newest bundle now
The installer checks the bundle against a published SHA-256 before it unpacks
anything. The bundle and its checksum are at
/dist/codetrain-agent.tar.gz. The CLI needs Python and
nothing else, and it talks to https://api.codetrain.ai by default.
It keeps itself current. Once a day it checks whether the published bundle has
changed, and replaces its own copy if it has, verifying the checksum the same way the installer
does. To force it, run codetrain update. To switch it off, set
CODETRAIN_NO_UPDATE=1 and update by hand.
Machine-readable
- OpenAPI 3.1 document for the public API.
- Interactive reference, generated from the same document.
- /llms.txt, which says when to reach for CodeTrain and links every page in markdown.
- /llms-full.txt, the whole public site as one markdown file.
- /sitemap.xml for the canonical URL list.