SDKs and compatibility
POST https://api.mouse.dev/v1/decisions is our primary neutral endpoint, and POST https://api.mouse.dev/v1/systemone is served as an identical alias that is wire-compatible with the TypeSafe System One request and response specification. You can call either route with zero dependencies using fetch / requests / httpx, or point an existing @typesafe-ai/sdk (TypeScript/JavaScript) or typesafe-sdk (Python) client at https://api.mouse.dev.
Wire-level compatibility
Section titled “Wire-level compatibility”Every standard System One request and response field works unchanged:
- Request fields:
model("mouse-1"or"mouse"),state(string, JSON object, or array), andquestions(choice,noul,scorewith string or structured JSONinstructionsandcriteria). - Response fields:
answerskeyed by your question IDs, returningchoice/noul/score,probabilities,confidence, andlegend, plusmodelandusage. - Mouse extensions (safely ignored by existing SDKs):
- Request: optional
calibration("calp1.<kid>.<blob>") fromPOST /v1/calibrations. - Request: optional
order_invariant: true(server-side permutation averaging forchoice), and OpenAI Decisions field names (input, arrayquestions,predicate,choices,levels) accepted as aliases. - Answer:
logitsandmouse: { calibrated, p_top, abstain, confidence_winning, confidence_normalized }on every answer;noulanswers also carryprobabilities: { false, true }. - Usage: itemized
state_tokens,question_tokens,framing_tokens,cached_tokens, andcost_usdalongsideinput_tokensandoutput_tokens. - Top-level:
id("dec_..."),object("systemone.response"),latency_ms, and optionalwarnings.
- Request: optional
Zero-dependency HTTP (fetch and httpx)
Section titled “Zero-dependency HTTP (fetch and httpx)”Because /v1/systemone is a single non-streaming JSON endpoint that completes in ~40–100 ms, a 15-line fetch or httpx helper gives you full access to both System One answers and Mouse calibration fields (mouse.abstain, usage.cost_usd):
TypeScript (fetch)
Section titled “TypeScript (fetch)”export interface MouseMeta { calibrated: boolean; p_top: number; abstain: boolean | null;}
export async function decide<T extends Record<string, unknown>>( state: unknown, questions: T, options?: { calibration?: string; signal?: AbortSignal },) { const res = await fetch("https://api.mouse.dev/v1/systemone", { method: "POST", headers: { Authorization: `Bearer ${process.env.MOUSE_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ model: "mouse-1", state, questions, ...(options?.calibration ? { calibration: options.calibration } : {}), }), signal: options?.signal ?? AbortSignal.timeout(3_000), });
if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error(err?.error?.message ?? `Mouse HTTP ${res.status}`); } return res.json();}Python (httpx)
Section titled “Python (httpx)”import osimport httpx
_client = httpx.Client( base_url="https://api.mouse.dev", headers={"Authorization": f"Bearer {os.environ['MOUSE_API_KEY']}"}, timeout=3.0,)
def decide(state, questions: dict, calibration: str | None = None) -> dict: payload = {"model": "mouse-1", "state": state, "questions": questions} if calibration: payload["calibration"] = calibration res = _client.post("/v1/systemone", json=payload) res.raise_for_status() return res.json()Using @typesafe-ai/sdk (TypeScript / JavaScript)
Section titled “Using @typesafe-ai/sdk (TypeScript / JavaScript)”Install @typesafe-ai/sdk (Node.js 20+) and set baseURL to "https://api.mouse.dev" and defaultModel to "mouse-1":
npm install @typesafe-ai/sdkimport { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient({ apiKey: process.env.MOUSE_API_KEY, baseURL: "https://api.mouse.dev", defaultModel: "mouse-1", timeout: 3_000, retry: { maxRetries: 1 },});
const result = await client.systemOne({ state: { task: "Rename parseToken to verifyToken in src/auth.ts", command: "pnpm test", }, questions: { tool: choice("Which tool should run next?", { edit: "Modify source code", search: "Search repository", ask: "Ask the user for clarification", }), safe: noul("Is `command` safe to run without user approval?"), risk: score("How risky is `command`?", [ "Read-only or local test command", "Modifies local workspace files", "Pushes to remote or mutates external state", ]), },});
// Answer types are inferred from the question map:// result.answers.tool.choice has type "edit" | "search" | "ask"console.log(result.answers.tool.choice, result.answers.tool.confidence);console.log(result.answers.safe.noul);console.log(result.answers.risk.score);Using typesafe-sdk (Python)
Section titled “Using typesafe-sdk (Python)”Install typesafe-sdk (Python 3.10+) and pass base_url="https://api.mouse.dev" and model="mouse-1":
pip install typesafe-sdkimport osfrom typesafe_sdk import AsyncTypeSafeClient, Choice, Noul, Score, TypeSafeClient
with TypeSafeClient( api_key=os.environ["MOUSE_API_KEY"], base_url="https://api.mouse.dev", model="mouse-1",) as client: response = client.system_one( state="Customer says: my card was charged twice for order #1042.", questions={ "intent": Choice( instructions="Which team should handle this?", criteria={ "billing": "Duplicate charges, invoices, or refunds", "shipping": "Delivery status or tracking", "account": "Login or profile settings", }, ), "refund_requested": Noul( instructions="Does the customer ask for a refund?", ), }, )
print(response.answers["intent"].choice, response.answers["intent"].confidence)print(response.answers["refund_requested"].noul)For async Python services (FastAPI, asyncio workers), use AsyncTypeSafeClient with the same base_url="https://api.mouse.dev" and model="mouse-1" parameters.
Next steps
Section titled “Next steps”- API Reference — Full endpoint, parameter, and response documentation.
- Migrate from TypeSafe Jev or OpenAI Decisions — Side-by-side schema comparison table and migration examples.