Use the Crius API from AI agents (OpenAPI, llms.txt, MCP)
Give an AI agent Robinhood Chain data: Crius docs as llms.txt and Markdown, tool definitions from the OpenAPI document, an MCP server, and accuracy tips.
For writing code, give the model https://docs.crius.sh/llms.txt (or llms-full.txt, or any page as .md). For live data, turn https://api.crius.sh/openapi.json into tool definitions or run a small MCP server around a few endpoints. Core endpoints work without a key at 2 requests per second; give a production agent its own key with only the read scope.
AI agents use the Crius API in two ways: they read the documentation to write correct code against it, and they call it as a tool to answer questions about Robinhood Chain right now. For the first, the docs are published as llms.txt, one full-text file and a Markdown copy of every page. For the second, the OpenAPI document at https://api.crius.sh/openapi.json turns into tool definitions in a few lines, or into a small MCP server. Core endpoints work without a key, so an agent can explore before you give it one.
What to give the model
| Resource | URL | Use it for |
|---|---|---|
llms.txt |
https://docs.crius.sh/llms.txt |
Index of every docs page, with summaries and links to Markdown |
llms-full.txt |
https://docs.crius.sh/llms-full.txt |
All docs in one Markdown file, for long-context models or retrieval |
| Markdown pages | https://docs.crius.sh/<page>.md |
One page, e.g. https://docs.crius.sh/guides/token-security-score.md |
| OpenAPI 3.1 | https://api.crius.sh/openapi.json |
Endpoints, parameters and descriptions for tool definitions |
Every page also has a Copy as Markdown button. More on these resources is on the AI page.
The two lessons every agent needs
Three tokens with the symbol NVDA
A user asks an agent for the price of NVDA. Which token is that?
curl "https://api.crius.sh/v1/robinhood/search?q=nvda&limit=3"const res = await fetch("https://api.crius.sh/v1/robinhood/search?q=nvda&limit=3");const { data, meta } = await res.json();import requests
r = requests.get( "https://api.crius.sh/v1/robinhood/search?q=nvda&limit=3",)body = r.json()print(body["data"])Real response 200 Captured Oct 28, 2026 · 73 lines (arrays trimmed)
{ "data": [ { "address": "0xd0601ce157db5bdc3162bbac2a2c8af5320d9eec", "label": "stock_nvda", "launchpad": null, "launchpad_name": null, "links": { "discord": null, "farcaster": null, "github": null, "telegram": null, "twitter": null, "website": null }, "liquidity_usd": 5690673, "logo": null, "name": "NVIDIA • Robinhood Token", "price_usd": 214.313, "symbol": "NVDA", "type": "token" }, { "address": "0xdecf74e4aa6ff30b1612e65665aaf650bedecba3", "label": null, "launchpad": "bankr", "launchpad_name": "Bankr", "links": { "discord": null, "farcaster": null, "github": null, "telegram": null, "twitter": null, "website": null }, "liquidity_usd": 7070.72, "logo": null, "name": "NVDA", "price_usd": 0.000000282232, "symbol": "NVDA", "type": "token" }, { "address": "0xaaea5ec642e0b3ebbe7b484ad3702a408ca743c9", "label": null, "launchpad": "pons", "launchpad_name": "Pons", "links": { "discord": null, "farcaster": null, "github": null, "telegram": "https://t.me/NVDADogAsset", "twitter": "https://x.com/NVDADogAsset", "website": "https://www.nextviraldogasset.vip" }, "liquidity_usd": 4674.03, "logo": "https://api.crius.sh/v1/robinhood/logo/0xaaea5ec642e0b3ebbe7b484ad3702a408ca743c9.png?size=128", "name": "Next Viral Dog Asset", "price_usd": 0.00000270377, "symbol": "NVDA", "type": "token" } ], "meta": { "block": 100409954, "block_age_ms": 464, "block_ts": 1793225401000, "chain": "robinhood", "finalized_block": 100401329, "lag_ms": 7, "safe_block": 100405028 }}What this tells you
- The first result is NVIDIA’s tokenized stock:
name: "NVIDIA • Robinhood Token",label: "stock_nvda",address0xd0601ce157db5bdc3162bbac2a2c8af5320d9eec,price_usd214.313 andliquidity_usd5,690,673. - The other two also use the symbol
NVDA: a Bankr token (0xdecf74e4aa6ff30b1612e65665aaf650bedecba3, price 0.000000282232) and a Pons token named Next Viral Dog Asset (0xaaea5ec642e0b3ebbe7b484ad3702a408ca743c9). - An agent that passes the symbol around would be off by a factor of about 760 million. Resolve to an address once, prefer a
labelor the deepest liquidity, and confirm with the user when results are close.
An error the agent can act on
An agent without a key asks for CHARGE's holders. What comes back?
curl "https://api.crius.sh/v1/robinhood/token/0x7b8892cea949bc60d494681d1bc3ea96071ab0b8/holders" \ -H "x-api-key: $CRIUS_API_KEY"const res = await fetch("https://api.crius.sh/v1/robinhood/token/0x7b8892cea949bc60d494681d1bc3ea96071ab0b8/holders", { headers: { "x-api-key": process.env.CRIUS_API_KEY },});const { data, meta } = await res.json();import os, requests
r = requests.get( "https://api.crius.sh/v1/robinhood/token/0x7b8892cea949bc60d494681d1bc3ea96071ab0b8/holders", headers={"x-api-key": os.environ["CRIUS_API_KEY"]},)body = r.json()print(body["data"])Real response 403 Captured Oct 28, 2026 · 10 lines (arrays trimmed)
{ "error": { "code": "plan_required", "docs_url": "https://docs.crius.sh/plans-and-limits/", "message": "This endpoint needs an API key (Free plan or higher); you called it without one. To use it, get a free API key at https://dashboard.crius.sh.", "plan": "anon", "required_plan": "free", "upgrade_url": "https://dashboard.crius.sh" }}What this tells you
403witherror.code: "plan_required"andrequired_plan: "free": the endpoint needs a key on the Free plan or higher.error.messageis a complete sentence the agent can pass to the user as is, andupgrade_urlsays where to get a key.- Return errors to the model as text, not exceptions. It can then explain the problem, wait after a
429 rate_limited(retry_after_ms), or pick an endpoint its key allows.
Tool definitions from the OpenAPI document
This turns a handful of endpoints into provider-neutral tool definitions (name, description, JSON Schema parameters) and runs them. Pass tools to your model’s tool or function-calling API and feed each call to runTool.
// crius-tools.mjs: tool definitions from Crius's OpenAPI document (Node.js 22+)const KEY = process.env.CRIUS_API_KEY; // optional: the anonymous plan covers these endpointsconst spec = await (await fetch("https://api.crius.sh/openapi.json")).json();
const PATHS = [ "/v1/{chain}/search", "/v1/{chain}/token/{address}", "/v1/{chain}/token/{address}/price", "/v1/{chain}/token/{address}/security", "/v1/{chain}/token/{address}/candles", "/v1/{chain}/tokens",];const toolName = (path) => path.replace("/v1/{chain}", "").replace(/\{\w+\}/g, "").split("/").filter(Boolean).join("_");
export const tools = PATHS.map((path) => { const op = spec.paths[path].get; const params = op.parameters.filter((p) => p.name !== "chain"); // always Robinhood Chain return { name: toolName(path), // search, token, token_price, token_security, token_candles, tokens description: `Robinhood Chain: ${op.summary}. ${op.description ?? ""}`.trim(), path, parameters: { type: "object", properties: Object.fromEntries(params.map((p) => [p.name, { type: p.schema?.type ?? "string", description: p.description || p.name }])), required: params.filter((p) => p.required).map((p) => p.name), }, };});
export async function runTool(name, args) { const tool = tools.find((t) => t.name === name); let path = tool.path.replace("{chain}", "robinhood"); const query = new URLSearchParams(); for (const [k, v] of Object.entries(args ?? {})) { if (path.includes(`{${k}}`)) path = path.replace(`{${k}}`, encodeURIComponent(v)); else if (v != null) query.set(k, String(v)); } const res = await fetch(`https://api.crius.sh${path}${query.size ? `?${query}` : ""}`, { headers: KEY ? { "x-api-key": KEY } : {} }); const body = await res.json(); if (!res.ok) return `Crius API error ${res.status} ${body.error?.code}: ${body.error?.message}`; // text the model can act on return JSON.stringify({ data: body.data, block: body.meta?.block }).slice(0, 20_000); // trim, and keep the block for citing}
console.log(tools.map((t) => t.name).join(", "));console.log((await runTool("token_price", { address: "0xd0601ce157db5bdc3162bbac2a2c8af5320d9eec" })).slice(0, 120));Or an MCP server
For assistants that speak the Model Context Protocol (desktop assistants, IDE agents), wrap the same calls as MCP tools. Tested with @modelcontextprotocol/sdk 1.32.1 and zod 4.6.5:
// crius-mcp.mjs: npm i @modelcontextprotocol/sdk@1.32.1 zod@4.6.5, then register "node crius-mcp.mjs" in your MCP clientimport { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";import { z } from "zod";
const API = "https://api.crius.sh/v1/robinhood";const KEY = process.env.CRIUS_API_KEY;const address = z.string().regex(/^0x[0-9a-fA-F]{40}$/).describe("Token address (0x + 40 hex characters)");
async function crius(path) { const res = await fetch(`${API}${path}`, { headers: KEY ? { "x-api-key": KEY } : {} }); const body = await res.json(); const text = res.ok ? JSON.stringify({ data: body.data, block: body.meta?.block }).slice(0, 20_000) : `Crius API error ${res.status} ${body.error?.code}: ${body.error?.message}`; return { content: [{ type: "text", text }], isError: !res.ok };}
const server = new McpServer({ name: "crius", version: "1.0.0" });const ro = { readOnlyHint: true };
server.registerTool("search_tokens", { description: "Find Robinhood Chain tokens by name, symbol or address. Symbols are not unique: pick by address.", inputSchema: { query: z.string().min(1).max(64) }, annotations: ro,}, ({ query }) => crius(`/search?q=${encodeURIComponent(query)}&type=token&limit=10`));
server.registerTool("token_profile", { description: "Price, market cap, liquidity, holders summary and launchpad of a Robinhood Chain token.", inputSchema: { address }, annotations: ro,}, ({ address }) => crius(`/token/${address}`));
server.registerTool("token_security", { description: "Security score 0-100, risk level, flags, buy/sell tax and honeypot check of a token.", inputSchema: { address }, annotations: ro,}, ({ address }) => crius(`/token/${address}/security`));
await server.connect(new StdioServerTransport());Keep the agent accurate
-
A key of its own. Create a key for the agent with only the
readscope, an IP allow-list if it runs on a fixed host and a per-key rate limit (Authentication). Revoke it without touching your other services. -
Teach the units. Amounts are in human units, USD values are plain decimals and timestamps are unix milliseconds. Say so in the system prompt, with the conventions page in context.
-
Cite the block. Every response has
meta.block. Returning it with the data lets the agent say “at block 100409954” instead of “now”. -
Budget the calls. Each tool call costs its endpoint’s credits: 1 for search, profile, price or security, 2 for candles or trades, 5 or 10 for the heavier holder and wallet analytics. Limit tool calls per conversation if the agent is public.
Frequently asked questions
Is there an llms.txt for the Crius docs?
Yes: https://docs.crius.sh/llms.txt lists every page with a one-line summary and a link to its Markdown version, and https://docs.crius.sh/llms-full.txt has all pages in one file. Any page is also available as Markdown by adding .md to its path, for example https://docs.crius.sh/guides/token-security-score.md.
Where is the Crius OpenAPI document?
At https://api.crius.sh/openapi.json (OpenAPI 3.1). It lists every endpoint with its parameters and descriptions, which is what tool and function definitions need. Plans and credit costs per endpoint are on Plans & limits.
Can an agent call the API without a key?
Yes, for the anonymous-plan endpoints: token profiles and prices, batch prices, pools, trades, candles, token lists, search, stats, volume, launchpads and security. The limit is 2 requests per second per IP. Holders, wallets, bundles and the stream need a key; the error says which plan.
How do I stop an agent confusing tokens with the same symbol?
Make it resolve every name to an address with /search first, prefer results with a label such as stock_nvda or the deepest liquidity_usd, and pass addresses, never symbols, to every other tool. Tell it in the system prompt that symbols are not unique on Robinhood Chain.
Is there an official Crius MCP server?
There's no package to install. The server on this page is about 40 lines, wraps whichever endpoints you choose, and runs in any MCP-capable client.
Related
Get your free Crius API key
Every example on this page works with a free key: higher rate limits than the anonymous plan, holders, wallets and the WebSocket stream. No card needed.
- Robinhood Chain (4663) only, from our own archive nodes
- REST + WebSocket
- Pay on-chain or by card