# MOCA API > Complete documentation for Large Language Models --- ## Document: Web3 & agents SOUL files, signature verification, and the ERC-8004 / ERC-8183 / ERC-8257 agent stack URL: /web3 # Web3 & agents import { Callout } from "zudoku/ui/Callout"; The MOCA ecosystem treats NFTs as **agents-in-waiting**: every Art DeCC0 (and any collection onboarded through [Soulweaver](https://soulweaver.museumofcryptoart.com)) carries a generated personality codex and a portable identity document — the **SOUL file**. This page is for builders wiring those identities into the emerging onchain agent stack. ## SOUL files A SOUL file is a markdown identity document (identity, appearance, voice, personality, behavioral directives) generated from the token's onchain traits plus community lore, then: - hashed with **keccak256** (`contentHash`) - signed by the platform key via **EIP-191** `personal_sign` (`signature`, `signerAddress`) - pinned to **IPFS** (`ipfsCid`) so it outlives any single server Fetch one through the MOCA API: ```bash curl -H "X-API-Key: moca_YOUR_KEY" \ "https://api.moca.qwellco.de/v1/souls/1/0xCONTRACT/42" ``` ## Verifying authenticity Every response includes a `verification` block. The signed message binds the content hash to the token's onchain coordinates and codex version: ``` {contentHash}|{chainId}:{contractAddress}:{tokenId}|codex-v{version} ``` Verification with [viem](https://viem.sh): ```ts import { recoverMessageAddress, keccak256, toBytes } from "viem"; const { data } = await getSoul(1, contract, tokenId); // 1. The content actually hashes to the committed hash const hash = keccak256(toBytes(data.soul.content)); if (hash !== data.soul.contentHash) throw new Error("content tampered"); // 2. The EIP-191 signature recovers to the platform signer const signer = await recoverMessageAddress({ message: data.verification.message, signature: data.soul.signature, }); if (signer.toLowerCase() !== data.soul.signerAddress.toLowerCase()) { throw new Error("bad signature"); } ``` Two checks, no trust in the API required — the same verification works against the IPFS copy. ## The onchain agent stack Three draft ERCs define how agent identities like SOULs plug into open economies. SOUL files were designed with all three in mind: ### ERC-8004 — Trustless Agents An identity / reputation / validation registry triad: agents are discoverable onchain (ERC-721-based identity), accumulate client feedback, and can have work validated. **Integration pattern:** register an agent whose metadata points at the SOUL file's IPFS CID — the EIP-191 signature chain proves the personality document belongs to that token. Soulweaver reserves `mintedAgentId` per SOUL and `agentRegistryAddress` per collection for exactly this registration. ### ERC-8183 — Agentic Commerce Job escrow with evaluator attestation (Open → Funded → Submitted → Terminal). **Integration pattern:** when a SOUL-derived agent takes work, the job's descriptor references the agent's identity (8004 id or SOUL coordinates), so clients know *who* they hired — voice, values, and capabilities are all in the SOUL document. ### ERC-8257 — Agent Tool Registry A minimal onchain registry of agent tools with predicate-based access control and manifest-hash commitments. **Integration pattern:** the MOCA API itself is a natural tool entry — a manifest describing these endpoints, priced and access-controlled onchain, lets 8257-aware agents discover and query the museum autonomously. All three ERCs are Standards-Track drafts; interfaces may shift. The stable ground today is the SOUL file format and its EIP-191 verification chain — build on those, and treat registry integration as a thin layer on top. ## Building an agent from a soul The fastest path to a *running* agent, no chain required: ```ts const { data } = await getSoul(1, DECC0S_CONTRACT, tokenId); const agent = await llm.chat({ system: data.soul.content, // the SOUL.md IS the system prompt messages: [{ role: "user", content: "Introduce yourself." }], }); ``` Pair it with the [Library](/library) (`/v1/library/ask`) for grounded museum knowledge, and `/v1/decc0s/:id?include=profiles` for structured persona data (adjectives, lore, writing style) when you need more than markdown. ## Ownership-aware experiences Souls are public; *control* is onchain. To gate actions to the current holder, read `ownerOf(tokenId)` from the contract (the soul response also carries a cached `ownerAddress`) and have the user prove the address with a standard wallet signature — the usual SIWE flow. The MOCA API deliberately stays read-only: writes belong to your contracts and your users' wallets. --- ## Document: MOCA Skills Ground-truth skill files your AI agents fetch before building URL: /skills # MOCA Skills import { Callout } from "zudoku/ui/Callout"; AI models hallucinate APIs they half-remember. **MOCA Skills** fixes that: curated, always-current `SKILL.md` files your agents fetch over plain HTTP *before* writing an integration. Each skill is a short, self-contained markdown document — working `curl` examples, exact response shapes, and the rendering/verification rules that actually matter — maintained alongside the code it describes. The pattern follows [ethskills.com](https://ethskills.com/) and [cortexskills.org](https://cortexskills.org/), bringing everything MOCA under one umbrella. ## How it works One index file orients the agent; seven focused skills carry the depth. The loop your agent should run: 1. **Read the index** — [`/SKILL.md`](/SKILL.md) explains the whole map and summarizes every skill. 2. **Fetch the skills relevant to the task** — artworks for rendering, exhibitions for 3D, souls for agent identity, and so on. 3. **Verify before shipping** — cross-check endpoints against [`/llms-full.txt`](/llms-full.txt) or the [OpenAPI reference](/api). Tell your agent (Claude, Cursor, ChatGPT, your own): > Read `https://docs.museumofcryptoart.com/SKILL.md`, then fetch the skills > relevant to the task before writing any code. Verify endpoints against > `/llms-full.txt`. ## The skills | Skill | URL | Teaches | | --- | --- | --- | | **Index** | [`/SKILL.md`](/SKILL.md) | Orientation + the whole map | | API fundamentals | [`/skills/api/SKILL.md`](/skills/api/SKILL.md) | Auth, envelope, limits, every endpoint | | Artworks & media | [`/skills/artworks/SKILL.md`](/skills/artworks/SKILL.md) | Original-ratio rendering rules | | Art DeCC0s | [`/skills/decc0s/SKILL.md`](/skills/decc0s/SKILL.md) | Personas, profiles, agent recipes | | Library Cortex | [`/skills/library/SKILL.md`](/skills/library/SKILL.md) | RAG ask/stream/search + presence | | Souls & web3 | [`/skills/souls/SKILL.md`](/skills/souls/SKILL.md) | SOUL verification, ERC-8004/8183/8257 | | Exhibitions & Hyperfy | [`/skills/exhibitions/SKILL.md`](/skills/exhibitions/SKILL.md) | Slot convention, baked slot data, spawning worlds | | Museum guide | [`/skills/museum-guide/SKILL.md`](/skills/museum-guide/SKILL.md) | Be the exhibition guide: context, suggestions, visitor Q&A | Two kinds of skill live here. The first six are **integration skills** — knowledge an agent reads before calling the MOCA API. The **museum guide** is a *behavioral* skill: it ships cortexskills.org-style frontmatter and installs into Cortex as an agent skill, teaching an agent to act as a MOCA exhibition guide (read a spawned exhibition's context, suggest questions, answer visitors, adopt Art DeCC0 personas). The skills handbook is part of the museum's own knowledge base — the [Library](https://museumofcryptoart.com/library) can explain MOCA Skills, point you at the right skill file, and answer integration questions with citations. ## Machine-readable docs - [`/llms.txt`](/llms.txt) — index of these docs for LLMs - [`/llms-full.txt`](/llms-full.txt) — the complete documentation in one file - [`/api`](/api) — interactive OpenAPI reference Sibling knowledge layers your agents can combine with MOCA Skills: [docs.decc0s.com/llms-full.txt](https://docs.decc0s.com/llms-full.txt), [docs.cortex.eco/llms-full.txt](https://docs.cortex.eco/llms-full.txt), [cortexskills.org](https://cortexskills.org/), and [ethskills.com](https://ethskills.com/). --- ## Document: Quickstart Your first MOCA API calls in two minutes URL: /quickstart # Quickstart import { Callout } from "zudoku/ui/Callout"; import { Stepper } from "zudoku/ui/Stepper"; 1. **Check the API is reachable** The index route works without a key and lists every endpoint: ```bash curl "https://api.moca.qwellco.de/v1" ``` 1. **Authenticate** Send your MOCA API key on every other request — either header works: ```bash curl -H "X-API-Key: moca_YOUR_KEY" \ "https://api.moca.qwellco.de/v1/collections" ``` ```bash curl -H "Authorization: Bearer moca_YOUR_KEY" \ "https://api.moca.qwellco.de/v1/collections" ``` 1. **Browse artworks** Page through a collection (use the `slug` from the previous step): ```bash curl -H "X-API-Key: moca_YOUR_KEY" \ "https://api.moca.qwellco.de/v1/artworks?collection=genesis&page=1&limit=10" ``` Each artwork carries render-ready media: ```json { "id": 3643, "name": "Tree of Origins", "artist_name": "…", "media": { "url": "https://ipfs.pixura.io/ipfs/Qmf…", "type": "image", "width": 1026, "height": 1431 }, "animation": null, "ratio": 0.717, "opensea_url": "https://opensea.io/assets/…" } ``` 1. **Meet the DeCC0s** The Art DeCC0s knowledge base is aggregated into the same API: ```bash curl -H "X-API-Key: moca_YOUR_KEY" \ "https://api.moca.qwellco.de/v1/decc0s/1?include=profiles" ``` 1. **Search everything** ```bash curl -H "X-API-Key: moca_YOUR_KEY" \ "https://api.moca.qwellco.de/v1/search?q=butterfly" ``` Every endpoint has a live playground in the [API Reference](/api) — plug in your key and experiment without writing a line of code. ## What's next? - [Authentication & rate limits](/authentication) - [How the system works](/architecture) - [Integration recipes](/integration) --- ## Document: Library Cortex Ask questions against the museum's knowledge base URL: /library # Library Cortex import { Callout } from "zudoku/ui/Callout"; The **MOCA Library** is the museum's knowledge base — writings, curated lore, artist interviews, historical documents — indexed by [Cortex](https://cortex.eco) into a hybrid vector + knowledge-graph retrieval system. The MOCA API exposes its read surface, so your software can ask grounded, **cited** questions about crypto art without running any RAG infrastructure of your own. ## Ask a question ```bash curl -X POST "https://api.moca.qwellco.de/v1/library/ask" \ -H "X-API-Key: moca_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "question": "What is the significance of the Genesis Collection?" }' ``` The answer arrives with its receipts: ```json { "data": { "answer": "Based on the available reference material, …", "sources": [ { "document_id": "…", "content": "the cited excerpt…", "score": 0.92, "metadata": { "filename": "moca-history.md" } } ] } } ``` **Options:** `collection_id` scopes the question to one Library collection (`GET /v1/library/collections` lists them), `top_k` controls retrieval depth, `use_graph: false` skips knowledge-graph context for faster answers, and `conversation_history` carries prior turns for follow-ups. ## Streaming (SSE) For chat UX, `POST /v1/library/ask/stream` answers as Server-Sent Events: ```ts const res = await fetch(`${BASE}/library/ask/stream`, { method: "POST", headers: { "X-API-Key": KEY, "Content-Type": "application/json" }, body: JSON.stringify({ question, use_agentic: true }), }); const reader = res.body!.getReader(); const decoder = new TextDecoder(); let buffer = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); for (const frame of buffer.split("\n\n")) { if (!frame.startsWith("data: ")) continue; const event = JSON.parse(frame.slice(6)); if (event.content) process.stdout.write(event.content); // token if (event.thinking) console.log("[thinking]", event.thinking); if (event.sources) renderCitations(event.sources); if (event.done) return; } buffer = buffer.slice(buffer.lastIndexOf("\n\n") + 2); } ``` Event types you'll see: `{content}` token chunks, one `{sources: [...]}`, `{graph_context}` (entities/relationships used), and — in **deep research mode** (`use_agentic: true`) — `{thinking}` steps and `{sub_questions}`. Research streams legitimately run for minutes; don't buffer them through proxies. `POST /v1/library/search` runs the same hybrid retrieval but skips the LLM — scored excerpts only, fast and cheap. Perfect when you want to build your own presentation (or feed your own model). ## The chat in these docs The floating **Ask the Library** window (bottom-right of every page here) is this API, eating its own dog food — with a deliberate privacy model: - **Your conversations never leave your device.** History lives in your browser's localStorage; there are no accounts and no server-side history. - **Presence is ephemeral.** The little list of handles that "searched since you arrived" comes from `/v1/presence` — an in-memory broadcast that the server relays and forgets. You only experience what happens while you (or your agent) are present; nothing is stored, nothing can be replayed. - **Only handles travel.** When you ask, the widget pings presence with your chosen handle (or "anon") — never the question itself. Agents are first-class citizens here: point yours at [`/skills/library/SKILL.md`](/skills/library/SKILL.md) and it can ask the Library, watch presence, and collaborate with the humans in the room on integrations. ## What's in the Library? ```bash curl -H "X-API-Key: moca_YOUR_KEY" \ "https://api.moca.qwellco.de/v1/library/collections" ``` Each collection reports its document and entity counts. Want something indexed that isn't there? Talk to the MOCA team — the Library grows by curation. --- ## Document: MOCA API The unified public API of the Museum of Crypto Art URL: /introduction # MOCA API import { Callout } from "zudoku/ui/Callout"; Welcome to the **MOCA API** — the unified public interface of the [Museum of Crypto Art](https://museumofcryptoart.com). One API key gives your software structured access to the whole MOCA universe: | Surface | What you get | | --- | --- | | **Collections** | The museum's published collections and their hierarchy | | **Artworks** | Every artwork with normalized, *original-ratio* media URLs | | **Rooms** | The 3D exhibition architecture as GLB models with artwork slots | | **Art DeCC0s** | The 10,000-entity DeCC0s knowledge base, aggregated from [api.decc0s.com](https://docs.decc0s.com) | | **Search** | One query across all of the above | | **Library** | RAG Q&A and hybrid search over the museum's knowledge base — answers with citations ([guide](/library)) | | **Souls** | EIP-191-signed agent identity documents per NFT, ready for ERC-8004/8183/8257 ([guide](/web3)) | | **Hyperfy** | Spawn curated exhibitions into walkable multiplayer worlds ([guide](/hyperfy)) | | **Skills** | Ground-truth `SKILL.md` files + [`llms.txt`](/llms.txt) for your AI agents ([handbook](/skills)) | ## Base URL ``` https://api.moca.qwellco.de/v1 ``` ## Design principles **One key, one surface.** The MOCA API aggregates several backends — the museum's Directus CMS and the Art DeCC0s knowledge base — behind a single authenticated endpoint, so you never juggle multiple credentials or base URLs. **The artwork, not a thumbnail.** Historic NFT pipelines are littered with square-cropped CDN variants. The MOCA API resolves every artwork to its **original file** where one survives, revives dead hosts, and only reports an aspect `ratio` it can actually trust. Render `media.url` at `ratio` and you're showing the work the way the artist made it. **Familiar conventions.** Responses use the Directus-style envelope — `{ "data": …, "meta": … }` on success, `{ "errors": [...] }` on failure — the same conventions as the [DeCC0s API](https://docs.decc0s.com), so moving between the two feels seamless. Grab your key and make your first call in the [Quickstart](/quickstart). ## Need an API key? API keys are issued by the MOCA team. Reach out through [museumofcryptoart.com](https://museumofcryptoart.com) and tell us what you're building — we love seeing the collection travel. --- ## Document: Integration recipes Patterns for building MOCA into your own software URL: /integration # Integration recipes import { Callout } from "zudoku/ui/Callout"; All examples assume your key is available server-side as `MOCA_API_KEY`. ## A tiny typed client (TypeScript) ```ts const BASE = "https://api.moca.qwellco.de/v1"; async function moca(path: string, params?: Record): Promise { 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; } // Usage const collections = await moca("/collections"); const artworks = await moca("/artworks", { collection: "genesis", limit: "50", }); ``` ## Rendering artworks correctly The cardinal rule: **respect the ratio**. Works are portraits, panoramas, videos — never assume squares. ```tsx function ArtworkFigure({ art }: { art: Artwork }) { if (art.animation) { return (