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

MethodPathReturns
GET/v1/healthLiveness and the current API version.
GET/v1/catalogEvery 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/changelogWhat shipped, newest first. The same entries as /changelog/.
GET/v1/roadmapRoadmap 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": "tutor-examples-2026-08-28", "date": "2026-08-28", "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 [email protected] 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. The referral lookup allows 60 per hour per IP address, because it answers a question about real people to a stranger.

Every response carries the current state of your budget, so a client can slow down before it is refused rather than after:

HeaderMeaning
RateLimit-LimitRequests allowed in the current window.
RateLimit-RemainingRequests left in the current window.
RateLimit-ResetSeconds until the window resets.
RateLimit-PolicyThe window itself, for example 120;w=60.
Retry-AfterSent only with a 429. Seconds to wait. Honour this one and you will not see another 429.

Versioning and deprecation

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 agent 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 agent.

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

Open the API reference All documentation