No key, no signup. This works right now, from anywhere:
curl 'https://cuckootrade.com/api/v1/alpaca/v2/stocks/bars?symbols=AAPL,CRASH&timeframe=1Day&start=2026-07-01'
Using alpaca-py? Pass
url_override="https://cuckootrade.com/api/v1/alpaca" and any
non-empty strings as API keys — they're never checked. The API is also
self-describing: /api returns a machine-readable index,
and /llms.txt summarizes everything for AI coding
tools.
Every endpoint lives under /api/v1/, and provider-compatible
surfaces add the provider's name to the path:
/api/v1/{provider}/<the provider's own path> ← mimics that provider's wire format
/api/v1/<endpoint> ← CuckooTrade-native (e.g. /api/v1/stream)
Everything through the provider segment is CuckooTrade's namespace;
everything after it replicates the provider exactly, which is why a
client only needs its base URL changed. The v2 in
/api/v1/alpaca/v2/stocks/bars is Alpaca's own version, not
ours. Three providers are live:
| provider | base URL | stands in for |
|---|---|---|
| alpaca | https://cuckootrade.com/api/v1/alpaca | data.alpaca.markets |
| alphavantage | https://cuckootrade.com/api/v1/alphavantage | www.alphavantage.co |
| polygon | https://cuckootrade.com/api/v1/polygon | api.polygon.io |
Two things are versioned, on purpose: the path version
(v1) covers the API surface — paths, parameters, error
shapes — while the generation parameter covers the
data itself. A surface change bumps the path; a data change becomes a new
generation, and old generations stay queryable (see
determinism).
Alpaca-compatible historical OHLCV bars. Regular sessions only (09:30–16:00 ET, NYSE calendar — weekends and US market holidays have no bars; half-days trade as full sessions). Only completed bars are served, so any response you receive is permanently reproducible.
| param | meaning |
|---|---|
| symbols | required; comma-separated, max 50. Any well-formed symbol works: curated tickers (AAPL, SPY, …) sit at plausible price levels, everything else gets a stable hash-derived personality. |
| timeframe | [1-59]Min, [1-23]Hour, 1Day, 1Week, [1,2,3,4,6,12]Month. Default 1Day. Coarser bars aggregate exactly from finer ones. |
| start / end | RFC-3339 or YYYY-MM-DD, inclusive. Defaults: last 30 days. Weeks/months clipped by the window are dropped, not served partial. |
| limit | total bars across all symbols, 1–10000 (default 1000). More data ⇒ next_page_token; pass it back as page_token. |
| sort | asc (default) or desc. |
| seed | cuckoo extension. Any string; returns a different but equally deterministic dataset with the same statistical character. Omit it for the shared default dataset. |
| generation | cuckoo extension. Pins the generator version (currently 1). Responses carry X-Cuckoo-Generation. |
| adjustment, feed, asof, currency | accepted and ignored, for Alpaca client compatibility. No corporate actions exist in generation 1. |
Also available: /api/v1/alpaca/v2/stocks/{symbol}/bars
(single symbol) and
/api/v1/alpaca/v2/stocks/bars/latest?symbols=… (last
completed bar). Errors are Alpaca-shaped
{"code", "message"}, and every message states the valid
grammar plus a working example.
Alpha Vantage's single-endpoint format, faithfully — including its
quirks: values are strings, series are keyed newest-first, and errors
come back as HTTP 200 with an "Error Message" body,
because that is how the real API reports them. apikey
accepts anything, including nothing. Intraday is a premium endpoint
on Alpha Vantage's free tier; here it's free like everything else.
curl 'https://cuckootrade.com/api/v1/alphavantage/query?function=TIME_SERIES_DAILY&symbol=IBM'
| param | meaning |
|---|---|
| function | required: TIME_SERIES_INTRADAY, TIME_SERIES_DAILY, TIME_SERIES_WEEKLY, TIME_SERIES_MONTHLY, or GLOBAL_QUOTE. |
| symbol | required; one symbol. Scenario tickers work: symbol=CRASH. |
| interval | intraday only, required there: 1min, 5min, 15min, 30min, 60min. Labels are interval-end times in US/Eastern. |
| outputsize | compact (default, last 100 points) or full (~20 years daily; trailing 30 days intraday). |
| month | intraday only: YYYY-MM serves that calendar month. |
| apikey, adjusted, extended_hours | accepted and ignored. |
| seed / generation | cuckoo extensions, same semantics as everywhere else. |
Two deliberate deviations from the real thing: only completed bars are served (no partial current day/week/month row — determinism requires it), and sessions are regular-trading-hours only.
Polygon's aggregates format: the same envelope
(ticker, queryCount, resultsCount, adjusted, results, status,
request_id, count), bars as {v, vw, o, c, h, l, t, n}
with t in Unix milliseconds, next_url cursor
pagination, and {"status": "ERROR"} error bodies.
apiKey is accepted and ignored, and status is
always OK — synthetic data is never delayed.
curl 'https://cuckootrade.com/api/v1/polygon/v2/aggs/ticker/MSFT/range/1/day/2026-07-01/2026-08-01'
| path / param | meaning |
|---|---|
| range/{multiplier}/{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 (inclusive dates) or Unix millisecond timestamps. |
| sort | asc (default) or desc. |
| limit | 1–50000 (default 5000); past it, follow next_url. |
| adjusted, apiKey | accepted and ignored — no corporate actions exist, so adjusted and unadjusted are the same numbers. |
| seed / generation | cuckoo extensions; carried through next_url automatically. |
Also available:
/api/v1/polygon/v2/aggs/ticker/{ticker}/prev — the previous
session's daily bar, with Polygon's extra "T" field.
request_id is a hash of the request rather than a random
id, so identical requests stay byte-identical.
Every bar is a pure function of (symbol, timestamp, generation, seed).
Identical requests return identical bytes, forever, within a generation —
there is no database and no randomness at request time, which is also why
fully-specified historical responses ship
Cache-Control: immutable. If the generator ever improves,
that becomes generation 2; generation 1 stays queryable, so committed
fixtures never break.
Reserved symbols with scripted, calendar-anchored behavior. Every pattern appears within any 30-day window, so a demo or test never catches a quiet stretch. Responses stay schema-valid — the stress is in the values, never in malformed fields.
| ticker | behavior |
|---|---|
| CRASH | sharp ~25% crash mid-month, slow grind recovery |
| MOON | parabolic run-up peaking late in the month, hard correction |
| FLAT | zero-range bars pinned at $100.00 — breaks naive autoscaling |
| GAPPY | ±5–15% overnight gaps most days, quiet sessions |
| HALTS | minute bars absent during intraday halt windows |
| SPIKEY | single-minute wicks that spike and instantly revert |
| PENNY | ~$0.30 prices, four decimals, high volatility |
| CHOPPY | high volatility, zero net drift |
Server-sent events — curl-able, no WebSocket library needed. It's what
drives the live ticker at the top of every page here. Two clocks:
clock=demo (default) is an always-open synthetic session whose
price is a pure function of wall time, so every viewer sees the same tick
at the same instant; clock=real follows the NYSE calendar and
emits completed 1-minute bars, staying silent (heartbeats only) while the
market is closed. Max 10 symbols and 5 concurrent streams per address;
streams close after 15 minutes — reconnect freely.
curl -N 'https://cuckootrade.com/api/v1/stream?symbols=CUCKOO,CRASH'
60 requests per minute sustained per address, with burst headroom to 120 —
no key required. Responses carry
RateLimit-Limit / -Remaining / -Reset headers, and a 429
tells you exactly how long to back off. Limits are enforced per replica,
so the effective ceiling may be somewhat higher than advertised.
The API is stateless and MIT-licensed. If your CI pipeline shouldn't
depend on an external service, run your own instance: clone
the repo and
start it with pip install -r api/requirements.txt &&
python api/api.py, or pull the prebuilt container image published
alongside the repo. Determinism means a local instance serves
byte-identical data to cuckootrade.com for the same generation.
X-Cuckoo-Synthetic: true. CuckooTrade exists to exercise
code paths — development, CI, demos, teaching. It is not market data,
must never inform a real trade, and is not a backtesting tool: a strategy
that profits against synthetic data has learned the generator, not the
market.