{"service":"foam-dungeon api","contract":"https://foam.mino.mobi/dungeon/FORMAT.md","endpoints":{"/api/dungeon":{"returns":"canonical foam-dungeon JSON (the map)","params":{"seed":"int ≥1 (default 1)","n":"endpoints 1–6 (default 3)","shape":"grid|hex|penrose|ammann|seven|rhombille|snub|kagome|rhombitri|truncsq (default grid)","scale":"tile scale 0.08–1 (default 0.35)","size":"s|m|l|xl (default m)","twin":"1 = the intertwined pair (two disjoint dungeons, one foam)","starts":"2–4 = confluence: k far-apart starts descending to ONE shared chamber, routes sharing no chamber until they arrive. CPU-heavy (the generator searches foams until one can carry k disjoint descents) — often exceeds the edge limit; import the modules for this mode."},"versions":{"dungeon":4,"servable":[4]},"pinning":"v=<version> pins the generator: served exactly, or 409 naming what is available — geometry is never silently substituted. Omit (or v=latest) for current. Every response carries x-dungeon-version and x-layout-signature (the geometry fingerprint) so a saved artefact can detect drift."},"/api/content":{"returns":"foam-dungeon-content JSON (the roll) for the same map params","params":{"roll":"int ≥1 (default 1) — reroll without touching the map","tune":"lo,tr,ob,en,tf,gr — the forge tuning block (optional)","…":"plus every /api/dungeon param, to name the map"},"versions":{"dungeon":4,"content":4,"servable":{"dungeon":[4],"content":[4]}},"pinning":"v=<version> pins the map generator, cv=<version> the content roller; either unservable is a 409."}},"determinism":"same params → byte-identical response, immutable per version; responses are edge-cached","note":"generation is CPU-bound: s/m/l summon reliably; xl can exceed the edge CPU limit (a 503 with Cloudflare error 1102 — not retryable, the work is deterministic). For xl, import the modules instead: https://foam.mino.mobi/dungeon.mjs (CORS-open, node ≥18 or browser)."}