API
Public HTTP endpoints for the wiki. Validate world JSON against the live V36 schema, fetch section docs and schema fragments, or pull the full wiki as JSON or Markdown. Designed for AI agents, but you can hit them from any script or terminal.
Heads up: these endpoints are CORS-open, unauthenticated, and free to use. If you build automation on top of them, please be a good neighbour — cache aggressively for the GET endpoints (they only change when the wiki redeploys) and avoid runaway loops on /validate.
Overview
All endpoints share the same base URL and conventions:
- Base URL:
https://api.unofficial.voyage - CORS: open to all origins — safe to call from any web page, terminal, or agent runtime.
- Auth: none. The wiki is a public reference.
- Versioning: every endpoint serves the currently deployed wiki. The validator endpoint returns its
validatorVersionin the response body.
Quick reference
| Endpoint | Method | Purpose |
|---|---|---|
/validate | POST | Validate a world JSON. Returns errors, warnings, and recommendations. |
/ | GET | Manifest of every API endpoint. |
/sections.json | GET | Lightweight index of every documented section. |
/sections/<section>.json | GET | One section — prose, field notes, schema fragment. |
/sections/<section>.md | GET | Same as above, formatted as Markdown. |
/wiki.json | GET | Entire wiki, all sections in one payload (JSON). |
/wiki.md | GET | Entire wiki concatenated as Markdown. |
/schema.json | GET | Raw V36 codec schema. |
POST /validate
Validates a world JSON against the live V36 schema plus every semantic check the in-browser Validator performs — cross-references, enum validity, size limits, runtime-affecting authoring patterns. Output is identical to the in-browser tool.
Request
Content-Type: application/json- Body: the world JSON object (the same JSON you would paste into the Voyage editor).
Response
JSON object with:
counts—{ errors, warnings, recommendations }totals.errors— array of{ path, title, fix, detail?, value?, message }. If any are present, Voyage rejects the world — it won't pass validation or load (missing required fields, broken references, invalid values, malformed JSON). Zero errors means Voyage will accept it.warnings— array of the same shape. Might break at runtime — behaviour degraded, fragile, or silently wrong.recommendations— array of the same shape. Might improve quality — missing optional context the AI would benefit from. Safe to ignore by design.validatorVersion— ISO-8601 timestamp of the currently deployed validator.
Example (curl)
curl -X POST https://api.unofficial.voyage/validate \
-H 'Content-Type: application/json' \
--data-binary @MyWorld.jsonExample (JavaScript)
const result = await fetch('https://api.unofficial.voyage/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(world),
}).then(r => r.json());
console.log(result.counts);
result.errors.forEach(({ path, message }) => console.log(path, message));Example (Python)
import json, urllib.request
with open('MyWorld.json', 'rb') as f:
body = f.read()
req = urllib.request.Request(
'https://api.unofficial.voyage/validate',
data=body,
headers={'Content-Type': 'application/json'},
)
result = json.loads(urllib.request.urlopen(req).read())
print(result['counts'])GET /sections.json
Lightweight index of every documented section — section key, title, tab, summary. No body content. Good for an agent to enumerate before fetching specific sections.
curl https://api.unofficial.voyage/sections.jsonGET /sections/<section>.json or .md
One section, fully self-contained. The .json form returns structured data; the .md form returns Markdown formatted for direct ingestion by an LLM. Both contain section metadata, the full prose body, per-field notes, and the V36 schema fragment for that section.
curl https://api.unofficial.voyage/sections/npcs.json
curl https://api.unofficial.voyage/sections/locations.mdGET /wiki.json or .md
The entire wiki in one payload — useful when an agent wants the full V36 reference loaded into its context in a single request. The Markdown form is typically the better fit for LLM ingestion.
curl https://api.unofficial.voyage/wiki.json
curl https://api.unofficial.voyage/wiki.mdGET /schema.json
Raw V36 codec schema as JSON — the same schema fragments embedded in the section endpoints, aggregated.
curl https://api.unofficial.voyage/schema.jsonMirror the wiki for an offline agent
Some agents — notably ChatGPT and Codex in long-running threads — intermittently fail to fetch live URLs they should be able to reach. Mirroring the wiki to local disk once sidesteps that entirely: the agent reads from files instead of fetching. This pulls the top-level payloads plus every section, driving the section loop from /sections.json so it never goes stale when sections are added or removed.
set -e
base='https://api.unofficial.voyage'
out='./voyage-wiki' # change to your docs folder
mkdir -p "$out/sections"
curl -sSL "$base/" -o "$out/manifest.json"
curl -sSL "$base/sections.json" -o "$out/sections.json"
curl -sSL "$base/schema.json" -o "$out/schema.json"
curl -sSL "$base/wiki.json" -o "$out/wiki.json"
curl -sSL "$base/wiki.md" -o "$out/wiki.md"
# Drive the per-section loop from the live manifest (requires jq) so it never goes stale
curl -sSL "$base/sections.json" | jq -r '.[].section' | while read -r s; do
curl -sSL "$base/sections/$s.md" -o "$out/sections/$s.md"
doneOn Windows, the bash version needs Git Bash or WSL. PowerShell does the same thing natively with no jq dependency, since it parses JSON for you:
$base = 'https://api.unofficial.voyage'
$out = './voyage-wiki' # change to your docs folder
New-Item -ItemType Directory -Force -Path "$out/sections" | Out-Null
Invoke-WebRequest "$base/" -OutFile "$out/manifest.json"
Invoke-WebRequest "$base/sections.json" -OutFile "$out/sections.json"
Invoke-WebRequest "$base/schema.json" -OutFile "$out/schema.json"
Invoke-WebRequest "$base/wiki.json" -OutFile "$out/wiki.json"
Invoke-WebRequest "$base/wiki.md" -OutFile "$out/wiki.md"
# Section loop driven from the live manifest, so it never goes stale
Invoke-RestMethod "$base/sections.json" | ForEach-Object {
Invoke-WebRequest "$base/sections/$($_.section).md" -OutFile "$out/sections/$($_.section).md"
}If you only need the full reference in one file, skip the loop entirely and fetch /wiki.md — it bundles every section into a single Markdown document. The per-section mirror is for agents that want to open one topic at a time.
Agent prompt snippet
Drop this into your agent's system prompt or task instructions so it validates as it works:
You are authoring or editing a Voyage V36 world JSON.
Reference docs: every wiki section is available as a self-contained
endpoint at https://api.unofficial.voyage/sections/<section>.md or .json. Fetch only the
sections you need, or pull the whole wiki from https://api.unofficial.voyage/wiki.md in one request.
Verification: POST the JSON to https://api.unofficial.voyage/validate. The response groups
issues by severity:
- errors: runtime-affecting problems. Fix these.
- warnings: quality issues. Many are intentional; read the
"Safe to ignore when..." line before acting.
- recommendations: best-practice suggestions, same rule as warnings.
Validate after each batch of changes. Do not declare work complete
until counts.errors is 0.Conventions and notes
- Backtick chips in messages. Validator messages use backtick-wrapped tokens to mark field names and values, so agents can parse them as code-like literals.
- Path notation. Validator
pathvalues use dot/bracket notation into the world JSON — e.g.locations.Acorn Hall.factions[0],npcs.Maren Halst.type. - Identical surfaces. The in-browser validator and this endpoint share the same engine. Output is identical across both.
- No write endpoints. The wiki is read-only. Validation does not modify the submitted JSON.