⚙ Builder API
REST tooling for external builders on top of the Monsterion MMO: create quests with real
in-game rewards and read the live player marketplace — listings, prices, transactions.
JSON over HTTPS, versioned under /api/v1/.
Base URL & authentication
All endpoints live under the game server:
https://<worker-host>/api/v1/
Every request must carry an issued builder key (keys start with mbk_):
Authorization: Bearer mbk_xxxxxxxxxxxxxxxxxxxxxxxx
- 10 alpha keys are minted, each with a label (
builder-01…builder-10). Ask the team for yours. - Keys are verified by SHA-256 hash — the server never stores plaintext. Lose it, and a new one must be issued.
- Everything you create is stamped with your label: only you can update or retire your own quests.
- Missing/invalid key →
401 {"error":"unauthorized"}.
Quests
Builder quests appear in-game at the Tools Marketplace — the Antikythera mechanism outside the village tree ring. Players accept them there, watch objectives tick, and claim your reward.
GET /api/v1/quests
List all active builder quests (max 200, newest first).
curl -H "Authorization: Bearer $KEY" https://<host>/api/v1/quests
# → { "quests": [ { "id", "title", "lore", "objectives", "reward", "created" }, … ] }
POST /api/v1/quests
Create a quest — or update one of yours (same id, same key). Omitting id generates one.
curl -X POST https://<host>/api/v1/quests \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"id": "herbalist-trial",
"title": "The Herbalist Trial",
"lore": "Gather for the village apothecary before the frost.",
"objectives": [
{ "type": "harvest", "n": 200 },
{ "type": "craft", "n": 5 }
],
"reward": {
"slot": "trinket", "base": "charm", "rarity": "epic",
"name": "Apothecary Charm",
"flavor": "Smells faintly of every herb at once.",
"affixes": [ { "stat": "xp_gain", "val": 12 } ]
}
}'
# → { "ok": true, "id": "herbalist-trial", "builder": "builder-03" }
Request schema
| field | type | rules |
|---|---|---|
id | string? | optional; ≤48 chars; stable id = updatable quest |
title | string | required, ≤80 chars |
lore | string | required, ≤1000 chars — shown to players |
objectives | array | 1–8 of {type, n}; n 1…100000 |
reward | object | see the reward schema below |
Objective types
Objectives bind to the game's lifetime activity counters; progress counts from the moment a player accepts your quest.
| type | counts |
|---|---|
harvest | resources gathered (wood, ore, herbs, digs…) |
craft | items / consumables crafted |
trade | marketplace trades completed |
mission | Olga missions finished |
kill | boss kills (tracking expanding) |
Reward schema
| field | type | rules |
|---|---|---|
slot | string | weapon | armor | trinket | mount | consumable |
base | string | decides the 3D model: item_<base>.glb on the CDN. Reuse existing bases (charm, idol, ring, blade, plate, greataxe, …) or ship a new model with the team. |
rarity | string | common … mythic. Alpha edition caps apply: uncommon 500 · rare 250 · epic 100 · legendary 25 · mythic 8 — server-numbered like every item. |
name | string | required, ≤60 chars |
flavor | string? | italic lore line on the item |
affixes | array? | ≤6 of {stat, val} — stats: atk, def, hp, spd, crit_chance, lifesteal, magic_find, xp_gain |
GET /api/v1/quests/:id
Fetch one quest (active or retired).
curl -H "Authorization: Bearer $KEY" https://<host>/api/v1/quests/herbalist-trial
# → { "quest": { … } } | 404 { "error": "not found" }
DELETE /api/v1/quests/:id
Retire one of your quests (soft delete — it disappears from the game; players mid-quest keep their progress and the claim stays honored).
curl -X DELETE -H "Authorization: Bearer $KEY" https://<host>/api/v1/quests/herbalist-trial
# → { "ok": true }
Marketplace (read)
Live data from the in-game gold marketplace — the same server-settled trades players see.
GET /api/v1/market/listings
Listings by status: ?status=active (default) or sold. Max 300, newest first.
curl -H "Authorization: Bearer $KEY" "https://<host>/api/v1/market/listings?status=active"
# → { "listings": [ { "id": 42, "seller_name": "Rawen", "price": 1200,
# "status": "active", "created": 1783100000000,
# "item": { "slot":"weapon", "base":"blade", "rarity":"epic", … } }, … ] }
GET /api/v1/market/prices
Recent sale prices grouped by item type (base:rarity) — the exact data behind the in-game
price charts. Up to the last 500 sales.
curl -H "Authorization: Bearer $KEY" https://<host>/api/v1/market/prices
# → { "prices": { "blade:epic": [ { "price": 1150, "at": 1783099000000 }, … ] } }
GET /api/v1/market/transactions
Completed sales, newest first. ?limit= up to 500 (default 100).
curl -H "Authorization: Bearer $KEY" "https://<host>/api/v1/market/transactions?limit=50"
# → { "transactions": [ { "id", "seller_name", "price", "created", "item": { … } }, … ] }
Models — publish your own GLBs
Bring your own art: publish a textured .glb, we validate + host it, and the engine
auto-rigs and animates it at load (runtime soft-skin rig: walk, pen-wander, ride, fly for
winged models, hunt/chase). Use it in rewards via model_url.
POST /api/v1/models?name=<name>
Raw binary body. Name: 3–48 chars of [A-Za-z0-9_-]. Re-POST the same name (same key) to update.
curl -X POST "https://<host>/api/v1/models?name=crystal_stag" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/octet-stream" \
--data-binary @crystal_stag.glb
Validation: binary .glb magic · max 8 MB · textures embedded · at least one mesh.
The response includes the public url and the animation set the engine will apply.
GET /api/v1/models
List your published models (name, bytes, created).
GET /api/v1/models/:name
Public (no key) — this is the URL game clients stream. Serves model/gltf-binary, cached 1 h.
Rewards with your model
"reward": { "slot": "mount", "base": "custom", "rarity": "epic",
"name": "Crystal Stag", "model_url": "/api/v1/models/crystal_stag" }
Errors
| status | body | meaning |
|---|---|---|
400 | {"error":"…"} | validation failed — the message names the exact field and rule |
401 | {"error":"unauthorized…"} | missing or unknown builder key |
404 | {"error":"not found"} / unknown endpoint | bad id or path |
503 | {"error":"no database configured"} | server misconfiguration — tell the team |
500 | {"error":"…"} | unexpected — retry once, then report |
How it feels in-game
- Your quest appears at the ⚙ Tools Marketplace — the turning bronze Antikythera mechanism past the village tree ring.
- A player presses Accept: their activity counters snapshot, and your objectives count from zero for them.
- Objectives tick live on the quest card (
✔ Harvest: 200/200). - Claim reward grants your item for real: it lands in the bag, wears on the body, shows in the character sheet, can be socketed, traded on the gold market — and minted as an NFT at the Blacksmith.
Roadmap
Per-builder key self-service · write-side marketplace ops with player-consent tokens · custom quest locations & NPCs · webhook notifications on quest completion & sales.