Create Minigame

When building a minigame you can add:

  • A SlotMachine block
  • A WheelSpinner block (also called Wheel of fortune)
  • A Sudoku block
  • A Minesweeper block
  • A Crosswords block
  • Form fields: FormBuilder, standalone FormField blocks, or an embedded FormSelect
  • General blocks: Content, Quote, and Ad
  • One result page

Every minigame block's title is required and has to carry text: "", a whitespace-only string and markup that renders to nothing are all rejected, because the game would be published with a blank heading above it.

Adding a SlotMachine

Properties

PropertyRequiredTypeDescriptionDefault
typestringSet to SlotMachine
titlestringThe title of the slot machine
descriptionstringThe description of the slot machine
mediastring|objectMedia to display as part of the block. See Use media
startBalanceintegerThe starting balance of the user; 1-1000. 0 (or less) is a machine that cannot be played, and the ceiling keeps the balance inside the small badge the player sees10
winningProbabilitystringSet to Low, Medium or HighMedium
winTitlestringTitle of the message shown once the player lands a winning combination
winDescriptionstringDescription of that win message
winMediastring|objectMedia of that win message
hasCustomSymbolsEnabledbooleanWhether custom reel symbols are rendered instead of the default emojifalse
customSymbolsobjectUp to 6 custom reel symbols; see below. Every entry carries its own keys instead of a title - see item formats

The slot machine has no mediaOrientation - its media is always shown as-is.

Note: Like WheelSpinner below, a SlotMachine block has no score property - a spin only produces a win/loss outcome (whether the reels land on the winning combination), not a rankable score.

Custom reel symbols

The reels always carry exactly these six symbols, and customSymbols replaces the emoji of one of them with an image of your own. There is no way to add a seventh symbol or a symbol under a different key. customSymbols only accepts objects (see item formats) - each entry needs both a symbolKey and a media.

PropertyRequiredTypeDescriptionDefault
symbolKeystringWhich symbol to replace: :recycle:, :cherries:, :lemon:, :grapes:, :bell:, or :dollar:
mediastring|objectThe image to use; must be an image (no video/social media)

Rules:

  • At most 6 entries, and every symbolKey may only appear once - a duplicate key is rejected.
  • Supplying at least one custom symbol automatically sets hasCustomSymbolsEnabled to true, even if you explicitly send false - otherwise the custom symbols would never be rendered.

Example

{
    "title": "Spin the slot machine",
    "description": "Try your luck!",
    "type": "SlotMachine",
    "startBalance": 1000,
    "winningProbability": "High",
    "winTitle": "Jackpot!",
    "winDescription": "You won a 20% voucher.",
    "customSymbols": [
        {
            "symbolKey": ":cherries:",
            "media": "https://httpbin.io/image/jpeg"
        }
    ]
}

Adding a WheelSpinner

Properties

PropertyRequiredTypeDescriptionDefault
typestringSet to WheelSpinner
titlestringThe title of the wheel spinner
itemsobjectThe items on the wheel, 2-30; see WheelSpinnerItem properties below - see item formats
descriptionstringThe description of the wheel spinner
mediastring|objectMedia to display as part of the block
isMediaVisiblebooleanWhether the items' own media renders on the wheel segmentsfalse
areEmojisEnabledbooleanWhether emoji are rendered on the wheel segmentsfalse
isCopyToClipboardButtonEnabledbooleanWhether the result offers a "copy to clipboard" button for the awarded item, e.g. a discount codetrue

The wheel spinner has no mediaOrientation. Its items are objects described by the properties below rather than by a title (see item formats).

Note: A WheelSpinner block and its items do not support scoring - neither has a score property (unlike Sudoku below, which does). This is also why a minigame consisting of nothing but a WheelSpinner cannot be connected to a Leaderboard: a wheel spin only produces a win/loss/free-spin outcome, not a rankable score. See Create and connect to Leaderboard.

WheelSpinnerItem properties

PropertyRequiredTypeDescriptionDefault
typestringSet to either Win, Loss, or FreeSpin
titlestringThe title of the item
percentintegerThe percentage of the wheel this item takes up; 0-100
awardrequired if type is WinstringThe award the user gets, e.g. a voucher code
backgroundColorstringThe background color of the itemrgba(255, 255, 255, 1)
textColorstringThe text color of the itemrgba(0, 0, 0, 1)
mediastring|objectMedia to display on this wheel segment

