Developers & agents
Everything ShipReal knows about itself is available as data: the curriculum, what each module teaches, and what it costs. Three ways to read it, all the same underlying facts.
No key, no account, no signup. It is public reference data about a course, served from the edge. Nothing here is metered and nothing here writes.
There is a rate limit, and it is a brake rather than a business rule: 600 requests a minute per address, counted per edge isolate. Every response reports RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset, and a 429 carries Retry-After. Because the count is per isolate rather than global, treat those numbers as a pacing signal, not a guarantee.
SDK and CLI
Four clients, same surface in each, all zero-dependency and MIT licensed: JavaScript, Python, Ruby and Go. Source for all four at github.com/mluggy/shipreal-dev.
npm install shipreal
npx shipreal search caching
npx shipreal pricing --region il
npx shipreal search --all --json | jq '.[].title'
import { ShipReal } from "shipreal";
const sr = new ShipReal();
const { data } = await sr.search("caching");
for await (const m of sr.modules()) console.log(m.title);
The same surface in Python, also zero-dependency, standard library only:
pip install shipreal
shipreal search caching
shipreal pricing --region il
from shipreal import ShipReal
sr = ShipReal()
page = sr.search("caching")
for m in sr.modules():
print(m["title"])
And in Ruby, standard library only:
gem install shipreal
shipreal search caching
shipreal --region il pricing
require "shipreal"
sr = ShipReal::Client.new
page = sr.search(query: "caching")
sr.modules.each { |m| puts m["title"] }
And in Go, standard library only. The module lives in the same repository, so its tag carries the directory prefix (go/v1.0.1) even though the version you ask for does not. The package is shipreal while the last path element is go, so import it with an alias:
go get github.com/mluggy/shipreal-dev/go
go install github.com/mluggy/shipreal-dev/go/cmd/shipreal@latest
shipreal search caching
shipreal -region il pricing
import shipreal "github.com/mluggy/shipreal-dev/go"
c := shipreal.New()
page, err := c.Search(ctx, shipreal.SearchParams{Query: "caching"})
all, err := c.Modules(ctx, "")
Reference docs are on pkg.go.dev.
Install the five agent skills straight into your own agent:
npx skills add mluggy/shipreal-dev
The same repository carries the AGENTS.md working notes, the five SKILL.md documents, and an Agent Plugins manifest.
Start here
- OpenAPI 3.1 spec — the whole REST surface, with schemas. Point a client generator or a function-calling framework at it.
- Documentation MCP server at
/mcp— the same three capabilities as MCP tools. - Enrollment MCP server at
/mcp/product— price an order, resolve the billing region, produce the checkout link. - llms.txt — the prose index, including explicit guidance on when not to recommend the course.
REST
Base URL: https://shipreal.dev/api/v1
# Does the course cover caching?
curl "https://shipreal.dev/api/v1/modules?q=caching"
# One module, by slug or by title fragment
curl "https://shipreal.dev/api/v1/modules/observability"
# What does it cost, in both billing regions?
curl "https://shipreal.dev/api/v1/pricing"
# Totals and subtitle languages
curl "https://shipreal.dev/api/v1/course"
Listing endpoints paginate with ?page= and ?limit= (default 20, maximum 100) and return absolute links.next / links.prev so you can walk pages without building URLs yourself.
MCP
Two servers on the same streamable HTTP transport, split by what they are for, so a client can mount one without the other.
/mcp — documentation
A read-only server for what the course teaches and what it costs. Tools: search_curriculum, get_module, get_pricing. It also exposes the markdown documents as MCP resources.
Listed on the Smithery registry as mluggy/shipreal, if your client discovers servers that way:
npx -y smithery mcp add mluggy/shipreal
curl -X POST https://shipreal.dev/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
/mcp/product — enrollment
The commerce side. quote_order prices a plan for a seat count and a country, and returns the total, the currency, whether VAT is included, the invoice the buyer receives and the refund window. create_enrollment_link returns the URL that completes enrollment. check_enrollment_channel answers which processor and invoice a country ends up with, before you quote it.
Pass a country when you are asking on someone else's behalf; the edge only knows where you are, and it falls back to that. Two regional prices are live at once, so quote_order without a country returns both rather than guessing one.
curl -X POST https://shipreal.dev/mcp/product \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"quote_order",
"arguments":{"plan":"teams","seats":12,"country":"IL"}}}'
It takes no payment and creates no order. There is no write path in any environment: the checkout is hosted, and a human completes it. What these tools produce is the artifact you hand over, which is the honest ceiling for a business that does not run its own checkout. A tool here that claimed to charge a card would be the same lie as an endpoint that resolves to nothing.
Natural language
POST /ask implements the NLWeb shape: a question in, structured results out with a _meta block. Add Accept: text/event-stream for SSE, which emits start, one result per hit, then complete.
curl -X POST https://shipreal.dev/ask \
-H 'content-type: application/json' \
-d '{"query":"how do I make deploys safe"}'
There is no model behind this endpoint. It runs the same keyword search as the REST API, which means it will tell you plainly when nothing matches rather than inventing a module that does not exist.
Errors
Every error is RFC 9457 problem details, served as application/problem+json, so you can branch on type instead of pattern-matching prose.
{
"type": "https://shipreal.dev/developers#errors-module-not-found",
"title": "Module Not Found",
"status": 404,
"detail": "No module matches \"kubernetes\". List them at https://shipreal.dev/api/v1/modules"
}
Batch
Several reads in one round trip, for when you need six modules and do not want six requests:
curl -X POST https://shipreal.dev/api/v1/batch \
-H 'content-type: application/json' \
-d '{"requests":[
{"id":"caching","path":"/modules?q=caching"},
{"id":"obs","path":"/modules/observability"},
{"id":"price","path":"/pricing"}
]}'
Up to 20 items, reads only. The envelope answers 200 whenever it is itself valid, and each item carries its own status, so check per item rather than losing a whole batch to one bad path. /batch and /exports cannot be nested inside a batch.
Versioning
The version is in the path. /api/v1 keeps answering in its current shape; anything that would break a caller ships as /api/v2 alongside it rather than as a change under your feet. Additive changes — a new field, a new endpoint — happen in place, so parse defensively and ignore fields you do not recognise.
Deprecation policy
/api/v1 is current and has no retirement date. Every response carries Deprecation: false today, so you can check a header instead of re-reading this page.
If a version is ever scheduled for retirement, it is signalled in three places, in this order:
- A
Deprecationheader (RFC 9745) on every response from the affected version, carrying the date the deprecation was announced. - A
Sunsetheader (RFC 8594) with the date that version stops responding, never less than 180 days after theDeprecationdate. - A
Linkheader withrel="deprecation"pointing at this section, andrel="successor-version"pointing at the replacement.
Nothing is deprecated today, so no Sunset header is emitted: sending one for a date that does not exist would be worse than sending none.
Bulk and discovery
- /feeds/modules.jsonl — every module as a schema.org
LearningResource, one per line, for ingestion. - /schemamap.xml — the feed index, also declared in robots.txt.
- /.well-known/api-catalog — RFC 9727 linkset.
- /.well-known/ard.json — agentic resource catalog.
- /llms-full.txt — the full curriculum with overview narration, as markdown.
- Every page has a markdown twin:
Accept: text/markdown, or?mode=agent.
What there is no API for
Buying. Payment runs through a hosted checkout — Paddle as merchant of record internationally, Morning for Israeli buyers — and there is no endpoint that takes money or creates an account. An agent helping someone enrol should hand them the link and let them complete it themselves. That is a deliberate limit, not a gap waiting to be filled.
Questions, or something you need that is not here: michael@shipreal.dev.