Developer documentation

Build on CaseCanon

A REST API and an MCP server for published US opinions, structured briefs and the Legal Graph. Use them from Python, Node.js or any HTTP client.

Quick start

Your first request in two minutes

Get an API key, run a search, fetch a brief. Everything is plain REST with JSON responses.

  1. Get your API key

    Log in, open Account settings, then API keys. Keys start with sk-cc-.

  2. Run a search

    bash
    curl -X POST https://api.casecanon.ai/v1/search \
      -H "X-API-Key: sk-cc-your-key" \
      -H "Content-Type: application/json" \
      -d '{"query": "non-compete enforceability Florida", "limit": 5}'
  3. Fetch a brief

    bash
    curl https://api.casecanon.ai/v1/briefs/608-F.3d-724 \
      -H "X-API-Key: sk-cc-your-key"
Authentication

Three ways to send your key

Send your key in a header, a query parameter or a Bearer token. If you send more than one, they're checked in this order.

bash
# 1. X-API-Key header (recommended)
curl -H "X-API-Key: sk-cc-your-key" ...

# 2. Query parameter (Claude custom connector)
https://mcp.casecanon.ai/mcp?api_key=sk-cc-your-key

# 3. Bearer token
curl -H "Authorization: Bearer sk-cc-your-key" ...
For Claude's custom connector, put the key in the address with ?api_key=. It's the simplest setup.
MCP · Python

Connect a Python agent

Use the official MCP SDK. It works with LangChain, LlamaIndex, smolagents and any framework that speaks MCP.

bash
pip install mcp
Python
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

MCP_URL = "https://mcp.casecanon.ai/mcp?api_key=sk-cc-your-key"

async def main():
    async with streamablehttp_client(MCP_URL) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()

            tools = await session.list_tools()
            for tool in tools.tools:
                print(f"- {tool.name}: {tool.description[:60]}")

            result = await session.call_tool(
                "search_opinions",
                arguments={"query": "qualified immunity false arrest", "limit": 5},
            )
            print(result.content[0].text)

asyncio.run(main())
MCP · Node.js

Connect a Node.js app

Use the official TypeScript SDK. It runs on Node.js, Deno and Bun.

bash
npm install @modelcontextprotocol/sdk
TypeScript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const MCP_URL = "https://mcp.casecanon.ai/mcp?api_key=sk-cc-your-key";

const client = new Client({ name: "my-app", version: "1.0.0" });
await client.connect(new StreamableHTTPClientTransport(new URL(MCP_URL)));

const result = await client.callTool({
  name: "search_opinions",
  arguments: { query: "ADA disability employment", court: "ca11", limit: 5 },
});

const data = JSON.parse(result.content[0].text);
data.results.forEach(o => console.log(`${o.citation} — ${o.name}`));

await client.close();
REST · Briefs & Legal Graph

Briefs and citations

Fetch a brief by official citation or CaseCanon ID, then follow the Legal Graph to the opinions that cite it.

Python
# Full brief by citation
brief = httpx.get(
    "https://api.casecanon.ai/v1/briefs/608-F.3d-724",
    headers={"X-API-Key": "sk-cc-your-key"},
).json()
print(brief["issues"])       # Questions the court answered
print(brief["disposition"])  # Affirmed / Reversed / Remanded

# Who cites this opinion?
cited = httpx.get(
    "https://api.casecanon.ai/v1/briefs/608-F.3d-724/cited-by?limit=20",
    headers={"X-API-Key": "sk-cc-your-key"},
).json()
print(f"Cited by {cited['total']} opinions")
Errors

Error codes

Every error returns JSON with an error field.

CodeMeaningWhat to do
401API key missingAdd the X-API-Key header
403API key invalid or expiredCreate a new key in Account settings
404Opinion not foundCheck the citation or ID
422Invalid parameterCheck the parameter values above
429Daily limit reachedWait for the reset or upgrade to Pro
500Server errorTry again, or contact us
Python
import httpx

try:
    resp = httpx.get(
        "https://api.casecanon.ai/v1/briefs/not-a-citation",
        headers={"X-API-Key": "sk-cc-your-key"},
    )
    resp.raise_for_status()
except httpx.HTTPStatusError as e:
    print(e.response.status_code, e.response.json().get("error"))
Limits

Limits by plan

Limits apply per API key and reset every day at midnight Eastern.

PlanSearches a dayResults per requestMCP
No account310No
Free510No
Pro ($29.99/month)Unlimited20Yes
Need help with an integration? Contact us. We answer technical questions within one business day.