The base URL swap
Replace https://api.polygon.io with
https://cuckootrade.com/api/v1/polygon. Everything
after that is Polygon’s own path:
curl 'https://cuckootrade.com/api/v1/polygon/v2/aggs/ticker/MSFT/range/1/day/2026-07-01/2026-08-01'
{
"ticker": "MSFT",
"queryCount": 22,
"resultsCount": 22,
"adjusted": true,
"results": [
{"v": 24183400, "vw": 431.87, "o": 429.4, "c": 433.12,
"h": 434.9, "l": 428.1, "t": 1782964800000, "n": 214905}
],
"status": "OK",
"request_id": "234ee1ae9d085ae58a8d694fac44e7ed",
"count": 22
}
Polygon’s conventions are preserved down to the awkward
details: t is Unix milliseconds rather than an ISO
string, and results and count are
omitted entirely when nothing matched rather than sent as
[] and 0 — which is what the real API
does, and a common source of client-side crashes.
request_id is deterministic. It is an md5 of the
request, so the same call returns the same id forever. That makes it
assertable in a test, which the real API’s random ids are not.
Parameters
| Segment / param | Accepted |
|---|---|
| multiplier | Any positive integer, subject to the timespan limits below. |
| timespan | minute (1–59), hour (1–23), day, week, month (1,2,3,4,6,12), quarter (1,2,4), year. |
| from / to | YYYY-MM-DD or Unix milliseconds — both, as Polygon allows. |
| sort | asc (default) or desc. |
| limit | Up to 50,000. |
| cursor | Real cursor pagination, delivered via next_url. |
| adjusted | Accepted and echoed; this surface does not restate. |
| apiKey | Accepted and ignored. Nothing is ever checked. |
| seed, generation | CuckooTrade extensions — alternate universe, pinned generator. |
There is also /v2/aggs/ticker/{ticker}/prev for the
previous session’s daily bar.
import httpx
url = ("https://cuckootrade.com/api/v1/polygon"
"/v2/aggs/ticker/MSFT/range/1/day/2026-01-01/2026-08-01?limit=10")
while url:
payload = httpx.get(url).json()
for bar in payload.get("results", []): # absent, not empty, when unmatched
print(bar["t"], bar["c"])
url = payload.get("next_url") # already carries the cursor
Errors keep Polygon’s shape
{
"status": "ERROR",
"request_id": "9f2c1b0e5d3a47c8b1e6f0a2d7c94b35",
"error": "timespan=fortnight is not valid. Use minute, hour, day, week, month, quarter or year -- e.g. /v2/aggs/ticker/MSFT/range/1/day/2026-07-01/2026-08-01"
}
The shape matches Polygon; the message deliberately does not. Errors get read at the moment someone is stuck, so every one states the valid grammar and includes a URL that works.
What the real API cannot do
Scenario tickers work on this surface exactly as they do on the others — the engine is shared, so only the wire format differs:
curl 'https://cuckootrade.com/api/v1/polygon/v2/aggs/ticker/CRASH/range/1/day/2026-07-01/2026-08-01'
And fault injection rides the same scenario= parameter,
returning Polygon’s error shape at whatever status you name:
curl -i 'https://cuckootrade.com/api/v1/polygon/v2/aggs/ticker/MSFT/range/1/day/2026-07-01/2026-08-01?scenario=flap:2'
One world, three formats
All three provider surfaces read from the same deterministic engine, so the same symbol on the same day returns identical OHLCV through each — only the serialisation differs. A cross-provider consistency test enforces this in CI.
That makes this a useful place to test a provider migration: point the same test suite at both surfaces and any difference is your adapter, not the data.
curl 'https://cuckootrade.com/api/v1/polygon/v2/aggs/ticker/AAPL/range/1/day/2026-07-06/2026-07-06' curl 'https://cuckootrade.com/api/v1/alpaca/v2/stocks/bars?symbols=AAPL&timeframe=1Day&start=2026-07-06&end=2026-07-06'
Scope and honesty
Aggregates and previous-close are implemented. Reference data,
trades, quotes, snapshots, and the Polygon WebSocket are not. Every
response carries X-Cuckoo-Synthetic: true.