Build your own tools on the league's draft data — a cheat sheet, a "best available" board, or a script that sets your pick queue for you.
- Acts as you. A key resolves to one manager. It reads league-public data and can only ever change your own queue — you can't see or touch anyone else's.
- Instance-stamped. Every response includes
"instance": "league"(or"demo") so you always know which server answered. - Add-only fields. Existing fields won't be renamed or change type; new ones may be added. Safe to build on without a version pin.
- CORS-open. The API sends
Access-Control-Allow-Origin: *, so a browser tool hosted anywhere can call it (auth is by key, never cookies).
export line.)
The demo is read-only — sign in to your own league to mint a key.
Base URL https://ligazo.app/demo. Authenticate with your key as
?key=… or an X-Api-Key header. If a key is presented and it's wrong,
you get a 401 even in a signed-in browser — a bad key never silently falls back
to your session.
/api/draft — every league at once (array under leagues)./api/draft/<league> — one league./api/draft/<league>/status — cheap poll: picks_made,
on_the_clock, your_next_pick. Poll this; fetch the big one on change./api/draft/<league>/queue — your current pick queue, in order./api/draft/<league>/queue — set your whole queue. Body
{"players": ["id1", "id2", …]} in priority order. Ids that aren't draftable
(already taken, wrong league, unknown) come back under rejected./api/rules — the scoring matrix + roster/lineup/armband structure, straight
from the engine so it never drifts./api/standings (or /<league>) — the table: cumulative points
per manager, overall and per league, ranked (ties share a rank)./api/fixtures (or /<league>) — real-match Score Center: each
game's clubs, score, status (sched/live/ht/ft), minute, kickoff.429 with a Retry-After header — pause and retry.ETag. Send it
back as If-None-Match and you get 304 Not Modified (no body) when nothing
changed — cheap polling. Pair it with /status for a near-free refresh loop.<league> is the exact, URL-encoded league name. All five,
in draft order (append /queue or /status to any of these):
https://ligazo.app/demo/api/draft/ESP-La%20Liga?key=$KEY
https://ligazo.app/demo/api/draft/ENG-Premier%20League?key=$KEY
https://ligazo.app/demo/api/draft/FRA-Ligue%201?key=$KEY
https://ligazo.app/demo/api/draft/ITA-Serie%20A?key=$KEY
https://ligazo.app/demo/api/draft/GER-Bundesliga?key=$KEY
A single league object (the all-leagues call wraps these under
leagues:[…] with instance, season, generated_at):
{
"instance": "league", // "league" or "demo" — which server answered
"generated_at": "2026-08-09T…Z",
"league": "ESP-La Liga", // exact id — use it in the URL
"name": "La Liga",
"status": "live", // pending | live | complete
"snake": true, // draft snakes: even rounds reverse
"roster_size": 8,
"picks_made": 4,
"slots_remaining": 92,
"available_count": 477,
"on_the_clock": { // null unless status == "live"
"pick": 5, "round": 1, "manager_id": 12, "manager": "…", "team": "…",
"deadline": "2026-08-09T16:33:35Z"
},
"picks": [ { "pick": 1, "round": 1, "made_at": "…", "manager_id": 7,
"manager": "…", "team": "…", ...player }, … ],
"managers": [ { "manager_id": 1, "manager": "…", "team": "…",
"seat": 0, // draft-seat order (0-based)
"slots_left": 7,
"autopick": false, // on Auto Draft?
"roster": [ ...player ] }, … ],
"available": [ ...player ], // who's LEFT, best prev-season first
"you": { // present when you call with your key
"manager_id": 1,
"your_next_pick": 14, // your next pick number (null if done) — no snake math
"autopick": false
}
}
// ...player =
{ "player_id": "p123", "player": "Kylian Mbappé", "pos": "FWD", "club": "Real Madrid",
"prev_pts": 152, // last season's Ligazo points; 0 for newcomers
"kind": "player", // "player" | "club_gk"
"display_name": "Kylian Mbappé" } // for a club-GK: "FC Barcelona (GK)"
{ instance, league, manager_id, queue:[…player…] },
plus rejected:[…ids…] on a POST. A goalkeeper slot is drafted by club, not
person: it comes back as kind: "club_gk" — use display_name and don't
parse the raw GK::<club> id.export KEY=your-key and the
examples below work as-is.
curl "https://ligazo.app/demo/api/draft?key=$KEY"
curl "https://ligazo.app/demo/api/draft/ESP-La%20Liga/status?key=$KEY"
curl "https://ligazo.app/demo/api/rules?key=$KEY"
curl "https://ligazo.app/demo/api/standings?key=$KEY" curl "https://ligazo.app/demo/api/fixtures/ESP-La%20Liga?key=$KEY"
curl -sD- -o/dev/null -H 'If-None-Match: "<etag-from-last-response>"' \ "https://ligazo.app/demo/api/draft/ESP-La%20Liga?key=$KEY"
curl "https://ligazo.app/demo/api/draft/ESP-La%20Liga?key=$KEY"
curl -X POST "https://ligazo.app/demo/api/draft/ESP-La%20Liga/queue?key=$KEY" \
-H "Content-Type: application/json" \
-d '{"players": ["id1", "id2", "id3"]}'
import os, requests, urllib.parse
BASE, KEY = "https://ligazo.app/demo", os.environ["KEY"]
draft = requests.get(f"{BASE}/api/draft", params={"key": KEY}).json()
for lg in draft["leagues"]:
if lg["status"] == "complete":
continue
fwds = [p["player_id"] for p in lg["available"] if p["pos"] == "FWD"][:5]
path = urllib.parse.quote(lg["league"]) # encodes the space in the name
requests.post(f"{BASE}/api/draft/{path}/queue",
params={"key": KEY}, json={"players": fwds})
print(lg["league"], "queued", len(fwds))