Getting started

A question bank is a reusable pool of questions. Instead of putting the questions into a Riddle, you keep them in a bank and let a Riddle draw from it – so the same questions can feed many Riddles, and updating the bank updates every Riddle using it.

Every bank belongs to

  • exactly one project (or your personal space), and
  • exactly one Riddle type: Quiz or Poll.

The Riddle type cannot be changed afterwards and a bank can only be used by Riddles of that type.

Not familiar with the API yet? Read the Getting started guide first to learn about authentication and the response format.

Draft and published state

A bank has two states, exactly like a Riddle:

  • Everything you write via the API – new items, changed items, deleted items – lands in the draft state first.
  • Publishing copies the draft over the published state.

A Riddle only ever draws from the published state of a bank. A bank that was never published contains no questions as far as your Riddles are concerned, so remember to publish after filling a bank.

Create a bank

To create a bank, use the /question-bank endpoint:

PropertyRequiredTypeDescription
riddleTypeyesstringQuiz or Poll - cannot be changed later
titlestring|nullThe title of the bank; defaults to "New question bank"
projectinteger|nullThe project to create the bank in; pass NULL for your personal space. If the key is omitted, the project of the API key is used
{
    "riddleType": "Quiz",
    "title": "History questions"
}

The response contains the new bank, including the id you need for every other call:

{
    "success": true,
    "code": 200,
    "data": {
        "id": 4711,
        "riddleType": "Quiz",
        "title": "History questions",
        "user": "abc123",
        "team": null,
        "notes": null,
        "tags": [],
        "modifiedAt": "2026-08-06 10:14:22",
        "createdAt": "2026-08-06 10:14:22",
        "publishedAt": null,
        "itemCount": 0,
        "draftItemCount": 0,
        "riddleDependencies": []
    }
}
PropertyDescription
itemCountThe number of published items - i.e. the number of questions your Riddles can actually draw from
draftItemCountThe number of items in the draft state, including unpublished additions
publishedAtnull until the bank was published for the first time
riddleDependenciesThe Riddles that currently use this bank, as {"UUID": ..., "title": ...}
tagsThe tags of the bank, as {"id": ..., "name": ...}

List your banks

To list the banks of a project, use the /question-bank/list endpoint. All parameters are optional query parameters:

PropertyTypeDescription
riddleTypestringOnly return banks of this type: Quiz or Poll
searchstringA search term matched against the bank title
tagsstringA JSON encoded array of tag IDs, e.g. [123,456] - only banks carrying these tags are returned
sortBystringcreatedAt (default) or modifiedAt
sortOrderstringASC or DESC (default)
pageintegerThe page to fetch (default 1)
pageSizeintegerHow many banks per page (default 12, maximum 50)
projectinteger|nullThe project to list the banks of; pass an empty value for your personal ones. If the parameter is omitted, the project of the API key is used
GET /question-bank/list?riddleType=Quiz&search=history&pageSize=50

The response is a list response, i.e. the data object holds the count of returned banks and the banks themselves in items:

{
    "success": true,
    "code": 200,
    "data": {
        "count": 1,
        "items": ["... the banks ..."]
    }
}

Banks in this list carry a few additional properties on top of the shape above:

PropertyDescription
hasChangestrue when the draft state differs from the published one, i.e. the bank has to be published again
isPublicTemplateWhether this bank is a template
categoriesEvery category used by the bank's items
blockTypeCategoryMapWhich categories exist per block type, e.g. {"SingleChoice": ["History", "Sports"]}

Get a single bank

/question-bank/{questionBank} returns one bank with the same properties as the list above.

Note: A bank that is not yours is answered exactly like one that does not exist - a 404 with Question bank not found. - so that bank IDs cannot be walked to find out which ones exist. The only exception is a write to a public template, which is answered with an explicit access error instead: templates are listed to everybody, so their existence is no secret.

Rename a bank

/question-bank/{questionBank}/rename (PUT) expects the new title (required, at most 255 characters):

{
    "title": "History questions 2026"
}

Set the notes of a bank

Every bank can hold a free-form note, e.g. to describe where its questions come from. /question-bank/{questionBank}/notes (PUT) expects the complete notes string – it replaces the previous one:

{
    "notes": "Sourced from our 2026 history course. Ask marketing before changing."
}

Duplicate a bank

/question-bank/{questionBank}/duplicate copies a bank and all of its items:

PropertyRequiredTypeDescription
titleyesstringThe title of the copy
projectinteger|nullThe project the copy should land in; pass NULL for your personal space. If the key is omitted, the project of the API key is used

This is also how you start from a template.

Publish a bank

/question-bank/{questionBank}/publish copies the draft state of every item over its published state. No request body is needed.

Only after this do new or changed questions reach the Riddles that use the bank.

Discard your changes

/question-bank/{questionBank}/discard-changes resets every item back to its published state. Items that were never published are removed. No request body is needed.

Delete a bank

/question-bank/{questionBank} (DELETE) deletes a bank and all of its items.

Note: A bank that any Riddle still references is not deleted. The request is rejected with 400 and the error code QUESTION_BANK_INTERDEPENDENCY, message Cannot delete Question Bank with existing Riddle dependencies.. Check riddleDependencies first, or remove the QuestionBank block from those Riddles. A Riddle counts as soon as its build references the bank, even in an unpublished draft, not only once it is published.

Use a bank in a Riddle

A bank is drawn from by a QuestionBank block in a build configuration. The block names the bank via questionBankId and describes which questions to draw – per block type, category and difficulty range:

{
    "blocks": [
        {
            "type": "QuestionBank",
            "questionBankId": 4711,
            "questionBankBlocks": [
                {
                    "blockType": "SingleChoice",
                    "isEnabled": true,
                    "questionBankCriteria": [
                        {
                            "category": "History",
                            "difficultyRange": [3, 7],
                            "maxNumberOfQuestions": 5
                        }
                    ]
                }
            ]
        }
    ]
}

See the Quiz and Poll block reference for every property of the block.

Next steps