Note: No wheel item has a score property either - a Win/Loss/FreeSpin item only carries its award/percentage/appearance, never a score.

Note: The percent values across all items must sum to exactly 100, otherwise a validation error is thrown. Because the API always states the percentages explicitly, the Creator's "custom percentages" option is switched on automatically for wheels built via the API.

Note: Giving any item a media automatically switches isMediaVisible on for the whole block. Send isMediaVisible: false without item media if you want a wheel without images.

Example

{
    "title": "Spin the wheel",
    "description": "Try your luck!",
    "type": "WheelSpinner",
    "items": [
        {
            "title": "Win 100$",
            "type": "Win",
            "percent": 50,
            "award": "100$"
        },
        {
            "title": "Lose 50$",
            "type": "Loss",
            "percent": 30,
            "award": "-50$"
        },
        {
            "title": "Free spin",
            "type": "FreeSpin",
            "percent": 20,
            "award": "Free spin"
        }
    ]
}

Adding a Sudoku

Properties

PropertyRequiredTypeDescriptionDefault
typestringSet to Sudoku
titlestringThe title of the sudoku block
descriptionstringThe description of the sudoku block
mediastring|objectMedia to display as part of the block. Adding it automatically switches its display on
mediaOrientationstringHow it is cropped: Settings, Wide, Square, Tall, or OriginalSettings
difficultyintegerThe difficulty level of the sudoku; 0-100. A knob, not the percentage of cells removed - see the note below50
areRulesVisiblebooleanWhether the rules are visible to the usertrue
isConflictHighlightingAllowedbooleanWhether conflict highlighting is allowedfalse
isGuessCheckingAllowedbooleanWhether guess checking is allowedfalse
refreshIntervalstringThe interval in which the sudoku automatically refreshes; set to a value of: None, Hourly, Daily, Weekly, or MonthlyNone
scoreintegerPoints awarded for solving the puzzle1
successMessagestringMessage shown once the puzzle is solved. Setting a non-empty message switches the success message on; an empty string switches it off
isSuccessMessageEnabledbooleanWhether the success message is shown. Sending false keeps the message stored but hidden. See feature togglesderived from successMessage
successMessageMediastring|objectMedia of that success message
isSuccessMessageMediaEnabledbooleanWhether the success message's own media is displayedfalse

The puzzle itself is generated for you from difficulty - you cannot supply a grid or a solution.

Note: difficulty is a 0-100 knob, not a share of the grid. The generator blanks floor(difficulty * 0.3) + 31 of the 81 cells, so the scale runs from 31 blanks (50 givens) at 0 to 61 blanks (20 givens) at 100 - between 38% and 75% of the cells removed, never less than 38%. It moves one cell per ~3.3 points, so 0 and 1 produce the same puzzle. A cell is only blanked while the puzzle still has a unique solution, so the result can fall a cell or two short of that number, never above it. difficulty: 40, for example, gives 38 givens - not the 49 a "40% removed" reading would suggest.

Example

{
    "title": "Sudoku Challenge",
    "description": "Solve the puzzle!",
    "type": "Sudoku",
    "difficulty": 70,
    "areRulesVisible": true,
    "isConflictHighlightingAllowed": true,
    "isGuessCheckingAllowed": true,
    "refreshInterval": "Weekly"
}

Adding a Minesweeper

Properties

PropertyRequiredTypeDescriptionDefault
typestringSet to Minesweeper
titlestringThe title of the minesweeper block
descriptionstringThe description of the minesweeper block
mediastring|objectMedia to display as part of the block. Adding it automatically switches its display on
mediaOrientationstringHow it is cropped: Settings, Wide, Square, Tall, or OriginalSettings
rowsintegerHeight of the grid; 5-189
colsintegerWidth of the grid; 5-189
minesintegerHow many mines are hidden in the grid; 1-20 whatever the board size is10
gameModestringSet to Normal, Streak, or NoneStreak
areRulesVisiblebooleanWhether the rules are visible to the usertrue

The board is laid out at play time from rows, cols and mines - there is nothing to configure per cell, and the smallest grid (5x5) always has room for the maximum of 20 mines.

Note: the mine cap does not scale with the board - it is 20 on every grid size, matching the Creator's own mine input, so a board built here stays editable there. Mine density therefore falls as the board grows: 20 mines in 25 cells on the smallest grid, but 20 in 324 cells (about 6%) on an 18x18, well below the 15-20% a conventional Minesweeper uses. Large boards play sparse; choose a smaller grid if you want a dense one. An 18-column board is also wider than a default 540px embed and scrolls sideways inside it rather than being visible all at once.

