A Bot in Five Minutes
This walkthrough takes you from nothing to a bot playing a full game against the server’s built-in sparring bot — using only REST calls, no streaming, no rules engine. Every command is a plain curl; translate to your language of choice as you go.
The base URL for the public platform is:
https://play-api.jc.id.lv1. Mint a token
Section titled “1. Mint a token”No registration, no signup — one request gives you an anonymous, ready-to-play token:
curl -X POST "https://play-api.jc.id.lv/bot/anon?name=my-first-bot"{ "token": "bearer-token-string", "team": "anon", "name": "my-first-bot-8b7a6c5d", "id": "bot:team:anon:my-first-bot-8b7a6c5d"}Save the token; every other call carries it as Authorization: Bearer <token>. Anonymous tokens are perfect for trying things out — they live in server memory (a restart invalidates them) and never appear on the ladder. When you want a durable identity, see Authentication & Identity.
export TOKEN="bearer-token-string"2. Challenge the house bot
Section titled “2. Challenge the house bot”The platform ships a built-in sparring partner at house/greedy. Challenge it to an unlimited-time game:
curl -X POST "https://play-api.jc.id.lv/bot/challenge" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"team": "house", "name": "greedy", "timeControl": {"Unlimited": {}}}'The house bot accepts immediately. Find the resulting game:
curl "https://play-api.jc.id.lv/bot/games" -H "Authorization: Bearer $TOKEN"{ "games": [ { "gameId": "game-uuid", "seat": "White", "activeSeat": "White", "dicePending": true, "version": 4 } ]}3. Contribute a dice seed
Section titled “3. Contribute a dice seed”As soon as the game starts, submit a random seed — your contribution to the provably-fair dice. It is optional but good citizenship (and it is your entropy in the roll):
curl -X POST "https://play-api.jc.id.lv/bot/game/$GAME_ID/seed" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"seed": "'"$(head -c 16 /dev/urandom | xxd -p)"'"}'4. Read the legal moves and play
Section titled “4. Read the legal moves and play”When dicePending is true and activeSeat is your seat, fetch the legal-move tree for the current roll:
curl "https://play-api.jc.id.lv/games/$GAME_ID/moves"{ "version": 4, "dfen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 NBK", "dicePending": true, "legalMoves": { "b1c3": { "g1f3": { "e2e4": {} } }, "e2e4": { "b1c3": { "g1f3": {} } } }}legalMoves is a prefix tree of UCI micro-moves. Walk any path from the root to a leaf ({}) — that path is one complete, legal turn. Submit it:
curl -X POST "https://play-api.jc.id.lv/bot/game/$GAME_ID/move" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"moves": ["e2e4", "b1c3", "g1f3"]}'{ "applied": true, "version": 5, "reason": null }The verdict comes back synchronously — no need to watch a stream to learn whether your move landed. That is what makes a poll-only bot viable.
5. Loop
Section titled “5. Loop”That is the whole game loop:
flowchart LR
A[Wake] --> B[GET /bot/games]
B --> C{My turn?<br/>dicePending & activeSeat}
C -- no --> Z[Sleep]
C -- yes --> D[GET /games/id/moves]
D --> E[Walk tree → moves]
E --> F[POST .../move]
F --> Z
Z --> A
Repeat until the game leaves Active. For Unlimited games a ~1-minute timer is plenty (a 120-second anti-abandonment cap is the only clock). Shorter time controls need faster polling or a live stream.
A complete example
Section titled “A complete example”The reference random bot does exactly this loop — discovery, accept, seed, and play — in about 100 lines of dependency-free Python:
examples/random_bot.py— poll-only, public domain.- rabestro/dicechess-reference-bot — a fuller client in Scala.
Next steps
Section titled “Next steps”- Authentication & Identity — claim a durable identity, rotate tokens, join the rating ladder.
- Game Mechanics — DFEN, the legal-move tree, and time controls in depth.
- Connection Modes — choose polling, streaming, or a serverless webhook.
- Provably-Fair Dice — verify that no one is grinding the dice.