Mosaic 1 API
Two tiers. The Research API is free: we run the table, you play against Mosaic. The Full API is the model itself: you bring the table — a simulator, an analysis pipeline, your own game — and stream decisions out of Mosaic at any state you like.
Base
Base URL https://api.icosalab.com. Authenticate every
request with an X-Api-Key header
(get a key — free). All bodies are JSON. Games:
"hu" (heads-up, 200bb) and "6max" (six-handed,
100bb); blinds 50/100 chips; stacks reset each hand.
Protocol
| Method | Path | Body | Purpose |
|---|---|---|---|
POST | /v1/tables | {"game":"hu"|"6max"} | Create a table, deal the first hand |
GET | /v1/tables/{id} | — | Current view |
POST | /v1/tables/{id}/hands | — | Deal the next hand |
POST | /v1/tables/{id}/act | {"slot": int} or {"raise_to": chips} | Take your action; bots respond |
DELETE | /v1/tables/{id} | — | Close the table |
The view
Every response returns the state you're entitled to see:
hole— your two cards;board,pot,stacks,bets.seat— your engine seat this hand (seat 0 posts SB, 1 posts BB, last seat is the button; seats rotate every hand).legal— when it's your turn: available action slots, each with akind(fold,check,call,raise_to), the chip totalto_chips, and for raises the pot fractionfracand anallinflag. The slots are the models' own size grid, but you are not limited to it: act with{"raise_to": chips}at any amount between the smallest listed raise (the min-raise) and the largest (all-in); out-of-window amounts are clamped. The models read your exact sizes — bet history is consumed as continuous pot fractions, not grid indices.events— the sampled actions taken since your last call, including every bot action.result— on hand end: your payoff, the final board and, only when the hand reached a genuine showdown, the revealed hole cards. Folded hands stay mucked.
Sessions and fairness
- One engine session per table: the models accumulate a read on your play across hands, as any opponent would. Close the table to reset it.
- The server deals from a seeded shuffle; bot actions are sampled from the model at its serving decode. No probabilities, EVs, or ranges are exposed.
- Idle tables expire after 15 minutes; an abandoned hand is scored as a fold.
- Up to 4 concurrent tables per key. Use one key per bot — your dashboard stats stay clean, and labels keep them sorted.
Rate limits
Token buckets per key and per source IP, sized so an actively playing bot never notices them. HTTP 429 means slow down; sustained abuse leads to key revocation.
Data use
We log complete hands server-side — including cards that were never shown to you — and use them for research and model training. Aggregate per-key results appear in your dashboard.
The Full API is in private beta. The spec below is what we're building with early partners — metered per decision, volume pricing. Email us for access.
One endpoint, any state
You describe a no-limit hold'em decision point; Mosaic returns its action. No table lifecycle, no server-side dealing — your state, our decision. All amounts are in big blinds. Seats are in posting order: seat 0 posts SB, seat 1 posts BB, the last seat is the button (heads-up: seat 1 is the button and posts SB).
POST /v2/decisions { "seats": 6, // 2 routes to the heads-up model, 3–6 to 6-max "session": "ms_9f3e2c…", // optional — see opponent modeling "hand": { "hero": 3, // the seat to decide for "hole": ["Ah", "Kd"], "board": ["7c", "8d", "2s"], "stacks": [61.5, 98.0, 100.0, 87.2, 0, 104.0], "bets": [0, 0, 3.5, 0, 0, 3.5], "history": [ {"seat": 2, "action": "raise_to", "to": 2.5}, {"seat": 5, "action": "call"}, {"seat": 2, "action": "raise_to", "to": 3.5} ] }, "style": {"aggression": 0.3}, // −1.0 … +1.0, see the style knob "decode": {"temperature": 0.05} // 0 = deterministic; capped at 1.0 } 200 OK { "action": {"kind": "raise_to", "to": 11.0, "frac": 0.72, "allin": false}, "considered": [ {"kind": "fold"}, {"kind": "call", "to": 3.5}, {"kind": "raise_to", "to": 7.8}, {"kind": "raise_to", "to": 11.0}, … ], "model": "mosaic1-6max", "request_id": "req_01H…" }
The style knob
A continuous aggression parameter applied at the decode: it shifts
decisions the model was close on and leaves clear folds alone. 0
is Mosaic's own game; −1 plays markedly tighter (roughly half
the open-raise frequency), +1 markedly looser and more
aggressive (~1.5× hands played, ~1.5× raise frequency). The presets in the
browser game are this knob at −0.5 / 0 / +0.5.
Opponent modeling
Mosaic's biggest measured edge is adaptation: conditioning on opponent tendencies is worth +111 to +711 bb/100 against fixed archetypes in our ablations. To use it, create a session and stream your completed hands; decisions inside that session condition on what Mosaic has seen from each seat.
| Method | Path | Purpose |
|---|---|---|
POST | /v2/sessions | Create a persistent opponent-model context |
POST | /v2/sessions/{id}/hands | Report a completed hand (full action history; showdown cards optional) |
DELETE | /v2/sessions/{id} | Forget everything |
Seat identities inside a session are yours to assign and keep stable — "seat 4 in this session" is one opponent as far as the model is concerned. Stateless decisions (no session) get a fresh-opponent prior.
Batch
POST /v2/decisions:batch takes an array of decision
requests and returns an array of decisions — for simulations and
large-scale analysis. Single decisions run in ~10–15 ms of model time;
batches amortize transport.
Honest edges of the envelope
- Mosaic's own raises come from its native geometric size grid —
consideredshows the grid at your decision point. History amounts are not snapped: the models consume bet history as continuous pot fractions, so exact amounts carry through (the 6-max model additionally tags each past action with its nearest grid size). The models trained against their own grid, though — histories full of exotic sizes are represented exactly but sit slightly outside the training distribution. - Trained at 100bb (6-max) and 200bb (heads-up) starting depths. Arbitrary stacks are accepted; fidelity is best in roughly the 40–250bb effective range.
- Decisions are sampled actions at your chosen decode — same as the research tier, there are no probability vectors, EVs, or ranges in any response.
- The terms apply unchanged: no real-money play, no use against real-money platforms.