Note: Unlike Sudoku and Crosswords, a Minesweeper block has no success message and no score property.

Example

{
    "title": "Clear the minefield",
    "description": "Avoid the mines!",
    "type": "Minesweeper",
    "rows": 12,
    "cols": 12,
    "mines": 18,
    "gameMode": "Normal",
    "areRulesVisible": true
}

Adding a Crosswords

Properties

PropertyRequiredTypeDescriptionDefault
typestringSet to Crosswords
titlestringThe title of the crossword block
wordsobjectThe words and their clues, at least 1; see CrosswordWord properties below - see item formats
descriptionstringThe description of the crossword block
mediastring|objectMedia to display as part of the block. Adding it automatically switches its display on
gridSizeintegerThe most room the layout may use, and therefore the longest word it can take; 5-15. Not the grid you get: the puzzle is laid out in the smallest grid its words still interlock in (never smaller than 5), and that is the size stored and read back. Leave it out and the words are simply fitted into the smallest grid that takes themfitted to the words
areRulesVisiblebooleanWhether the rules are visible to the userfalse
isHighlightingCurrentWordEnabledbooleanWhether the word the player is currently on is highlightedtrue
isGuessCheckingAllowedbooleanWhether the player may check their current guesstrue
isAutoCheckingAllowedbooleanWhether each entry is checked as it is typedtrue
isAnswerRevealingAllowedbooleanWhether the player may reveal an answertrue
highlightedWordColorstringColor of the currently active word#ffe082
highlightedCellColorstringColor of the single active cell#90caf9
scoreintegerPoints awarded for solving the puzzle1
successMessagestringMessage shown once the puzzle is solved. Setting a non-empty message switches the success message on; an empty string switches it off
isSuccessMessageEnabledbooleanWhether the success message is shown. Sending false keeps the message stored but hidden. See feature togglesderived from successMessage
successMessageMediastring|objectMedia of that success message
isSuccessMessageMediaEnabledbooleanWhether the success message's own media is displayedfalse

The crossword block has no mediaOrientation.

CrosswordWord properties

PropertyRequiredTypeDescriptionDefault
textstringThe answer, 2 letters up to gridSize letters long
cluestringThe clue shown for that answer, plain text (HTML is rejected - the clue list prints what it is given, so the tags themselves would show up in the puzzle), at most 200 characters. It is genuinely required: an empty or whitespace-only clue is rejected like a missing one, because the word would be drawn as a numbered entry of the grid with nothing in the clue list to answer it by
directionstringSet to across or down to pin the word to that direction. There is no default to fall back to: leave the key out (or send null) and the direction is part of what the layout decides - whichever one interlocks the word best, except for the very first word of the list, which is laid down across through the centre of the grid to start the puzzle off. An empty string is not a way to say "no direction" and is rejecteddecided by the layout

A word entry has exactly these three keys - any other key is rejected. The same answer cannot appear twice, however differently cased or padded and however different the two clues are: the puzzle has one place for those letters, so the second clue would be numbered like the first with no entry of its own to answer.

Note: You supply the words and their clues; where they sit is generated for you. The grid, each word's starting cell, its direction and number, and the clue list are all laid out server-side so that the words interlock on matching letters. This is the one deliberate difference from the Creator, where you drag the words around the grid yourself: a build configuration cannot know which cells are still free, and a crossword whose words do not interlock is not a crossword. The layout is deterministic, so the same word list always produces the same puzzle.

Note: Interlocking is a requirement of the build, not a best effort. A word that does not fit into the grid, and a word that fits but shares no letter with the others and would end up lying beside the puzzle rather than crossing into it, both fail the build with an error naming that word - so a successful build always gives you one connected puzzle, never a crossword for some of the words plus a loose word list for the rest. If you hit it, raise gridSize to give the layout more room - or leave it out entirely, which offers the layout the largest grid there is - or replace the word that shares no letters with the others.

Note: The grid size is generated too, not just the layout inside it. gridSize is a ceiling on the room the layout may use: once the words interlock, they are laid out again in the smallest grid they still interlock in, so a puzzle is never stored inside a border of empty cells - which the player would see as a grid far bigger than the crossword in it. A three-word puzzle asking for "gridSize": 15 therefore comes back at 6x6, and reading the Riddle back gives you that 6, not the 15 you sent. Two consequences worth knowing: asking for a bigger grid is not a way to space a puzzle out, and leaving gridSize out is the normal thing to do - the words are then fitted automatically instead of you having to guess a size that takes them.

