The same data the app shows, as JSON, for your own code. Every cluster with its full context: how long since that filer last bought, how the purchase compares to their usual size, where the stock sits against its range, and what this issuer has done before.
Sign in and subscribe to get a key.
Send the key as a bearer token. It is never accepted in a query string: URLs end up in access logs, browser history and referer headers, which is the most common way an API credential leaks.
curl -H "Authorization: Bearer ck_your_key_here" \
https://api.chorusmarket.com/v1/clusters
X-API-Key: ck_... works too if a bearer header is awkward
in your client.
| Path | Returns |
|---|---|
| GET /v1/clusters | Every cluster, newest first. limit (1–200,
default 50), offset, and since=YYYY-MM-DD. |
| GET /v1/clusters/{ticker} | Every cluster for one ticker. |
| GET /v1/issuers/{cik}/history | That issuer's reconstructed history, and what the archive covers. |
| GET /v1/me | What your key is, and its rate limit. |
{
"object": "list", "count": 126,
"data": [{
"ticker": "SCOR",
"issuer_name": "COMSCORE, INC.",
"issuer_cik": "1158172",
"at": "2026-08-27",
"n_insiders": 2,
"total_value": 142230,
"people": [["Kline David", "Director", "https://www.sec.gov/..."],
["McLaughlin Matthew F.", "CFO", "https://www.sec.gov/..."]],
"marks": [[false, false], [false, true]],
"ctx": ["a CFO and a director",
"first purchase in 9 months",
"3.2x typical size",
"32% below 52-week high"]
}]
}
ctx is the analysis layer, and the reason the API is not
the free feed. marks is one entry per buyer, in the same
order as people: [is_entity, has_bought_before].
Every people entry links to the filing on sec.gov, so any
number here can be checked against the source.
60 requests a minute per key by default. Every response carries your remaining budget, so a well-written client throttles itself and never sees a refusal.
x-ratelimit-limit: 60
x-ratelimit-remaining: 57
x-ratelimit-reset: 1788191400 unix seconds
Over the limit returns 429 with retry-after.
The data changes every six hours, so polling faster than hourly gains you
nothing.
| Status | Means |
|---|---|
| 401 unauthorized | No key, an unknown key, a revoked one, or a lapsed subscription. One response for all four, deliberately. |
| 400 bad_request | A parameter was out of range or the wrong shape. |
| 404 not_found | No such route, or no such ticker. |
| 429 rate_limited | Slow down; retry-after says how long. |
There is no CORS header, on purpose. Calling this from a browser would mean shipping your key into a page where anyone can read it.