Public API
Read-only HTTP endpoints under geck-data.vercel.app. All return JSON unless noted. Rate limit: courteous use; we may throttle at the edge if a single IP hammers an endpoint.
Contract guarantees
What we promise about the endpoints below.
- Adding fields is non-breaking. Consumers should ignore unknown keys.
- Removing or renaming a field is a versioned change. We will add a
v2path before deprecating v1. - Cresteds only on every endpoint. Other species are filtered out at the source view (see migration 0010).
- CORS open to any origin for the GET endpoints. POST endpoints require Bearer auth and are not in scope here.
- Members only (since 13 Oct 2026): endpoints that return single listings or sellers. Send
Authorization: Bearer <Supabase access token>for a signed-in account, or call them from a signed-in browser. Without it they answer 401. Aggregate prices stay public.
GET/data/market.json
Members only. Every recent priced crested listing with its seller, plus the breeder list.
/data/market.json
Heavy payload (megabytes). Cache at the consumer; the snapshot updates roughly hourly.
GET/api/market/fair-price
Price estimate for a trait set. Either supply a canonical combo id or a comma-separated trait list. Returns p10/p25/p50/p75/p90 plus adjustment-factor multipliers for age, sex, weight, proven-breeder status.
| Param | Type | Note |
|---|---|---|
| combo | string | Canonical combo id (lw-cap, axa-pin, etc). Either this or `traits`. |
| traits | string | Comma-separated traits. Matched into a combo or used directly. |
| age | enum | hatchling, juvenile, subadult, adult, proven_breeder, unknown |
| sex | enum | male, female, unknown |
| weight | number | Grams |
| proven | bool | true / false |
| recent_sales | int | If > 0, include up to N recent comparable sales (price, date and days to sell; no listing, seller or link). |
Documented at /docs/geck-inspect-integration.md; the contract is shared with the classifier app.
GET/api/market/temperature
Composite market temperature plus a weekly time series of listing volume, sold count, sell-through rate, median sold price and median days to sell. `score` is a number from 0 to 100 only when the data supports one: it is null whenever `status` is 'unavailable', which is the current state, and the response then carries `unavailable_reason` and a plain-English `unavailable_detail` naming the gate that failed. A client that reads `score` without checking `status` will treat a refusal to score as a zero.
/api/market/temperature
Backs the floating temperature card on /market. The gates are, in order: no weeks in the view, no captured sale in the trailing window, too few captured sales, too few complete weeks to rank against, a baseline with no spread, and a current week not yet fully observed. Sales inferred from listings that stopped appearing are deliberately not counted toward the demand side.
GET/api/market/arbitrage
Members only. Legacy pHash pair candidates (MorphMarket image vs cross-platform image). Separate from the dashboard source axis.
/api/market/arbitrage
Empty until a pHash worker has populated phash columns. Best-effort: pHash collisions exist; treat each row as a heads-up rather than a confirmation. Combo-level KR vs US asks live at /api/market/source-arbitrage instead.
GET/api/market/source-arbitrage
Combo-level ask vs ask: Feedle Air USD (Korea scheduled import) vs MorphMarket live listings. Matched by HIGH_VALUE_COMBOS on traits, not pHash. Hides rows with n<3 on either side. Altitude Exotics, TikisGeckos, and Feedle KRW are not in this table.
/api/market/source-arbitrage
Ask vs ask, not sold. MorphMarket uses current_status=live; last_seen_at is not a 48h gate because catalogue leftovers still dominate that column. Feedle Air is not a MorphMarket click-buy.
GET/api/market/traits
Trait vocabulary observed in the database, with per-trait listing counts.
/api/market/traits
Used by the trait picker on /whats-it-worth.
GET/api/market/snapshot.csv
Members only. CSV mirror of /data/market.json, one row per listing.
| Param | Type | Note |
|---|---|---|
| window_days | int | Defaults to 90. |
Returns Content-Type: text/csv. Suitable for sheets / Excel.
GET/api/stats
Lightweight global counts for the homepage hero and the /status route.
/api/stats
Returns total listings, sellers, sold, etc.
GET/api/status.json
Per-stream ingest health snapshot. Reports lifetime + 7d counts and freshness per event stream.
/api/status.json
Mirrors the /status page contents.
Not in scope here
The following endpoints exist but require auth and are not considered public. Treat them as implementation details that may change without notice:
/api/ingest- extension event firehose, Bearer auth./api/upload- dashboard drop-zone, session auth./api/alerts/*- alert lifecycle, owner-scoped./api/training/*- ML pipeline, admin only./api/trigger-scrape- admin only.
Found a bug or want a new endpoint? Open an issue on github.com/tennysonmilesperhour/geck-data.