Skip to main content
Press ⌘K to search

REST API

The REST API serves Equibles data as plain JSON over HTTPS — ideal for scripts, backends, and dashboards. It overlaps with the MCP catalog, but each endpoint documents its own response shape and coverage. For example, the customer-concentration REST endpoint serves verified narrative disclosures, while its MCP counterpart also serves supported tagged XBRL. Every endpoint lives under https://api.equibles.com/v1.

Base URL & authentication

All requests go to https://api.equibles.com/v1 and must include your API key as a Bearer token (or an ?api_key= query parameter — see Authentication).

curl "https://api.equibles.com/v1/stocks/AAPL/prices?startDate=2024-01-01" \
  -H "Authorization: Bearer eq_your_api_key"

Pagination

List endpoints accept limit and offset query parameters and wrap the rows in a data array alongside a meta object. Use meta.hasMore to decide whether to fetch the next page (increase offset by limit). The maximum limit is 500, and a limit of zero or less returns a 400 — omit the parameter to use the endpoint's default.

{
  "data": [ /* rows */ ],
  "meta": { "limit": 50, "offset": 0, "count": 50, "hasMore": true }
}

Some responses also carry a meta.total (or an endpoint-level total) with the full matching row count. It is present only where the endpoint already computes that count — when the field is absent, use hasMore to detect truncation rather than assuming the page is the whole set.

To pull an entire list, page until hasMore is false. Each page is one request against your daily limit, so a 10,000-row read at limit=500 costs 20 requests:

import requests

def fetch_all(url, key, page=500):
    rows, offset = [], 0
    while True:
        r = requests.get(url, params={"limit": page, "offset": offset},
                         headers={"Authorization": f"Bearer {key}"})
        r.raise_for_status()
        body = r.json()
        rows += body["data"]
        if not body["meta"]["hasMore"]:
            return rows
        offset += page

Response format

  • All responses are JSON with camelCase field names.
  • Dates are ISO yyyy-MM-dd strings.
  • Successful reads return 200; see Rate limits & errors for non-2xx.
  • v1 is stable — breaking changes ship under a future version, never inside v1.

A worked example

Fetch the short-squeeze board for names above a $1B market cap. Note that ratio fields (shortInterestPercentOfShares, priceAboveVwap, …) come over the wire as fractions at full decimal precision, not percentages — the MCP tool is what formats them as percentages:

curl "https://api.equibles.com/v1/short-squeeze-scores?minMarketCap=1000000000&limit=3" \
  -H "Authorization: Bearer eq_your_api_key"
import requests
r = requests.get(
    "https://api.equibles.com/v1/short-squeeze-scores",
    params={"minMarketCap": 1_000_000_000, "limit": 3},
    headers={"Authorization": "Bearer eq_your_api_key"},
)
for s in r.json()["data"]:
    print(s["ticker"], s["rank"], s["score"])
const url =
  "https://api.equibles.com/v1/short-squeeze-scores?minMarketCap=1000000000&limit=3";
const res = await fetch(url, {
  headers: { Authorization: "Bearer eq_your_api_key" },
});
const { data } = await res.json();
data.forEach((s) => console.log(s.ticker, s.rank, s.score));
{
  "settlementDate": "2026-07-15",
  "data": [
    {
      "ticker": "DNOW",
      "rank": 3,
      "score": 100.0,
      "shortInterestPercentOfShares": 0.0971129987129360664544336593,
      "daysToCover": 8.08,
      "shortVolumeShareTrend": 0.1083068876670983568816244712,
      "shortInterestChangePercent": 0.2165886393491481601105171991,
      "failsToDeliverPercentOfShares": 0.0001904130892603781785161542,
      "priceAboveVwap": 0.2223890995821585748987430555,
      "hasPriceSpikeCatalyst": true,
      "hasVolumeSurgeCatalyst": false,
      "hasEarningsProximityCatalyst": true,
      "marketCapitalization": 3027259856.2080235,
      "averageDailyDollarVolume": 36401236.80468409,
      "baseScore": 82.92,
      "catalystBoost": 20.0,
      "shortInterestPercentile": 88.51654514862591,
      "daysToCoverPercentile": 84.97150997150997,
      "shortVolumeTrendPercentile": 78.31572769953051,
      "shortInterestChangePercentile": 83.19160997732426,
      "failsToDeliverPercentile": 52.636006730229944,
      "priceAboveVwapPercentile": 93.57798165137615
    },
    {
      "ticker": "FIGS",
      "rank": 5,
      "score": 100.0,
      "shortInterestPercentOfShares": 0.119883309186464288405213711,
      "daysToCover": 6.71,
      "shortVolumeShareTrend": 0.0682086900561761833590394735,
      "shortInterestChangePercent": 0.1341783439780606248348624689,
      "failsToDeliverPercentOfShares": 0.000723172174023918900996906,
      "priceAboveVwap": 0.2382920223752723619248794544,
      "hasPriceSpikeCatalyst": true,
      "hasVolumeSurgeCatalyst": false,
      "hasEarningsProximityCatalyst": true,
      "marketCapitalization": 2384943104.0,
      "averageDailyDollarVolume": 42591226.331520475,
      "baseScore": 82.59,
      "catalystBoost": 20.0,
      "shortInterestPercentile": 92.37240605720696,
      "daysToCoverPercentile": 78.37606837606837,
      "shortVolumeTrendPercentile": 67.34154929577466,
      "shortInterestChangePercentile": 77.19671201814059,
      "failsToDeliverPercentile": 72.3780145821649,
      "priceAboveVwapPercentile": 94.28369795342273
    }
  ],
  "scoredCount": 7133,
  "total": 2939
}

rank is the row's position in the whole scored universe, stamped before your liquidity filters; scoredCount is that universe (what the percentiles are relative to) and total is how many rows matched your filters. The sample above is trimmed to two of the three rows the request returns.

Every endpoint's exact parameters and response schema are in the interactive docs.

Errors & rate limits

Non-2xx responses return a consistent error envelope, and requests count against a shared daily limit across MCP and REST. Full details are on Rate limits & errors.

{ "error": { "code": "not_found", "message": "Stock not found.", "status": 404 } }

Client libraries

There's no official SDK — the API is plain HTTPS + JSON, so any HTTP client works (the examples here use curl, requests, and fetch). For a typed client, generate one from the OpenAPI spec with a tool like openapi-generator or openapi-typescript.

Reference

Try it with a real key

Every example on this page runs against the live API. A free account includes an API key and MCP access — set up in under a minute.

Get your free API key