Note: Because the whole puzzle is re-generated from the word list, words is the one collection that does not merge by id and cannot be reordered - an update that sends words replaces the puzzle wholesale, so always send the complete list you want, not just the word you are changing. For the same reason "$create": true and "$delete": true are rejected on a word entry: with no merge to apply them to, they would leave the puzzle consisting of that one marked word.

Example

{
    "title": "Capitals crossword",
    "description": "Fill in the grid!",
    "type": "Crosswords",
    "gridSize": 9,
    "score": 10,
    "successMessage": "Well done - you solved it!",
    "words": [
        { "text": "PARIS", "clue": "Capital of France", "direction": "across" },
        { "text": "ROME", "clue": "Capital of Italy" },
        { "text": "OSLO", "clue": "Capital of Norway" }
    ]
}

Result page

In a minigame only one result page is allowed which is specified in build.result. Basic results have a title and description property:

{
    "title": "Thank you!",
    "description": "Thanks for playing"
}

If you want to create complex result pages with texts, images, ... click here to learn how to build advanced result pages.

Full example

Example with all three minigame blocks + options:

{
    "type": "Minigame",
    "build": {
        "title": "Minigame example (Builder API)",
        "blocks": [
            {
                "title": "Spin the slot machine",
                "description": "Try your luck!",
                "type": "SlotMachine",
                "media": "https://httpbin.io/image/jpeg",
                "startBalance": 1000,
                "winningProbability": "High",
                "winTitle": "Jackpot!",
                "winDescription": "You won a 20% voucher.",
                "winMedia": "https://httpbin.io/image/png",
                "customSymbols": [
                    {
                        "symbolKey": ":cherries:",
                        "media": "https://httpbin.io/image/webp"
                    },
                    {
                        "symbolKey": ":bell:",
                        "media": "https://httpbin.io/image/svg"
                    }
                ]
            },
            {
                "title": "Spin the wheel",
                "description": "Try your luck!",
                "type": "WheelSpinner",
                "isCopyToClipboardButtonEnabled": true,
                "areEmojisEnabled": false,
                "isMediaVisible": false,
                "items": [
                    {
                        "title": "Win 100$",
                        "type": "Win",
                        "percent": 50,
                        "award": "100$",
                        "backgroundColor": "rgba(89, 225, 171, 1)",
                        "textColor": "rgba(0, 0, 0, 1)"
                    },
                    {
                        "title": "Lose 50$",
                        "type": "Loss",
                        "percent": 30,
                        "backgroundColor": "rgba(0, 0, 0, 1)",
                        "textColor": "rgba(255, 255, 255, 1)"
                    },
                    {
                        "title": "Free spin",
                        "type": "FreeSpin",
                        "percent": 20
                    }
                ]
            },
            {
                "title": "Sudoku Challenge",
                "description": "Solve the puzzle!",
                "type": "Sudoku",
                "difficulty": 70,
                "areRulesVisible": true,
                "isConflictHighlightingAllowed": true,
                "isGuessCheckingAllowed": true,
                "refreshInterval": "Weekly",
                "score": 5,
                "successMessage": "Well done - you solved it!"
            },
            {
                "title": "Clear the minefield",
                "description": "Avoid the mines!",
                "type": "Minesweeper",
                "rows": 12,
                "cols": 12,
                "mines": 18,
                "gameMode": "Normal"
            },
            {
                "title": "Capitals crossword",
                "type": "Crosswords",
                "gridSize": 9,
                "score": 10,
                "successMessage": "Well done - you solved it!",
                "words": [
                    { "text": "PARIS", "clue": "Capital of France", "direction": "across" },
                    { "text": "ROME", "clue": "Capital of Italy" },
                    { "text": "OSLO", "clue": "Capital of Norway" }
                ]
            },
            {
                "title": "Where should we send your prize?",
                "type": "FormBuilder",
                "fields": [
                    { "title": "Your name", "type": "Name" },
                    {
                        "title": "Your email",
                        "type": "Email",
                        "isRequired": true,
                        "requiredMessage": "We need your email to send you the prize."
                    }
                ]
            }
        ],
        "result": {
            "title": "Thanks for playing!",
            "description": "We hope you had fun."
        }
    }
}

Next steps

Now that you know the basics of building a minigame, you might want to learn how to: