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-ddstrings. - Successful reads return
200; see Rate limits & errors for non-2xx. v1is stable — breaking changes ship under a future version, never insidev1.
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
- Endpoint reference — all endpoints, grouped by domain.
- Interactive docs — try endpoints live in Swagger UI.
- OpenAPI spec — generate a client from
v1.json.