🔌API_□×

The solving endpoints are the fast ones: they run on the edge, touch no database, and do nothing but compute. A beginner position resolves in well under a millisecond; a full expert frontier with exact probabilities is typically 1–5ms, with a worst case around 80ms on the most tangled positions.

No key required. Everything below takes and returns JSON. The board is described by width, height, mines and a view array of width*height entries: -1 hidden, -2 flagged, 0..8 revealed. You never send the mine layout, which is exactly why the bots cannot cheat.

POST /api/bot/move edge

Ask a difficulty tier what it would play in a position.

curl -s https://minesweeper.sushii.dev/api/bot/move \
  -H 'content-type: application/json' \
  -d '{
    "width": 9, "height": 9, "mines": 10,
    "difficulty": "grandmaster",
    "view": [
      -1,-1,-1, 1, 0, 1,-1,-1,-1,
      -1,-1,-1, 2, 0, 2,-1,-1,-1,
      -1,-1,-1, 2, 0, 1,-1,-1,-1,
      -1,-1,-1, 1, 1, 2,-1,-1,-1,
      -1,-1,-1,-1,-1,-1,-1,-1,-1,
      -1,-1,-1,-1,-1,-1,-1,-1,-1,
      -1,-1,-1,-1,-1,-1,-1,-1,-1,
      -1,-1,-1,-1,-1,-1,-1,-1,-1,
      -1,-1,-1,-1,-1,-1,-1,-1,-1
    ]
  }'

{
  "difficulty": "grandmaster",
  "actions": [
    { "k": "flag", "i": 6 }, { "k": "flag", "i": 11 },
    { "k": "flag", "i": 20 }, { "k": "flag", "i": 24 },
    { "k": "flag", "i": 41 }
  ],
  "computeMs": 0.55,
  "suggestedDelayMs": 60
}

difficulty: drone, novice, casual, sharp, tactician, grandmaster, singularity, singularity-v2. Add seed and moveIndex to make a tier's randomness reproducible.

POST /api/bot/solve edge

Exact mine probability for every hidden cell, plus the cells that are provably safe or provably mines. Enumerates the frontier by connected component and folds in the global mine counter, so the numbers are true probabilities, not heuristics.

# same position as above
{
  "probabilities": [0.089286, 0.089286, 0, null, ..., 1, ...],
  "interiorProbability": 0.089286,   // hidden cells with no revealed neighbour
  "certainSafe": [2, 15],
  "certainMines": [6, 11, 20, 24, 41],
  "exact": true,
  "consistent": true,
  "nodes": 96,
  "computeMs": 0.55
}

null marks a cell that is already known. Optional budget (default 400000) caps the enumeration; exceeding it falls back to a density estimate and sets exact: false. consistent: false means no mine layout can explain the board at all — normally a wrong flag.

POST /api/bot/play edge

Play whole boards headlessly against a house bot and get timings back — the fastest way to sanity-check a difficulty or measure the machine you are on.

curl -s https://minesweeper.sushii.dev/api/bot/play \
  -H 'content-type: application/json' \
  -d '{"width":30,"height":16,"mines":99,"seed":"BENCH","difficulty":"singularity","games":20}'

{
  "games": 20, "wins": 12, "winRate": 0.6,
  "avgComputeMs": 2.4,
  "decisionsPerSecond": 121481,
  "results": [ { "seed": "BENCH#0", "won": true, "moves": 118, "computeMs": 1.9, "bv": 168 } ]
}

Up to 50 games per request. Set mode: "free" to let the bot pick its own opening.

POST /api/runs node

Submit a run. Send the move log; the server regenerates the board from the seed, replays every move, and derives the duration itself. Requires the identity cookie from POST /api/players.

{
  "mode": "setseed",
  "engineMode": "setseed",
  "cfg": { "width": 16, "height": 16, "mines": 40, "seed": "K7M2-QP4X-9TDR" },
  "moves": [ { "k": "open", "i": 88, "t": 0 }, { "k": "flag", "i": 71, "t": 412 } ]
}

Rejected if the replay does not end in a win, if timestamps go backwards, or if the implied click rate is not physically possible.

GET /api/leaderboard node

Query params: mode (setseed | daily | free | vs), size (tiny | beginner | intermediate | expert | mega | colossal), optional seed, sort (time | speed), limit. One row per player, their personal best.

GET /api/tournaments node

Live, upcoming and recent brackets. GET /api/tournaments/{id} returns the full bracket with entries and matches; POST /api/tournaments/{id}/join registers you (or, for bot brackets, a bot of yours by slug); GET|POST /api/tournaments/{id}/match fetches and submits your current match.

POST /api/bots node

Upload or replace a script: { "name": "...", "source": "..." }. The script is booted in a sandbox and has to clear a beginner qualifier before it is stored. POST /api/bots/{slug}/replay plays it over up to 10 seeded boards and returns the full move logs, which is what the Bot Lab animates. See the Bot Lab for the script contract.

Board generation

Boards are a pure function of (seed, width, height, mines, openingCell), built with a seeded sfc32 shuffle. The same inputs give the same board in the browser, on the server and at the edge — which is what makes set-seed races and bracket matches comparable at all. In seeded modes the opening cell is derived from the seed itself, so every player starts from an identical position.

Rate limits

The solving endpoints are unmetered. Writes (runs, uploads, tests) are limited per player and per IP; you will get a 400 with a plain-English message if you trip one.

PlayMultiplayerLeaderboardsTournamentsguest