Skip to main content
Looking for the machine-readable spec? Download /openapi.yaml (OpenAPI 3) and import it into the API client you already use. To connect an AI assistant instead, see /mcp.

Issue your first request

Request
curl https://www.oxfordledge.com/api/data?ticker=AAPL \
  -H "X-API-Key: ol_your_api_key_here"
Response
{
  "ticker": "AAPL",
  "price": { "current": 187.44, "changePct": 1.23 },
  "metrics": { "pe": 28.5, "marketCap": "2.89T" }
}

Also available to your AI assistant (Claude, Codex, Cursor and others) as 62 MCP tools. Details below →

API Documentation

Access Oxford Ledge's financial data programmatically. Stock quotes, fundamentals, SEC filings, screener, portfolio management, and more — all via a simple REST API.

Authentication

All API requests require authentication via an API key. Generate your key from Settings → API Keys in the platform.

Send your key in the X-API-Key header on every request — the only header that carries an Oxford Ledge key today (Authorization: Bearer is reserved for OAuth access tokens; a key sent as a Bearer token is treated as anonymous). Send a descriptive User-Agent too: bare curl / python-requests agents are refused on /api/* without a credential.

# Using curl
curl -H "X-API-Key: ol_your_api_key_here" \
     -H "User-Agent: my-research-script/1.0 (you@example.com)" \
  https://www.oxfordledge.com/api/data?ticker=AAPL
# Using Python requests
import requests

headers = {"X-API-Key": "ol_your_api_key_here",
           "User-Agent": "my-research-script/1.0 (you@example.com)"}
r = requests.get("https://www.oxfordledge.com/api/data",
               params={"ticker": "AAPL"},
               headers=headers)
data = r.json()
API keys are free on every tier, Learner included. A few endpoints need a paid tier — they answer 402 below it — and the screener returns its top three matches until Researcher. See the tier badge on each endpoint below.

Base URL

https://www.oxfordledge.com/api/

API versioning is supported: /api/v1/* routes to the same handlers as /api/*. Both are interchangeable.

Rate Limits

Rate limits are applied per IP address. When exceeded, the API returns 429 Too Many Requests with a Retry-After header.

API rate limits by user tier
TierLimit
Authenticated users (validated session)900 req/min per IP
Unauthenticated290 req/min per IP
Burst window200 req / 5 sec per IP, signed in or not
Request budget (cost-weighted)200 req / 60 sec (1,000 weighted units) per signed-in account; the same per anonymous IP
Bot / suspicious UA30 req/min
/api/* catch-all1,200 req/min per signed-in account; 200 req/min per anonymous IP
/api/data, /api/fundamentals, /api/credit/120 req/min per IP, signed in or not
MCP / A2A tool callsper caller per hour by site tier — Free 100, Researcher 500, Investor 2,000, Power User 5,000
Heavy endpoints (13F filings, screener) consume more of your rate limit budget than lightweight ones (health, tickers list). Plan accordingly.

Developer plans

Developer and Developer Pro include everything in Power User, plus a monthly allowance of data calls across every key on the account. Keys run on the hourly ladder above, and a plan puts them on Power User's 5,000 MCP calls an hour, which makes the monthly allowance reachable:

Developer plans: monthly price, included calls, and the extra-call rate
PlanPriceIncluded calls per monthExtra calls, only if you turn them on
Developer$99/mo100,000$0.002 per call, capped at $50/month by default
Developer Pro$499/mo1,000,000$0.001 per call, capped at $250/month by default

By default, calls beyond the allowance are refused with 402 until the next month and nothing accrues. On Developer, extra calls are then $0.002 per call, capped at $50/month by default (you can change the cap); on Developer Pro, $0.001 per call, capped at $250/month by default. Each plan's extra-call rate is twice its included rate, so outgrowing a plan never costs more than 2x. AI-backed tools bill credits separately. Because a plan includes Power User, every endpoint badged Researcher, Investor or Power User answers a plan holder's keys. Cancel the plan and its Power User access ends with it.

Extra calls: the rate, the cap, and how to turn them on

Extra calls are OFF until you turn them on, and turning them on is an explicit act: POST /api/billing/agent-plan/overage with {"cap_usd": 50} (signed in, CSRF header) records the rate shown above and the monthly limit you name. Send no cap_usd for the default limit, any amount up to 4x the plan price ($396 on Developer, $1,996 on Developer Pro) to set your own, or 0 to turn extra calls off again. The rate and the limit you agree to are the ones that bill you; a later price change, or a plan change, asks you again before anything accrues.

Only a successful call counts; errors (402, 403, 404, 429, 5xx) are never billed. At the limit, calls are refused with 402 and reason: "overage_cap" naming the accrued amount and the limit, until you raise it or the month resets. GET /api/billing/agent-plan shows the rate, your limit, and what has accrued this month (overage_accrued_usd); every metered response carries the price of that call in the X-OL-Per-Call-Cost header. Extra calls are added to your next monthly invoice as one line, never charged per call.

Without a plan: included on every tier

API access is included on every plan, Learner included, and a key with no Developer plan is never billed per call. It runs within the hourly limits in the table above: 100 MCP calls an hour on Learner, 500 on Researcher, 2,000 on Investor and 5,000 on Power User. A Developer plan adds a monthly allowance on top — 100,000 calls on Developer ($99/mo) or 1,000,000 on Developer Pro ($499/mo) — and extra calls past it are metered only if you turn them on.

Your month-to-date call count is at GET /api/billing/agent-usage.

Buy or check a plan, and create keys, in YOUR API KEYS: press K or open Settings → API keys, or open /?panel=api-keys while signed in.

Response Format

All responses are JSON. Successful responses return the data directly:

{
  "ticker": "AAPL",
  "price": {
    "current": 189.84,
    "change": 2.15,
    "changePercent": 1.14
  },
  "fundamentals": { ... },
  "fetchedAt": "2026-04-03T10:30:00"
}

Errors

Error responses include an error field with a human-readable message:

{
  "error": "No ticker provided"
}
// HTTP 400, 401, 403, 404, or 429

Common error codes:

Endpoints

GET /api/data Learner

Full ticker snapshot: price, fundamentals, profile, SEC filings, locally computed technicals, and more. No buy/hold/sell ratings are served; a mean analyst price target appears only with its source and our fetch date (the date Oxford Ledge fetched it), plus the analyst count only when that same source supplies it. This is the primary data endpoint.

Parameters for ticker data endpoint
ParamTypeDescription
tickerstring requiredStock ticker symbol (e.g. AAPL, MSFT)
nocachestring optionalSet to 1 to force a fresh fetch
fieldsstring optionalComma-separated field names for GraphQL-style field selection
curl -H "X-API-Key: $KEY" \
  "https://www.oxfordledge.com/api/data?ticker=AAPL"
Example response (abbreviated)
{
  "ticker": "AAPL",
  "price": {"current": 189.84, "change": 2.15, "changePercent": 1.14},
  "fundamentals": {"marketCap": 2950000000000, "pe": 31.2, "eps": 6.08, ...},
  "profile": {"name": "Apple Inc", "sector": "Technology", ...},
  "filings": [{"form": "10-K", "filed": "2025-11-01", ...}],
  "fetchedAt": "2026-04-03T10:30:00"
}
GET /api/random-ticker Learner

Returns a random ticker from the universe. Useful for discovery and exploration.

curl -H "X-API-Key: $KEY" \
  "https://www.oxfordledge.com/api/random-ticker"
GET /api/fundamentals-pit Learner

Point-in-time fundamental data snapshot. Returns financials as they were known on a given date, avoiding look-ahead bias for backtesting.

Parameters for point-in-time fundamentals endpoint
ParamTypeDescription
tickerstring requiredStock ticker symbol
datestring optionalDate in YYYY-MM-DD format (defaults to latest)
curl -H "X-API-Key: $KEY" \
  "https://www.oxfordledge.com/api/fundamentals-pit?ticker=AAPL&date=2025-06-30"
  • GET /api/fundamentals-history?ticker=AAPL&start=2024-01-01&end=2025-12-31 — PIT time series
  • GET /api/fundamentals-pit/universe?date=2025-06-30 — All tickers with PIT data for a date
  • GET /api/fundamentals-pit/stats — Database statistics
GET /api/screener Learner

Screen stocks by fundamental criteria. Filter by market cap, P/E, dividend yield, sector, and more. Returns matching tickers with key metrics. Below Researcher the response carries the top three matches with locked: true and locked_total; Researcher and above get the full result set.

Parameters for stock screener endpoint
ParamTypeDescription
mktcap_minnumber optionalMinimum market cap
pe_maxnumber optionalMaximum P/E ratio
div_yield_minnumber optionalMinimum dividend yield (%)
sectorstring optionalFilter by sector (e.g. "Technology")
sortstring optionalSort field
limitinteger optionalMax results (capped at 500)
curl -H "X-API-Key: $KEY" \
  "https://www.oxfordledge.com/api/screener?pe_max=20&sector=Technology"
GET POST DELETE /api/portfolio-positions Learner

Manage portfolio positions. Requires authentication. Supports multiple named portfolios.

Parameters for portfolio positions endpoint
ParamTypeDescription
portfolio_idstring optionalPortfolio name (default: "default")

Get positions:

curl -H "X-API-Key: $KEY" \
  "https://www.oxfordledge.com/api/portfolio-positions"

Add a position:

curl -X POST -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"ticker": "AAPL", "shares": 100, "cost_basis": 150.00}' \
  "https://www.oxfordledge.com/api/portfolio-positions"

Delete a position:

curl -X DELETE -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"ticker": "AAPL"}' \
  "https://www.oxfordledge.com/api/portfolio-positions"
  • GET /api/portfolio-history?days=30 — Portfolio value history
  • GET /api/portfolio/benchmark?period=1y — Benchmark comparison (S&P 500)
GET /api/etf-data Learner

ETF profile, holdings, sector breakdown, and performance data.

Parameters for ETF data endpoint
ParamTypeDescription
symbolstring requiredETF ticker symbol (e.g. SPY, QQQ, VTI)
curl -H "X-API-Key: $KEY" \
  "https://www.oxfordledge.com/api/etf-data?symbol=SPY"
  • GET /api/etf-compare?symbols=SPY,QQQ,VTI — Compare multiple ETFs
  • GET /api/etf-list — All tracked ETF tickers
GET /api/news/search Learner

Search the historical news archive. Full-text search with sentiment scores, auto-tagged industries, and ticker associations.

Parameters for news search endpoint
ParamTypeDescription
qstring optionalFull-text search query
tickerstring optionalFilter by ticker symbol
tagstring optionalFilter by industry tag
sentimentstring optionalFilter by sentiment: positive, negative, neutral
daysinteger optionalLook back N days (default: 7)
limitinteger optionalMax results (default: 50)
offsetinteger optionalPagination offset
curl -H "X-API-Key: $KEY" \
  "https://www.oxfordledge.com/api/news/search?ticker=AAPL&days=30&limit=10"
  • GET /api/news/ticker?ticker=AAPL — Recent headlines for a specific ticker
  • GET /api/news/stats — News database statistics
GET /api/fund-holdings Learner

SEC 13F institutional holdings for one fund, by CIK. See what hedge funds and asset managers hold. Data sourced directly from SEC EDGAR. For the managers holding a given ticker, use /api/institutional-holders?ticker=.

Parameters for 13F holdings endpoint
ParamTypeDescription
cikstring requiredThe fund's SEC CIK (e.g. "0001067983" for Berkshire Hathaway)
max_holdingsinteger optionalRows to return, 1–500 (default 50)
curl -H "X-API-Key: $KEY" \
  "https://www.oxfordledge.com/api/fund-holdings?cik=0001067983"

Python SDK

The Python SDK is on PyPI as ol-sdk and is free on every tier, Learner included:

pip install ol-sdk
pip install "ol-sdk[pandas]"   # optional DataFrame support
import oxford_ledge_sdk as ol

ol.set_api_key("ol_live_your_api_key_here")

# Company profile and quote
company = ol.get_company("AAPL")

# Fundamentals, point-in-time fundamentals
fundamentals = ol.get_fundamentals("MSFT")
pit = ol.get_fundamentals_pit("MSFT", date="2025-06-30")

# Or hold a client for custom timeouts and retries
from oxford_ledge_sdk import OxfordLedgeClient
with OxfordLedgeClient(api_key="ol_live_your_api_key_here") as client:
    bonds = client.search_bonds("Apple")
Release 0.2.2 sends your key as Authorization: Bearer. The /api/* endpoints read only X-API-Key today (see Authentication), so SDK calls currently run with signed-out access. For keyed access, call the REST API directly with the X-API-Key header until the next SDK release.

MCP Tools

Oxford Ledge exposes 62 tools via the Model Context Protocol (MCP), so Claude, Codex, Cursor and other MCP clients can look things up in the same public filings the Ledge is built on. Step-by-step setup for each client is on the MCP page. Without a key, 45 of the 62 tools answer an anonymous call; a few more answer anonymously but refuse below a paid tier, and the rest need an API key (mint one under YOUR API KEYS on the dashboard — keys look like ol_live_…). Every tool, sorted by which of the three it is, is under Who answers what on the MCP page.

Claude Desktop Configuration

Install the package (pip install oxford-ledge-mcp), then add the following to your claude_desktop_config.json:

{
  "mcpServers": {
    "oxford-ledge": {
      "command": "oxford-ledge-mcp",
      "env": {
        "OXFORD_LEDGE_URL": "https://www.oxfordledge.com",
        "OXFORD_LEDGE_API_KEY": "ol_live_YOUR_KEY_HERE"
      }
    }
  }
}
Setup gotchas: OXFORD_LEDGE_URL is required for the authenticated tools — without it the server runs keyless-standalone and your key is silently ignored. On Windows, use the full path to oxford-ledge-mcp.exe as command (Claude Desktop does not inherit your shell PATH), and note the Microsoft-Store build of Claude Desktop reads its config from %LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\. The oxford-ledge-mcp console script is the recommended command; python -m oxford_ledge_mcp also works on 3.1.1 and later (earlier wheels shipped no __main__.py). After editing the config, fully quit Claude Desktop from the system tray and relaunch.
MCP tools pull from local databases and caches. A small set of heavy tools (bulk XBRL / cross-portfolio scans — e.g. get_fundamentals, marked below) is limited to 2 concurrent executions; total concurrency across all tools is capped at 5. Both caps are process-wide on the hosted server, not per session.

Tool Catalog

The hosted catalog carries 62 tools. The pip package (oxford-ledge-mcp) runs 29 tools on your own machine: the SEC-EDGAR tools (and the FRED tools, with your own FRED key) run standalone with no Oxford Ledge account, most of the rest answer keyless once OXFORD_LEDGE_URL is set, and the Researcher-tier ones need OXFORD_LEDGE_API_KEY; the exact split is on the MCP page. The full, always-current list is machine-readable at /api/mcp/tools.json and browsable at /mcp — plan tool calls from that live list, not from a static table. Highlights (verified against the registry 2026-09-13):

MCP tool highlights
ToolDescriptionWhere
get_fundamentalsXBRL annual statements from SEC EDGAR, newest-first — up to 10 years on the pip package (direct EDGAR), up to 30 fiscal-year labels hosted — heavypip + hosted
get_sec_filingsRecent 10-K / 10-Q / 8-K / DEF 14A filings with direct linkspip
get_yield_curveTreasury yield curve 1M–30Y (needs your free FRED_API_KEY in the pip package)pip + hosted
get_insider_tradesForm 4 insider buys/sells for a tickerpip
get_bdc_listAll tracked BDCs with AUM, holding counts, filing datespip + hosted
search_bdc_borrowerWhich BDCs hold a borrower, at what fair value (pip endpoint fixed in 3.1.1)pip + hosted
ol_bdc_credit_qualityBDC non-accrual / credit-deterioration signalpip + hosted
ol_insider_recent_buysRecent open-market insider purchases across the whole marketpip + hosted
ol_13f_filer_analyticsInstitutional-filer behavior from 13F holdingshosted
ol_intrinsic_valueDCF / EPV / Graham per-share value from SEC XBRLhosted
ol_peer_fundamentalsSide-by-side latest-fiscal-year fundamentals for a peer sethosted
ol_fdic_bankFDIC-insured institution lookup and financialshosted
ol_federal_contractsFederal-contract obligation history (forward-revenue signal)hosted

Example: Peer Comparison

Ask Claude Desktop to compare multiple tickers in a single request:

// Claude Desktop prompt:
"Compare latest-fiscal-year fundamentals for AAPL, MSFT, GOOG, and AMZN"

// Claude will call ol_peer_fundamentals with:
{
  "tickers": ["AAPL", "MSFT", "GOOG", "AMZN"]
}

Bulk Data Export

Export latest-fiscal-year fundamentals extracted from SEC filings for many tickers at once. Available to Investor tier and above.

Bulk Fundamentals

Bulk data export endpoints and latency
EndpointDescriptionLatency
GET /api/data/bulkStatement lines and ratios from each filer's own XBRL, one row per ticker, up to 100 tickers. Tickers without an SEC-provenance row are returned as withheld with a reason — never as zeros, never from a vendor row.1-5s
GET /api/data/bulk-historyRetired 2026-09-14 — answers 410 Gone. It served bulk OHLCV price history read from vendor price bars with no lineage predicate; Oxford Ledge displays vendor market data but does not redistribute it in bulk. Nothing sent to this URL is parsed.—

Examples

// Latest-fiscal-year statement lines for multiple tickers
GET /api/data/bulk?tickers=AAPL,MSFT,GOOG&fields=fundamentals

// Statement lines plus margin / return ratios
GET /api/data/bulk?tickers=AAPL,MSFT&fields=fundamentals,metrics

Parameters

Bulk export endpoint parameters
ParameterEndpointDescription
tickers/api/data/bulkComma-separated ticker symbols (required, max 100)
fields/api/data/bulkComma-separated: fundamentals (revenue, net income, assets, liabilities, equity, cash flows, EPS, long-term debt), metrics (gross / operating / net margin, ROA, ROE, current ratio). Default: both. price was retired 2026-09-14 and is answered under retiredFields with the reason.

Every served row carries fiscalYear, periodEnd, filingDate and source: "sec"; JSON only. The export is not a market-data feed: no prices, volumes or market capitalization, and no company-profile fields from vendor sources.

Additional Resources