Back to agents docs
Quickstart · TypeScript
Wire a TS agent into Orrery
Use @orrery/client for typed endpoint methods, or native fetch for raw x402 handling. Paid calls can spend monthly Orrery API credits or settle per request through x402.
Official client package
publish gatenpm install @orrery/client
Package scaffold is ready in-repo and documented at /docs/agents/sdk. Public npm install becomes live after the explicit package publish step.
Native fetch example install
npm install @anthropic-ai/sdk
Minimal agent (~30 lines)
briefing.tsimport Anthropic from "@anthropic-ai/sdk";
const ORRERY = "https://orrery.me/api/x402/v1";
const ORRERY_API_KEY = process.env.ORRERY_API_KEY;
const PAYMENT = process.env.ORRERY_X_PAYMENT; // produced by your x402 payer
const client = new Anthropic(); // reads ANTHROPIC_API_KEY
async function fetchJson<T>(url: string): Promise<T> {
const headers: Record<string, string> = {};
if (ORRERY_API_KEY) headers["X-Orrery-API-Key"] = ORRERY_API_KEY;
else if (PAYMENT) headers["X-PAYMENT"] = PAYMENT;
const r = await fetch(url, {
headers,
});
if (r.status === 402) {
throw new Error("x402 payment required: settle the challenge and replay with X-PAYMENT");
}
if (!r.ok) throw new Error(`${r.status} ${url}`);
return (await r.json()).data as T;
}
// 1. Today's brief.
const brief = await fetchJson<{
headline: string;
biggest_moves: { slug: string; question: string; delta_24h: number }[];
}>(`${ORRERY}/brief/today`);
// 2. Why did the top mover move?
const top = brief.biggest_moves[0];
const why = await fetchJson<{ factors: { type: string; summary: string }[] }>(
`${ORRERY}/markets/${top.slug}/why`,
);
// 3. Resolution-risk before treating it as news.
const risk = await fetchJson<{ risk_level: string; what_to_verify: string[] }>(
`${ORRERY}/markets/${top.slug}/resolution-risk`,
);
// Hand it to Claude. Orrery already structured the data, so the
// system prompt can be tight: stay grounded, don't predict.
const msg = await client.messages.create({
model: "claude-opus-4-7",
max_tokens: 600,
thinking: { type: "adaptive" },
system:
"You summarise prediction-market intelligence for a daily briefing. " +
"Stay grounded in the supplied JSON; never predict outcomes; flag " +
"resolution risk when present.",
messages: [{
role: "user",
content:
`Today's brief headline: ${brief.headline}\n\n` +
`Top mover: ${JSON.stringify(top)}\n\n` +
`Why it moved: ${JSON.stringify(why.factors)}\n\n` +
`Resolution-risk: ${JSON.stringify(risk)}\n\n` +
"Write a 4-sentence briefing for a busy reader.",
}],
});
console.log(msg.content[0].type === "text" ? msg.content[0].text : "");Replaying with X-PAYMENT
async function fetchWithPayment(url: string, payer: X402Payer) {
const r = await fetch(url);
if (r.status !== 402) return (await r.json()).data;
const challenge = (await r.json()).accepts[0];
const proof = await payer.settle({
amount: challenge.amount,
asset: challenge.asset, // "USDC"
network: challenge.network, // "base"
});
const r2 = await fetch(url, { headers: { "X-PAYMENT": proof } });
if (!r2.ok) throw new Error(`${r2.status} after payment`);
return (await r2.json()).data;
}In production, the first unpaid request should hit the 402 branch. A successful replay returns payment_status: "settled".
Next steps
- • Cache responses client-side using each endpoint's
meta.cache_secondshint to keep your usage in budget. - • For a Discord bot, fetch
/signals/resolution_riskevery 10 minutes and re-broadcast new fires only. - • SDK packages · Python quickstart · Raw HTTP / cURL