All examples assume your key is available server-side as MOCA_API_KEY.
A tiny typed client (TypeScript)
Code
const BASE = "https://api.moca.qwellco.de/v1";async function moca<T>(path: string, params?: Record<string, string>): Promise<T> { const url = new URL(BASE + path); for (const [k, v] of Object.entries(params ?? {})) url.searchParams.set(k, v); const res = await fetch(url, { headers: { "X-API-Key": process.env.MOCA_API_KEY! }, }); if (!res.ok) { const body = await res.json().catch(() => null); throw new Error(body?.errors?.[0]?.message ?? `MOCA API ${res.status}`); } return (await res.json()).data as T;}// Usageconst collections = await moca<Collection[]>("/collections");const artworks = await moca<Artwork[]>("/artworks", { collection: "genesis", limit: "50",});
Rendering artworks correctly
The cardinal rule: respect the ratio. Works are portraits, panoramas,
videos — never assume squares.
Code
function ArtworkFigure({ art }: { art: Artwork }) { if (art.animation) { return ( <video src={art.animation.url} muted loop autoPlay playsInline style={{ aspectRatio: art.ratio }} /> ); } if (!art.media) return null; return ( <figure> {/* width/height (when present) give the browser layout hints; the decoded file's own ratio always wins visually. */} <img src={art.media.url} width={art.media.width} height={art.media.height} alt={art.name ?? "Artwork"} loading="lazy" style={{ maxWidth: "100%", height: "auto" }} /> <figcaption> {art.name} {art.artist_name ? `— ${art.artist_name}` : ""} </figcaption> </figure> );}
Media can be heavy
media.url points at original files — sometimes multi-megabyte PNGs or
IPFS-hosted assets. For thumbnails, resize through your own image proxy or
CDN rather than shipping originals to every visitor.
Python
Code
import os, requestsBASE = "https://api.moca.qwellco.de/v1"HEADERS = {"X-API-Key": os.environ["MOCA_API_KEY"]}def artworks(collection: str | None = None, page: int = 1, limit: int = 25): params = {"page": page, "limit": limit} if collection: params["collection"] = collection r = requests.get(f"{BASE}/artworks", headers=HEADERS, params=params, timeout=30) r.raise_for_status() body = r.json() return body["data"], body["meta"]works, meta = artworks(collection="genesis")print(f"{meta['total']} works; first: {works[0]['name']} ({works[0]['ratio']:.2f})")
At 100 items/request and 120 requests/minute, a full catalog sync stays
comfortably inside the rate limit. Cache the result — the catalog changes on
the timescale of hours, not seconds.
Building agents on DeCC0s
Each DeCC0 is a fully-written character: biography, voice, personality,
philosophy. include=profiles adds ready-to-use agent persona blobs:
GET /v1/rooms → pick a room, download model_optimized_url (a
draco-compressed GLB that always carries slots — un_MUSEUM sculptures get
theirs generated from the onchain slot amount). model_url is the untouched
high-quality original for hero/detail rendering.
Find meshes named Slot_001…Slot_NNN — their transforms are wall anchors,
their bounding boxes the frame size.
GET /v1/artworks → fit each work into a slot preserving ratio
(letterbox inside the slot rectangle).
For video works, use the animation.url as a video texture — muted and
looping.
That's the entire recipe behind the museum's own world builder.