Eulernen API for developers and agents
Eulernen publishes its catalogue of all 22 learning poster sets (eleven sets, each in two styles) through open interfaces. All of them are public, read-only and need no sign-in: there are no API keys, no account and no sandbox, because no request changes anything. Prices, ordering and buying are only available on Etsy.
| Interface | Address | Purpose |
|---|---|---|
| Catalogue API | GET https://eulernen.de/api/v1/catalog.json | all sets as JSON |
| Query API | GET https://eulernen.de/api/v1/sets | filter sets by subject, grade, edition and style |
| MCP server | POST https://eulernen.de/mcp | tools list_sets and get_set |
| A2A agent | POST https://eulernen.de/a2a | find sets for a request written in German |
| WebMCP | home pages https://eulernen.de/ and https://eulernen.de/en/ | the same tools for agents in the browser |
Catalogue API
One JSON file with all sets: subject, grades, edition, style and poster titles, plus delivery
options, licence and shop link. You filter the file yourself; the
query API filters on the server. The
OpenAPI description (OpenAPI 3.1, operationId
getCatalog) describes the response and errors with schemas. Cross-origin requests
are allowed (Access-Control-Allow-Origin: *).
curl -s https://eulernen.de/api/v1/catalog.json
{
"name": "Eulernen",
"shop": "https://www.etsy.com/shop/Eulernen",
"sets": [
{
"id": "mathe12",
"name": "Mathe-Lernposter Klasse 1/2",
"subject": "Mathe",
"grades": [1, 2],
"edition": null,
"style": "Klassisch",
"posterCount": 12,
"posters": ["Zahlen bis 20", "Zahlen zerlegen", …]
},
…
]
}
Names, poster titles and field values are in German, as on the posters.
Query API
Filters the sets on the server. GET /api/v1/sets (operationId
listSets) takes the optional parameters subject (Mathe, Deutsch,
Englisch, HSU), grade (1 to 4), edition (Bayern, Allgemein) and
style (Klassisch, Aquarell). The response contains the matching sets without
poster titles, plus the shop link and the current sales status. GET /api/v1/sets/{id}
(getSet) returns one set with all poster titles. Unknown parameters or values
return 400, an unknown id returns 404, both as problem+json.
| Value | Meaning |
|---|---|
Mathe, Deutsch, Englisch | Maths, German, English |
HSU | science and social studies (Heimat- und Sachunterricht) |
Bayern, Allgemein | Bavaria edition (Bavarian curriculum, LehrplanPLUS), general edition |
Klassisch, Aquarell | classic, watercolour |
curl -s 'https://eulernen.de/api/v1/sets?subject=Mathe&grade=2&edition=Bayern'
{
"sets": [
{
"id": "mathe12_bayern",
"name": "Mathe-Lernposter Klasse 1/2 · Bayern",
"subject": "Mathe",
"grades": [1, 2],
"edition": "Bayern",
"style": "Klassisch",
"posterCount": 16
},
…
],
"shop": "https://www.etsy.com/shop/Eulernen",
"availability": "Verkauft wird nur über Etsy; …"
}
curl -s https://eulernen.de/api/v1/sets/mathe12_bayern_aquarell
{
"set": {
"id": "mathe12_bayern_aquarell",
"posterCount": 16,
"posters": ["Zahlen bis 20", …],
…
},
"shop": "https://www.etsy.com/shop/Eulernen",
"availability": "…"
}
MCP server
Streamable HTTP at https://eulernen.de/mcp, stateless, for protocol versions
2026-07-28, 2025-11-25, 2025-06-18 and 2025-03-26. An MCP client only needs the URL, with no
OAuth and no API key. Metadata is in the
MCP Server Card.
list_sets: search sets, optionally bysubject(Mathe, Deutsch, Englisch, HSU),grade(1 to 4),edition("Bayern"or"Allgemein";nullstill counts as Allgemein) andstyle(Klassisch, Aquarell)get_set: one set with all poster titles, parameterid
curl -s https://eulernen.de/mcp -H 'Content-Type: application/json' -d '{
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": "list_sets", "arguments": {"subject": "Mathe", "grade": 2, "edition": "Bayern"}}
}'
A2A agent
JSON-RPC at https://eulernen.de/a2a with SendMessage (A2A 1.0)
and message/send (A2A 0.3). The agent reads subject, grade, Bavaria and style from
a request written in German, without a language model, and replies with text and JSON data.
Described in the A2A Agent Card.
curl -s https://eulernen.de/a2a -H 'Content-Type: application/json' -H 'A2A-Version: 1.0' -d '{
"jsonrpc": "2.0", "id": 1, "method": "SendMessage",
"params": {"message": {"messageId": "1", "role": "ROLE_USER", "parts": [{"text": "Mathe Klasse 2 Bayern"}]}}
}'
WebMCP
The home pages https://eulernen.de/ and https://eulernen.de/en/ load webmcp.js.
In browsers with WebMCP (document.modelContext or navigator.modelContext)
it registers the tools list_sets and get_set; both read
/api/v1/catalog.json.
Discovery files
| File | Content |
|---|---|
| llms.txt | overview and “when to use” for language models |
| index.md | German home page as Markdown, also via Accept: text/markdown on / |
| .well-known/ard.json | Agent Resource Discovery (ARD) with skill, MCP server and A2A agent; also at /.well-known/ai-catalog.json |
| .well-known/agent-skills/index.json | Agent Skills with SHA-256 digest, points to SKILL.md |
| .well-known/api-catalog | API catalogue as defined in RFC 9727 |
| api/openapi.json | OpenAPI 3.1 for the catalogue and query APIs |
| .well-known/mcp/server-card.json | MCP Server Card |
| .well-known/agent-card.json | A2A Agent Card |
| auth.md | access: no registration, no credentials |
Errors
Errors under /api/ are returned as application/problem+json as defined in RFC 9457,
with type, title, status, detail,
instance and resolution, a hint on what to do next. In the
OpenAPI description, every error response refers to the same schema Problem.
| Status | When |
|---|---|
| 400 | unknown parameter or value on /api/v1/sets |
| 404 | unknown path or unknown set id |
| 405 | any method other than GET and HEAD, with Allow: GET, HEAD |
| 429 | rate limit exceeded, with Retry-After |
curl -i https://eulernen.de/api/v2/catalog.json
HTTP/2 404
content-type: application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Nothing is published at /api/v2/catalog.json.",
"instance": "/api/v2/catalog.json",
"resolution": "GET https://eulernen.de/api/v1/catalog.json returns the catalogue, …"
}
Other unknown addresses also answer with 404: as an HTML page, with
Accept: text/markdown as Markdown with links to llms.txt and the sitemap, and with
Accept: application/json as problem+json. MCP and A2A report errors as
JSON-RPC error objects.
Rate limit
/api/, /mcp and /a2a share one limit of 60
requests per 60 seconds per client IP. Every response there states the rule in the
RateLimit-Policy header, following the IETF draft draft-ietf-httpapi-ratelimit-headers
(q = requests, w = seconds):
RateLimit-Policy: "default";q=60;w=60
Above that, the server answers with 429 as application/problem+json and
Retry-After: 60; after this wait, requests work normally again. Requests are
counted per Cloudflare location and with a short delay, so the limit is approximate. There is
no RateLimit header with the remaining requests, because the counter does not
report them.
Versioning
- The major version is in the path:
/api/v1/. - Changes within v1 stay backwards compatible; new fields may be added.
- An incompatible change gets a new path, such as
/api/v2/. The old path stays available and is announced with the headersDeprecation(RFC 9745) andSunset(RFC 8594) before it is switched off. /api/catalog.jsonis an alias of/api/v1/catalog.json.- MCP and A2A negotiate their protocol version themselves (
MCP-Protocol-Version,A2A-Version).
Access
No sign-in, no API key, no sandbox: the interfaces are public and read-only. None of them can be used to buy, order or change anything. Buying happens only on Etsy, and an agent buys nothing unless the user explicitly confirms the item and the total price. Details are in auth.md.
Contact
Send questions about the interfaces to info@eulernen.de.