What it is

A dedicated /api/dice endpoint built for game developers. Pass a dice expression — 3d6, 2d20+5, 1d100-10, 4d6 — and the API returns each individual die, the modifier, and the total. Every roll is backed by the same provably fair HMAC-SHA256 stream that powers the rest of the Provable.io API, so any roll can be re-derived from the seed and confirmed against a published serverHash.

Most ad-hoc dice rollers use Math.random() server-side and ask players to trust the result. This one publishes the proof.

The pain point

If you're building a tabletop companion app, an online TTRPG client, a Discord bot, or anything where a die roll matters to a player, you eventually hit the same wall: a player rolls a critical, you roll, the player complains, and there's no evidence chain you can point at. Either you trust the server or you re-implement provably fair from scratch. The dice roller API is the off-the-shelf answer.

Try it live

Roll 4d6 with a player-supplied seed. The response includes each individual die in rolls, the running total, and the serverHash a verifier needs.

curl "https://api.provable.io/api/dice?clientSeed=player_42_attack_roll&notation=4d6"

A more familiar example — a d20 attack with a +5 modifier:

curl "https://api.provable.io/api/dice?clientSeed=player_42_round_3&notation=2d20%2B5"

Supported notation

Integration snippet

// Roll 3d6 for a D&D stat block
const url = new URL("https://api.provable.io/api/dice");
url.searchParams.set("clientSeed", `char_${characterId}_str`);
url.searchParams.set("notation", "3d6");

const res = await fetch(url, {
  headers: { "x-api-key": process.env.PROVABLE_KEY }
});
const { outcome, serverHash } = await res.json();
// outcome.rolls = [4, 6, 3]
// outcome.total = 13
console.log(outcome.rolls, "→", outcome.total);

// Persist serverHash with the character — anyone can re-verify later.

Verifying a roll

Three values, three steps, no trust:

  1. Show the player the clientSeed, the serverHash, and the published roll.
  2. Player visits /verify and pastes the trio in.
  3. The page recomputes the HMAC stream, applies the dice mapping, and confirms (or refutes) the published result.

For maximum trust, publish the serverHash before the player chooses to roll (e.g. at session start). That eliminates the "but you knew my seed when you generated yours" attack.

Deep dive: how the dice mapping works

The dice endpoint draws one float per die from the underlying HMAC byte stream and maps it to 1 + floor(f * sides). The modifier is added to the sum only — individual dice are unaffected, so per-die displays in your UI match the verified result exactly.

For the long-form walkthrough — including a Fisher-Yates explanation that's structurally identical to dice — see the recipe page: Dice rolls & coin flips.

Where it fits

Related