[{"data":1,"prerenderedAt":543},["ShallowReactive",2],{"search-api":3},[4,18,31,47,58,66,78,90,104,112,135,151,158,170,179,188,199,209,218,228,238,260,280,313,329,341,352,364,374,384,394,404,416,425,439,451,460,467,474,485,504,518,527,537],{"id":5,"path":6,"dir":7,"title":8,"description":7,"keywords":9,"body":17},"content:15.Api:0.index.md","/api","","Getting started",[10,11,12,13,14,15,16],"Introduction","Specification","Authentication","Response format","Exception handling","Rate limiting","Next steps","  Getting started  Introduction  The Riddle API can be used to dynamically list, embed + analyze + create Riddle content.  Example API usages:   Get all Riddles by type / name / tag  Get embed code for a Riddle  Analyze and view stats for Riddles, projects, or your personal project in a given time range  Build and edit Quizzes, Polls, Predictors, etc. via build configurations  Generate Riddles with AI based on topics or URLs  Maintain reusable question banks your Riddles draw their questions from  Specification  Looking for the API Endpoints?  You can find specification for all available API endpoints at   https://www.riddle.com/help/api/docs .  Authentication  To access the API you need an API key. You can   find or create new API keys on the API keys page  in the Riddle creator.\nOnce you have found or created an API key, you can use it to authenticate against the API.  Example Request:   URL: https://www.riddle.com/creator/api/v3/riddle/list\nHTTP method: POST\nHeaders:\n{\n    Authorization: \"Bearer [your API key]\"\n}\n  Example Request via CURL:     curl --location --request POST 'https://www.riddle.com/creator/api/v3/riddle/list' \\\n   --header 'Authorization: Bearer [your API key]'\n  Response format  In case no exception occurs and the API returns HTTP 200 the response will have the following format:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  :   \"[response data]\"\n   }\n  The type of   data  in the response can vary depending on the used endpoint. E.g. while the embed code endpoint returns a string (=> the actual embed code), the riddle list will return an array consisting of all riddles matching the given query.  Make sure to check out the API documentation to see example requests and responses for each endpoint.  Exception handling  In case an exception occurs the response will have a different structure:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"BAD_REQUEST\"  ,\n       \"message\"  :   \"Bad Request.\"\n   }\n  Let's go through each sent parameter:    code : The HTTP response code; Check out   https://http.cat  to explore various codes.   error : An unique error code which is easier to work with when working with this API programmatically.   message : An error message which includes more information why what happened. In some cases additional information is redacted to not expose any security-risking information. If that is the case and you want to know more please contact us in the support chat.  Validation errors  The API can also return validation errors to further describe where a mistake has been made.  For example in the builder API you could mistakenly supply an   integer  for a quiz question title of type   string  - this results in a validation error and the structure of the returned response would look like this:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION\"  ,\n       \"message\"  :   \"SingleChoice: Block properties are invalid. See the validation errors for more details.\"  ,\n       \"validationErrors\"  : [\n           {\n               \"message\"  :   \"Input is not a string.\"  ,\n               \"code\"  :   \"NOT_STRING\"  ,\n               \"property\"  :   \"title\"\n           }\n       ]\n   }\n  Rate limiting  By default the Riddle API is rate limited to 100 requests per minute, 2000 requests per hour.  Note that this is a   shared rate limit across all API keys of your Riddle account  (even if within different projects). If you exceed this limit you will receive HTTP 429 responses until the rate limit window resets.  Example response:     {\n       \"success\"  :   false  ,\n       \"code\"  :   429  ,\n       \"error\"  :   \"API_RATE_LIMIT_EXCEEDED\"  ,\n       \"message\"  :   \"Minutely API rate limit of 100 requests exceeded\"\n   }\n  If your use case requires more requests per minute/hour please contact us via the support chat or   via email .  Next steps     Look at the specification of all available API endpoints : Find out what you can do with the Riddle API.    Manage Riddles : List, publish, embed, tag, and delete your Riddles – and fetch their leads.    Stats API : Use the Riddle Stats API to retrieve stats for any of your Riddles, projects, or for your personal project.    Builder API : Use the Riddle Builder API to create and edit Riddles programmatically with defined build configurations.    Generative AI API : Use the Riddle Generative AI API to create Riddles programmatically based on topics and URLs.    Question Banks : Keep your questions in a reusable pool and let many Riddles draw from it.   Use the PHP Library:  If you use PHP in your project you can use our   PHP SDK  to integrate the Riddle API. This has the advantage that you don't have to worry about authentication or other boiler plate code and can focus on building your Riddle integration.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":19,"path":20,"dir":21,"title":22,"description":23,"keywords":24,"body":30},"content:15.Api:1.MCP.md","/api/mcp","api","MCP","The Model Context Protocol (MCP) is a standard that lets AI models and agents call external tools and APIs. Riddle's MCP exposes our API to AI agents, so any action you can do via the API – such as listing, building, editing, and analyzing Riddles – can be triggered from an AI chat.",[25,26,27,28,29,16],"How to use","Available Tools, Resources & Prompts","Keeping the context small","Response Format","Troubleshooting","  MCP  The   M odel   C ontext   P rotocol (MCP) is a standard that lets AI models and agents call external tools and APIs. Riddle's MCP exposes our API to AI agents, so any action you can do via the API – such as listing, building, editing, and analyzing Riddles – can be triggered from an AI chat.  How to use  When using the Riddle MCP, you have two options for authentication:    Preferred:  Via public MCP URL in Claude (using the   CIMD  (Client ID Metadata Document) protocol)  Via MCP key embedded in the URL  Via public MCP URL in Claude   To add the Riddle MCP to your Claude   account , navigate to Settings > Connectors > Add custom connector.  To add the Riddle MCP to your Claude   organization , navigate to Organization settings > Connectors > Add > Custom > Web connector.  In both cases the following dialogue will show:\n   Enter the following:   Name: Riddle MCP  URL:   https://www.riddle.com/creator/api/v3/mcp  After clicking on   add , you are almost ready to use the MCP in your Claude chats: Click on   connect  afterwards to link your Riddle account with Claude and if necessary, you'll have to log in. Once you're done with this, you can try asking Claude to list the latest, published Riddles from your account to test the connection. You can also use the   whoami  tool to verify your account and project access.  Via MCP key  If you wish to use the MCP with an MCP key, create one on the   API keys page  (see the   Authentication guide  for details). Please make sure to pick a   MCP key  – regular API keys will not work and will return an error. Personal MCP keys are best suited: they give you access both to your personal project and to all projects in which you have the   corresponding AI permissions . If you can only create normal API keys, your user role is missing the required permissions – ask a project administrator to grant them or to issue an MCP key for you.   Once you have your key, append it to the MCP URL as a path segment:    https://www.riddle.com/creator/api/v3/mcp/[MCP_KEY]  Replace   [MCP_KEY]  with your actual key, then add this URL as a custom connector in Claude (same steps as above).   Please note  that accessing the MCP via a configured MCP key is inferior to the CIMD option. It requires you to embed your key in the URL, and it is less flexible: you need to create a new MCP key for every Riddle account you want to access. With CIMD, each user authorizes with their own Riddle account instead, so no account has to be pre-configured in the URL.  Available Tools, Resources & Prompts   Note:  You can use standard MCP functionality to list tools and resources available to the model; this will include more verbose information, e.g. API parameters. Below is a short summary, but make sure to fetch the MCP's current capabilities to get the most up-to-date information.  Tools (62)  The 62 tools fall into nine categories:     Category  Tools     Utility & Account  2    Documentation  1    Projects  3    Riddle management  14    Builder API  11    Templates  5    Question banks  19    Design & palettes  2    Statistics  5  Utility & Account (2)  Test connectivity and check the context of your API key.     Tool  Description     ping  Connectivity and authentication test – simply returns \"Pong\".    whoami  Returns information about the current API key: the authenticated user (ID, email, name) and the linked project/team, if any. Useful to verify authentication and retrieve your user ID or project ID.  Documentation (1)     Tool  Description     reference_get  Reads the documentation of the MCP server itself: the block types, form field types, result blocks, palette values and response shapes the other tools expect. Every   riddle://reference/...  URI mentioned in a tool description, a tool response or an error message is a topic of this tool. These documents are the authoritative parameter reference for the   riddle_builder_*  and   palette_*  tools - a client that cannot read MCP resources can read them through this tool instead. They are long - up to ~13.6k tokens each - so at most 4 topics are returned per call; see   their sizes .  Projects (3)  List projects and fetch project details.     Tool  Description     project_list  Paginated list of the projects this token has access to (25 per page, 100 max), with a   pagination  object to page through accounts with many projects. If it is a project API token, only the project linked to the token will be returned. Returns a trimmed summary (id, name, image) per project.    project_get  Fetches a single project by its project ID.    project_get_settings  Returns the default Riddle settings of a project - the settings every new Riddle in it starts from, as   defaultRiddleSettings  (the draft the project owner edits) and   publishedDefaultRiddleSettings  (what Riddles actually inherit). A large, deeply nested payload - use project_get for a project's name, image and permissions.  Riddle management (14)  Find, read, and manage existing Riddles.     Tool  Description     riddle_list  Paginated list of Riddles from a single project – filterable by type, status, tags, origin (API created vs. created by hand), and search term; sortable. For Riddles across all projects, use riddle_account_list instead.    riddle_account_list  Paginated list of Riddles across the entire account – the personal project plus all team projects the user has access to.    riddle_get  Fetches a single Riddle by its UUID as a build configuration:   {uuid, type, modifiedAt, build, nextBlockId, warnings, published, context} .   build  is the same builder config the builder tools accept, so a Riddle can be read, edited and rebuilt; anything it cannot express is reported in   warnings .   nextBlockId  is the block ID a new block may claim in an edit.   published  describes the live version -   null  when never published,   {\"status\": \"identical\"}  when the live Riddle is exactly what   build  describes, and   {\"status\": \"differs\", \"build\": ..., \"warnings\": ...}  (spelled out in full) when there are unpublished changes. Unpublishing does   not  clear it back to   null : the last published content stays stored, so   published  being non-null means \"has been published at least once\", not \"is live right now\" -   context.unpublished  answers the latter.   context  adds title, features, origin, published state, the Riddle this one was copied from (  duplicated ), project and preset information. Reads several Riddles in one call with   UUIDs , and   omit  leaves parts of the response out – the only way to make it smaller.    riddle_rename  Renames a Riddle (new title by UUID).    riddle_publish  Publishes one Riddle (  UUID ) or up to 100 at once (  UUIDs ) – each becomes available via its public URL. For a single Riddle the answer is the same envelope riddle_get returns, with the new state under   context.published , and   omit  shrinks it exactly as it does there; for many it is the bulk envelope   {bulk, operation, summary, results}  with one entry per Riddle. A bulk publish is not atomic and never gives up early: a Riddle that cannot be published is reported as that entry's   error  while all others are still published.    riddle_unpublish  Takes one Riddle or up to 100 offline – the public URL is no longer reachable. A Leaderboard with active connections cannot be unpublished; use riddle_delete on it instead, which is always allowed and cleans the connections up. Same single/bulk response shapes and the same   omit  support as riddle_publish.    riddle_delete  Deletes one Riddle (  UUID ) or up to 100 at once (  UUIDs ). Only Riddles created via the builder, created from a template with riddleTemplate_use, or generated by the Riddle AI can be deleted –   context.origin.apiManageable  on riddle_get tells you upfront whether a Riddle qualifies. A bulk delete is not atomic and never gives up early.   Order does not matter:  a Riddle that another item of the same batch still references (a Leaderboard's connected Quiz, a FormSelect's Form) is retried once automatically after the rest of the batch has run, so only a failure that survives the retry is reported as an error.    riddle_get_embed_code  Returns the HTML embed code of a published Riddle.    riddle_qr_code  Generates a QR code (base64-encoded SVG) for a published Riddle.    riddle_move  Moves up to 100 Riddles into another project (or into the personal project). All-or-nothing: Riddles that reference each other - a Quiz and its Leaderboard, an embedded Form - have to move together, and the error names the ones to add. Needs the transfer permission in both projects. Tags are re-pointed to the destination scope; a tag left behind in the source scope is removed once nothing - no Riddle, no question bank - uses it there any more. The Riddle keeps its own design: a move does not switch it to the destination project's default preset.    riddle_move_check  The same check without moving anything: which Riddles are movable, which are blocked and by what, the UUIDs to add, and the projects the whole set could go to.    riddle_tag_list  The tags of a project with their usage count (  {id, name, count} ) - tags are per project.   count  only counts Riddles: a tag shared with a question bank can show   count: 0  and still be in use there. Gives you the tag IDs the riddle_list filters accept.    riddle_tag_add  Adds a tag to one Riddle or up to 100 at once, by tag name (created if the project does not have it yet) or tag ID.    riddle_tag_remove  Removes a tag from one Riddle or up to 100 at once. The tag itself is only deleted from the project once nothing - no Riddle, no question bank - uses it any more.  Builder API (11)  Create and edit Riddles with structured parameters (blocks, results, logic, presets, publish settings).     Tool  Description     riddle_builder_quiz  Builds a Quiz – question blocks (SingleChoice/MultipleChoice/TextEntry/Order/Flashcard/TypeRush/GuessIt), results with percentage ranges, optional branching logic and leaderboard connection.    riddle_builder_poll  Builds a Poll – block types include SingleChoice, Matrix, Order, Upvote, NPS, RateIt, Swiper, Reaction, TextEntry, and TierList; optional branching logic.    riddle_builder_form  Builds a Form – FormBuilder blocks with field mapping (e.g. Email, Name); result page with dynamic variables such as %fieldname.    riddle_builder_personality  Builds a Personality quiz – questions with score arrays per answer, at least 2 personalities with title/description/media.    riddle_builder_predictor  Builds a Predictor – blocks of type PickTheWinner or GuessTheScore, optional leaderboard connection.    riddle_builder_minigame  Builds a Minigame – SlotMachine, WheelSpinner (win/loss/free spin with percentages), or Sudoku.    riddle_builder_leaderboard  Builds a Leaderboard – connects up to 10 Quizzes, Predictors, or Minigames (Name and Email fields required); optional email validation.    riddle_builder_story  Builds a Story – general content blocks (Content/Ad/Quote), the InteractiveGraphic block and form fields, one optional result page, no questions or scoring; optional linear-only branching logic.    riddle_builder_placeholder  Builds a   Placeholder  – a Riddle with no content of its own, only a routing rule saying which other Riddle (or which Riddle carrying a given tag) is shown in its place. Needs the Placeholder feature. The rule is stored, not evaluated here, and comes back re-sorted and window-trimmed rather than verbatim.    riddle_builder_update  Edits an existing Riddle of any type as a   merge , not a rebuild: only what you send changes. Blocks are addressed by their ID and can be added (  \"$create\": true ), removed (  \"$delete\": true ) or reordered (  blocksOrder );   title ,   result /  results ,   logic ,   preset ,   publishSettings , a Personality Test's   personalities , a Leaderboard's   riddleConnections  and a Placeholder's   conditions  are replaced as a whole when sent and kept when omitted. Only Riddles created with the builder or generated by the Riddle AI can be edited - check   context.origin.apiManageable  from riddle_get first, which is also where the block IDs are. Returns the edited Riddle in the same envelope riddle_get returns. See   Editing Riddles .    riddle_builder_validate    Dry-runs  creates and/or edits – 1 to 20 per call, mixed freely – without creating or changing anything: each entry of   builds  is validated exactly as the real call would validate it, against a scratch Riddle that is discarded before the answer. Nothing is persisted, published or queued. Media URLs   are  still checked for reachability with a live request (the file is never downloaded), so an unreachable URL is rejected here too. The answer is   {valid, summary, items}  with one entry per item, in the order sent, each carrying either the   build  it would end up with or the   errors  it would be rejected with – one item's outcome never affects another's. Needed plan: Business or Enterprise. See   Validating build configurations .  Templates (5)  Reuse a Riddle as the starting point for new ones – your project's own templates and Riddle's public ones. A template is a copy taken at one moment: the Riddle it was made from keeps living its own life.     Tool  Description     riddleTemplate_create  Stores an existing Riddle as a template of its project (or of you, for a personal Riddle), so new Riddles can be created from it. It copies what the Riddle currently has stored, published or not; later changes to the Riddle do not reach the template. Requires the template-create permission.    riddleTemplate_list  The templates of a project (or your personal ones) – the ones   your  Riddles were made into, not Riddle's public ones. Filterable by Riddle type. Returned without the build configuration.    riddleTemplate_publicList  Riddle's public, ready-made templates, grouped by category – so calling it without arguments is also how you learn which categories exist. Also filterable by type. An unknown   category  is rejected with an error naming the categories that are actually allowed, rather than silently returning nothing.    riddleTemplate_get  A single template   including its build configuration  – the same   build  shape riddle_get returns and the builder tools accept. This is how a template is   adapted  rather than copied: edit the returned   build  and build it with the   riddle_builder_\u003Ctype>  tool of the template's type, passing the template's id as   templateId  so the new Riddle is still recorded as coming from it (and starts out on the template's whole preset, layout included). A template whose content has no build-configuration equivalent comes back with an empty   build  and a warning saying so.    riddleTemplate_use  Creates a new Riddle from a template as an   unchanged copy  – content, settings and design preset – in one call, and records the lineage: reading it back reports the template's Riddle under   context.duplicated . The new Riddle is a draft, so call riddle_publish to make it live, and it counts as programmatically created, so riddle_builder_update, palette_customize and riddle_delete work on it (  context.origin.apiManageable ). Requires the template-use permission plus Riddle-create permission in the target project.  Question banks (19)  Manage the reusable question pools a   QuestionBank  block of a Quiz or Poll draws from. A bank belongs to one project and to one Riddle type, and its items have a draft/published split of their own: a   QuestionBank  block always draws from a bank's   published  state, so a bank has to be published before its questions show up in a Riddle. See   Question banks .     Tool  Description     questionBank_create  Creates a new, empty bank for a Riddle type (  Quiz  or   Poll ) in a project. Its   id  is what a   QuestionBank  block references as   questionBankId .    questionBank_list  Paginated list of the banks of a project (12 per page, 50 max), filterable by search term and tags.    questionBank_templateList  The built-in template banks anyone can duplicate to start with real content. A template that was never published reports   itemCount: 0  – judge its real size by   draftItemCount .    questionBank_get  A single bank: title,   riddleType , tags, notes, categories/blockTypes and whether it has unpublished changes. Works on a template id too.    questionBank_getItems  The items (draft content) of a bank, filterable by search term, blockType, category or difficulty range. Returns everything unless you page it – unlike questionBank_list.    questionBank_rename  Renames a bank. Title and notes are metadata outside the draft/publish split, so this takes effect immediately.    questionBank_updateNotes  Replaces the bank's internal plain-text notes – for its maintainers, never shown to participants.    questionBank_duplicate  Copies a bank (or a template) with all of its items into a new, independent bank, optionally in another project.    questionBank_publish  Makes every item's draft content its published content – what a   QuestionBank  block actually draws. Also the moment a pending delete of a published item is purged for good.    questionBank_discardChanges  Resets every item back to its last published state, undoing pending deletes as well. Irreversible.    questionBank_delete  Deletes a bank and all of its items. A   QuestionBank  block still referencing the id afterwards simply draws nothing.    questionBank_addItem  Adds one question to a bank's draft. Call questionBank_blockTypeColumns first – there is no universal item shape.    questionBank_updateItem  Replaces an item's content entirely (blockType, category, difficulty and all columns).   blockType  is immutable.    questionBank_deleteItem  Deletes one item. A never-published item is gone immediately; a published one keeps being drawn live until the next questionBank_publish.    questionBank_blockTypeColumns  Every blockType valid for a bank of a given Riddle type, with the exact   columns  shape addItem/updateItem expects for it – a Quiz   SingleChoice  and a Poll   SingleChoice  differ.    questionBank_tagList  The bank tags of a project with usage counts – the tag IDs questionBank_list filters by. Separate from Riddle tags.    questionBank_addTag  Tags a bank by tag name (created if new) or tag ID.    questionBank_removeTag  Removes a tag from a bank; a tag no bank uses any more is deleted from the project.    questionBank_riddleBlockItems  Previews which items a   QuestionBank  block of an existing Riddle would draw right now – criteria matching too little inventory are only a pre-publish warning, so this is how to catch it.  Design & palettes (2)  Read and change the design (colors, fonts, buttons, background) of a Riddle.     Tool  Description     palette_get  Reads the palettes of a Riddle: every palette it can use (including the ones inherited from the account or project default preset) with all values, which palette is selected, which values this Riddle overrides, and the built-in palettes that can be used as a starting point.    palette_customize  Changes the palette of a   single  Riddle via a path ⇒ value map, e.g.   {\"bgColor\": \"#ffffff\", \"font.name\": \"Roboto\"} . An inherited palette is never changed for other Riddles - the values are stored as an override on this Riddle, and built-in palettes are duplicated into a Riddle-owned copy automatically. A palette change does not update the Riddle's   modifiedAt , matching the Riddle Creator, which does not stamp   modifiedAt  for a design change either. The new design is only visible on the embedded Riddle after publishing it again. Like riddle_delete, this only works on Riddles created via the builder or generated by the Riddle AI.  Statistics (5)  Views, starts, and submissions on user, project, and Riddle level.     Tool  Description     stats_fetch  Aggregated stats (views, starts, submissions) for a single period – namespace: project, user, or riddle; omit the dates for all-time stats.    stats_overview_fetch  Stats in daily intervals for a given date range – ideal for dashboards, graphs, and trend analysis.    stats_riddle_breakdown  Detailed breakdown for a specific Riddle – titles, answer choices, views, time spent, and submissions.    stats_project_breakdown  Stats breakdown for a specific project.    stats_user_breakdown  Stats breakdown for the authenticated user across all accessible projects – requires a user API key (will fail with project API keys).  Resources (11)     Resource  URI  Size  Description     getting-started   riddle://reference/getting-started  19 KB / ~4.9k tokens  Overview of the Riddle MCP server: available tool categories, common workflows, and authentication model.    response-format   riddle://reference/response-format  11 KB / ~2.9k tokens  The response envelope every tool answers with, and how errors are reported.    riddle-types   riddle://reference/riddle-builder/riddle-types  40 KB / ~10.3k tokens  All 7 Riddle types with their required/optional build fields, result structure, and documentation links.    block-types   riddle://reference/riddle-builder/block-types  42 KB / ~10.7k tokens  Question and content block types per Riddle type with required properties and item formats.    block-defaults   riddle://reference/riddle-builder/block-defaults  53 KB / ~13.6k tokens  The default value of every property a read-back omits for still being at it, per Riddle type and block type - what   riddle_get  states inline per block in   omittedDefaults , but without needing a Riddle.    form-field-types   riddle://reference/riddle-builder/form-field-types  7 KB / ~1.9k tokens  All 18 form field types for the FormBuilder block with their properties and configuration options.    result-blocks   riddle://reference/riddle-builder/result-blocks  12 KB / ~3.1k tokens  All 12 result page block types with their properties, format options, and styling configuration.    question-bank-overview   riddle://reference/question-bank/overview  10 KB / ~2.6k tokens  How question banks work: the bank/item model, the draft-and-publish split, the per-Riddle-type block types and item columns, and how a bank is referenced from a   QuestionBank  block.    palette-fields   riddle://reference/palette/fields  13 KB / ~3.3k tokens  Every palette path that palette_customize accepts and what each value does.    palette-built-in   riddle://reference/palette/built-in-palettes  23 KB / ~5.9k tokens  The built-in palettes (  default:* ) that can be used as a starting point.    palette-fonts   riddle://reference/palette/fonts  6 KB / ~1.4k tokens  All font families that can be used in a palette.  These documents are large - read them selectively  The sizes above are the whole set:   237 KB, roughly 61k tokens , which is a substantial part of a model's context window before a single Riddle has been built. They are written to be read by an agent, not loaded wholesale.    Never fetch them all.    reference_get  therefore accepts at most   4 topics per call  and rejects a longer list rather than returning a huge response - ask for the ones the current step needs and call again later for the rest.   The four builder documents are the expensive ones.    riddle-types ,   block-types  and   block-defaults  are ~10-14k tokens each.   riddle-types  +   block-types  is the usual pair before building; add   form-field-types  only for a Riddle with a form,   result-blocks  only when you style a result page, and   block-defaults  only when you need a default value without a Riddle in hand.   Let the server slice them.    reference_get  takes   riddleType ,   blockTypes  and   fieldTypes : asking for   block-types  with   riddleType: [\"Quiz\"]  drops every other type's blocks before the document is sent, while the shared conventions are always kept. Filtering here is far cheaper than receiving all 7 Riddle types and ignoring 6 of them.   Prefer the cheaper source when there is one.  For defaults of a block you have already built,   riddle_get 's per-block   omittedDefaults  costs a fraction of the 13.6k-token   block-defaults  document. For palettes,   palette_get  returns the Riddle's actual values, so   palette-fields  is only needed to look up a path you want to write.   Fetch once per session.  Their content only changes when the server is updated, so re-reading the same document in the same conversation is pure token cost - the exception is a   VALIDATION_ERROR , where re-reading the relevant document is exactly the right move.  Guided workflows (12)  The MCP server also ships   prompts : ready-made workflows that chain the tools above in the right order and ask you for the few things they cannot know (brand colors, the URL, which project). Pick one in your MCP client instead of describing the whole job yourself.     Prompt  What it does     build_LeadGenQuiz  A lead-generation Quiz: entertaining questions, a form block that collects contact data before the result, optional double opt-in, published and ready to embed.    build_LeadForm  A standalone lead form (newsletter, registration, contact): the right field types, GDPR consent, double opt-in and a confirmation email.    build_ProductRecommender  A \"which one fits me\" product or plan recommender as a Personality test - each product is a personality, every result links to its page.    build_GatedContentStory  A gated content Story: teaser sequence, form gate in the middle, the asset behind it.    build_PredictorWithLeaderboard  A prediction game with a public ranking: a Predictor for the picks, a connected Leaderboard, and the scoring rules.    build_QuizContestWithLeaderboard  A quiz contest (e.g. a daily quiz) with a ranked Leaderboard: timed and scored questions, one entry per participant, a live ranking.    restyle_ToBrand  Restyles a Riddle to brand colors and fonts and publishes so the change reaches the embed.    organize_Library  Cleans up the library: find Riddles by filter, tag them, publish or unpublish the set, move them once the move is verified as possible.    localize_Riddle  Localizes a Riddle: read it as a build configuration, create the translated counterpart with the language set, keep the two in sync.    setup_DataLayerTracking  Instruments a Riddle for analytics: tracking networks, which events they fire, dataLayer pushes, publish.    analyze_CampaignPerformance  Reports on a campaign: collect its Riddles, pull views/starts/submissions plus the daily trend, turn it into a funnel and next steps.    optimize_Riddle  Optimizes a Riddle against its own stats: find the drop-offs, propose fixes, apply them as a merge edit and publish.  Builder capabilities  The   riddle_builder_*  tools do more than their short descriptions suggest. Beyond the required   title  and   blocks , most builder tools accept optional parameters that unlock the same power available in the Creator:    Branching logic  (  logic ): Define a conditional flow over your blocks instead of a fixed linear order – route users to different blocks based on their answers, and merge paths back together. Supported by Quiz, Poll, and Form.   Design presets  (  preset ): Base the Riddle on an existing design/preset and override settings such as color palette, language, \"remember user\", and auto-open/auto-close dates. Supported by all types except Leaderboard.   Publish automation  (  publishSettings ): Configure what happens on publish – double opt-in (DOI), email automation, tracking (pixels, analytics), data layer items, showcase visibility, and third-party integrations. Supported by all types except Leaderboard.   Leaderboard connections  (  leaderboard  /   riddleConnections ): Attach a Quiz, Predictor, or Minigame to one or more leaderboards on creation, or create a Leaderboard that connects to existing Riddles (which must have Name and Email fields).   Publish & queue  (  publish ,   queue ): Publish the Riddle immediately after creation instead of leaving it as a draft, and/or process the creation asynchronously.   Project targeting  (  project ): Create the Riddle in a specific project, in your personal project, or in the currently selected project.   Reading Riddles back  (  riddle_get ): Every Riddle - not only the ones created via the API - can be read back as exactly this builder config, so an agent can inspect an existing Riddle, change a detail and rebuild it. What a builder config cannot express is listed in   warnings  instead of being silently dropped.   Editing Riddles  (  riddle_builder_update ): Change an existing Riddle instead of rebuilding it - blocks are addressed by their ID, only what you send changes, and blocks can be added, removed or reordered. Limited to Riddles created with the builder or generated by the Riddle AI (  context.origin.apiManageable ). See   Editing Riddles .   Routing instead of content  (  riddle_builder_placeholder ): Build a   Placeholder  - embed one Riddle and decide by rule, tag or time window which Riddle actually shows.   Questions from a bank  (  QuestionBank  block): Instead of authoring questions on the Riddle, let a Quiz or Poll draw them at view time from a   question bank  - filtered by category and difficulty, and optionally re-drawn on an interval. The bank itself is managed with the   questionBank_*  tools.   Restyling  (  palette_get  /   palette_customize ): Read the full design of a Riddle and change individual palette values without touching the design of any other Riddle.   Checking before building  (  riddle_builder_validate ): Dry-run up to 20 creates and/or edits in one call - the same validation, nothing created or changed - to find out whether a configuration would be accepted, and why not, before spending a real call on it. See   Validating build configurations .   Starting from a template  (  riddleTemplate_* ): Copy a template as-is with   riddleTemplate_use , or read it with   riddleTemplate_get  and build the edited configuration with the builder tool of its type, passing   templateId  so the new Riddle keeps the template's preset and its lineage.  Fetch the builder reference resources (  riddle://reference/riddle-builder/* ) or list the tools via standard MCP functionality to see the exact fields and formats for each of these.  Keeping the context small  An MCP conversation pays for every token it receives, and a few of these tools can answer with a   lot . These are the levers – they matter for you in a chat, and they matter much more for an agent that runs unattended over many calls.    Leave out what you will not read  (  omit ). Every tool that answers with a Riddle –   riddle_get , all   riddle_builder_*  tools,   riddle_publish ,   riddle_unpublish  – accepts   omit  to drop parts of the answer:   build ,   warnings ,   nextBlockId ,   published ,   context , and   build.omittedDefaults . That last one is the big one: the per-block default maps are   most of a read-back , so   omit: [\"build.omittedDefaults\"]  alone can shrink the response by an order of magnitude. Only fetching a title?   omit: [\"build\", \"published\", \"warnings\", \"nextBlockId\"] .   Scope the reference documents instead of loading them.  They are ~61k tokens in total. Ask   reference_get  for the one or two topics the current step needs, narrowed with   riddleType  /   blockTypes  /   fieldTypes , and read them   once  per conversation – see   the note above .   One call instead of a loop.    riddle_get ,   riddle_publish ,   riddle_unpublish ,   riddle_delete  and the tag tools take a list (  UUIDs , up to 100). One bulk call carries one envelope and one round of tool overhead rather than a hundred.   Edit instead of rebuilding.    riddle_builder_update  is a merge: to fix one question you send that one block, not the whole Riddle. Reading with   omit: [\"build.omittedDefaults\"]  and sending back the single block that changed is the cheapest edit loop there is.   Dry-run in batches.    riddle_builder_validate  checks up to 20 configurations in a single call. Twenty real builds that each fail cost twenty error responses – and twenty Riddles to clean up.   Filter at the source.    riddle_list ,   riddle_account_list ,   questionBank_list  and   questionBank_getItems  all take filters, a search term and a page size. Narrowing the query beats fetching a broad list and discarding most of it.   Pick the smaller tool for the question.    project_get  for a project's name and permissions, not   project_get_settings  (a deeply nested payload).   riddle_get 's per-block   omittedDefaults  for the defaults of a block you already have, not the 13.6k-token   block-defaults  document.   palette_get  for a Riddle's actual design, not the palette reference.   Start from a guided workflow.  The   prompts  already chain the tools in the right order, so the model does not have to discover the sequence – and rediscover it after a wrong turn.  Response Format  All responses from the MCP will adhere to the same schema   as specified in the API docs  for the corresponding endpoint.\nE.g. the   riddle_get  tool will return a response with the same schema as the   GET /riddle/{riddle_uuid}  API endpoint, including all details about the riddle content, design, etc.  Troubleshooting  If you encounter any issues while using the MCP, here are some common troubleshooting steps:    API authentication failed : Make sure you are using an   MCP key  (not a regular API key – re-create if in doubt) and that the URL contains the actual key in place of the   [MCP_KEY]  placeholder.   Missing API permissions : Check if your user role has the necessary AI permissions to access the desired projects and perform the intended actions. If you do not have permission to modify roles, ask your account administrators to grant you the required permissions.  ... Still not solved? Please reach out to our support team with details about the issue, either via our support chat or   via email , including any error messages received and the steps you have already taken to troubleshoot.  Next steps   Want to continue reading?  Read the following API sections to understand the MCP tools in more detail and see example requests and responses for each of them:     Look at the specification of all available API endpoints : Find out what you can do with the Riddle API.    Stats API : Use the Riddle Stats API to retrieve stats for any of your Riddles, projects, or for your personal project.    Builder API : Use the Riddle Builder API to create Riddles programmatically with defined build configurations.    Generative AI API : Use the Riddle Generative AI API to create Riddles programmatically based on topics and URLs.",{"id":32,"path":33,"dir":34,"title":35,"description":36,"keywords":37,"body":46},"content:15.Api:2.Manage Riddles:0.Getting started.md","/api/manage-riddles/getting-started","manage-riddles","Getting started - Manage Riddles","Learn how to list, publish, embed, and manage your Riddles via API",[38,39,40,41,42,43,44,45,16],"List your Riddles","Get a single Riddle","Rename a Riddle","Publish or unpublish a Riddle","Get the embed code","Get a QR code","Delete a Riddle","Projects","  Getting started  Besides building and generating Riddles, the API also covers the everyday management tasks: listing and searching your Riddles, reading a single Riddle, renaming, publishing and unpublishing, and retrieving the embed code or a QR code – for example to embed Riddles dynamically in your CMS.  Not familiar with the API yet? Read the   Getting started  guide first to learn about authentication and the response format.  List your Riddles  To get a list of the Riddles in a project, use the   /riddle/list  API endpoint. By default the project of the accessing API key is used; results are paginated with 12 Riddles per page.  You can use any combination of the following   optional  filters:     Property  Type  Description     project  integer  The ID of the project you want to list the Riddles from; if not sent, the project of the API key is used    type  string  Only return Riddles of this type, e.g.   Quiz  or   Poll ; omit to get all types    notType  string  Exclude Riddles of this type    tags  integer[]  An array of tag IDs the Riddles must be tagged with;   learn more about tags    status  string   published ,   modified , or   draft ; omit to get all statuses    search  string  Any search term    origin  string   api  (built via the Builder API or generated by the Riddle AI) or   manual  (created by hand in the Creator); omit to get both. Any other value is rejected with   Invalid filter origin: \"\u003Cvalue>\". Allowed: api, manual    sortBy  string   created ,   published , or   modified . Any other value is rejected with   Invalid sortBy: \u003Cvalue>. Allowed: created, modified, published    sortOrder  string   ASC  or   DESC . Any other value is rejected with   Invalid sortOrder: \u003Cvalue>. Allowed: ASC, DESC    page  integer  The page you want to fetch; if not sent, the first page is returned    pageSize  integer  How many Riddles to return per page (default 12, maximum 300)  Example: Fetch the most recently published quizzes matching \"onboarding\":     {\n       \"type\"  :   \"Quiz\"  ,\n       \"status\"  :   \"published\"  ,\n       \"search\"  :   \"onboarding\"  ,\n       \"sortBy\"  :   \"published\"  ,\n       \"sortOrder\"  :   \"DESC\"  ,\n       \"page\"  :   1\n   }\n  Pagination  Next to   data , the response contains a   pagination  object so you know whether you have to fetch more pages:     {\n       \"success\"  :   true  ,\n       \"data\"  : [  \"... the Riddles of this page ...\"  ],\n       \"pagination\"  : {\n           \"page\"  :   1  ,\n           \"pageSize\"  :   12  ,\n           \"total\"  :   137  ,\n           \"hasMore\"  :   true\n       }\n   }\n   total  is the number of Riddles matching your   filters , not the total number of Riddles in the project, so you can page through a filtered list with   hasMore .   Tip:  To list Riddles across your   entire account  (personal project plus all team projects), use the   /riddle/account-list  endpoint instead. It supports the same filters and the same   pagination  object, except   project .   Tip:  Combine   origin: \"api\"  with the   delete endpoint  to find and clean up the Riddles your integration created.  Get a single Riddle  To retrieve a single Riddle, including its content, settings, and metadata, use the   /riddle/{UUID}  endpoint with the Riddle's UUID.  This is also useful to look up block and answer IDs, e.g. when working with the   Stats API .  Both this endpoint and   /riddle/list  include a   features  object on each Riddle:     Property  Type  Description  Default     cta  boolean  Whether the Riddle has a call-to-action button     form  boolean  Whether the Riddle has a lead generation form     hasDependencies  boolean  Whether the Riddle depends on other Riddles, e.g. if this is a form embedded by other Riddles. Riddle-to-Riddle only - a Question Bank reference never sets this to true     hasEmbeddedRiddles  boolean  Whether the Riddle has other Riddles embedded in it, e.g. forms     hasQuestionBankDependencies  boolean  Whether the Riddle references at least one question bank     hasIntegration  boolean  Whether the Riddle is connected to at least one integration, e.g. MailChimp or Zapier; only present where it was resolved  false    connectedLeaderboards  object   The leaderboards this Riddle is connected to, each with   uuid  and   title     connectedRiddles  object   The Riddles connected to this Riddle, e.g. quizzes embedding this form, each with   uuid ,   type , and   title   Rename a Riddle  To rename a Riddle, send the new title to the   /riddle/rename/{UUID}  endpoint:     {\n       \"title\"  :   \"My new Riddle title\"\n   }\n  Publish or unpublish a Riddle    /riddle/publish/{UUID}  publishes a Riddle – it becomes available via its public URL and embed code.   /riddle/unpublish/{UUID}  takes a Riddle offline – the public URL is no longer reachable.  Both endpoints only require the Riddle UUID, no request body is needed.  Get the embed code  To retrieve the HTML embed code of a published Riddle, use the   /riddle/embed-code/{UUID}  endpoint. The   data  property of the response contains the embed code as a string, ready to be placed on your website.   Note:  This endpoint also works with old Riddle 1.0 IDs.  Get a QR code  To generate a QR code for a published Riddle (e.g. for print material), use the   /riddle/qr-code/{UUID}  endpoint.  Delete a Riddle  Riddles built via the Builder API can be deleted via the   Riddle delete endpoint . Deleting a Riddle created in the Creator is   not  possible via the API.   Learn more  Projects  Two endpoints help you work with projects, e.g. to find the project IDs used across the API:    /project/list  returns all the projects the user is a member of.   /project/{projectId}  returns information about a single project.   /project/list  returns   all  projects in a single response by default. If you have a lot of projects, add the query parameters   page  (1-indexed) and/or   pageSize  (default 50) to paginate instead - the response then also contains the same   pagination  object as the Riddle list:   GET /project/list?page=2&pageSize=25\n  Next steps     Manage tags : Organize your Riddles with tags and use them as list filters.    Fetch leads : Retrieve the leads collected by a Riddle.    Fetch stats : Read the results and engagement data of your Riddles.    Build Riddles : Create and edit Riddles of every type from a JSON build configuration.    Generate Riddles with AI : Let the Riddle AI create a Riddle from a topic or a URL.    Look at the specification of all available API endpoints : Find out what you can do with the Riddle API.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":48,"path":49,"dir":34,"title":50,"description":51,"keywords":52,"body":57},"content:15.Api:2.Manage Riddles:1.Tags.md","/api/manage-riddles/tags","Tags - Manage Riddles","Learn how to manage Riddle tags via API",[53,54,55,56],"List all tags","Get the tags of a Riddle","Add a tag to a Riddle","Remove a tag from a Riddle","  Manage tags  Tags help you organize your Riddles – and they are the most reliable way to find Riddles again programmatically, as you can   filter the Riddle list by tag IDs .  List all tags  To get all tags and their occurrence counts, use the   /tag/list  API endpoint.     Property  Required  Type  Description     project   integer|null  The project ID you want to get the tags from; pass   NULL  to explicitly get the user's tags; if nothing is sent, the project of the API key is used   Note:  Riddle tags and question bank tags share the same set of tags: a tag has one id, whichever side it was created from. The   count  returned here only counts how many Riddles use the tag, so   count: 0  does not mean the tag is unused - a question bank may still reference it.  Get the tags of a Riddle  To get all tags of a single Riddle, use the   /tag/riddle/list/{UUID}  endpoint with the Riddle's UUID.  Add a tag to a Riddle  To tag a Riddle, use the   /tag/riddle/{UUID}  endpoint. Send   either    name    or    id :     Property  Required  Type  Description     name  (one of the two)  string  Creates a new tag with the given name and attaches it to the Riddle    id  (one of the two)  integer  Attaches an already existing tag to the Riddle  Example: Create and attach a new tag:     {\n       \"name\"  :   \"summer-campaign\"\n   }\n  Remove a tag from a Riddle  To remove a tag from a Riddle, use the   /tag/riddle/{UUID}/{tag}  DELETE endpoint, where   tag  is the tag ID. The endpoint returns the serialized Riddle with its remaining tags, or HTTP 404 if the given tag + Riddle combination could not be found.  The tag itself is only deleted from the project once nothing uses it any more - neither a Riddle nor a question bank.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":59,"path":60,"dir":34,"title":61,"description":62,"keywords":63,"body":65},"content:15.Api:2.Manage Riddles:2.Leads.md","/api/manage-riddles/leads","Leads - Manage Riddles","Learn how to fetch the leads of a Riddle via API",[64,16],"Fetching the leads of a Riddle","  Fetch leads  Every form submission in a Riddle is stored as a   lead . Besides sending leads to integrations or exporting them in the Creator, you can also fetch them directly via the API – e.g. to sync them into your own CRM or database.   Note:  The leads endpoint is available for the   Business  and   Enterprise  plans.  Fetching the leads of a Riddle  To fetch the leads of a Riddle, use the   /leads/riddle/{UUID}  API endpoint. By default the newest 25 leads are returned; use the   page  and   limit  parameters to paginate through the leads.  You can use the following   optional  parameters:     Property  Type  Description  Default     page  integer  The page you want to return  first page    limit  integer  How many results the page should contain (maximum: 200)  25    search  string  Search term; exact match for an email address, or partial match for data in the current page     completed  boolean  Set to   true  to only return completed leads; if not sent, all leads are returned     orderBy  string  By which field to order; available:   createdAt     order  string  The order of the results;   ASC  or   DESC     dateFrom  string  Only return leads from this date on (format:   Y-m-d )     dateTo  string  Only return leads up to this date (format:   Y-m-d )   Example: Fetch the 50 newest completed leads of June 2026:     {\n       \"page\"  :   1  ,\n       \"limit\"  :   50  ,\n       \"completed\"  :   true  ,\n       \"orderBy\"  :   \"createdAt\"  ,\n       \"order\"  :   \"DESC\"  ,\n       \"dateFrom\"  :   \"2026-06-01\"  ,\n       \"dateTo\"  :   \"2026-06-30\"\n   }\n  Next steps     Send leads to integrations : Learn how leads work and how to send them to Google Sheets, Mailchimp, webhooks, and more.    Analyze your Riddles : Use the Stats API to analyze views, starts, and submissions.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":67,"path":68,"dir":34,"title":69,"description":70,"keywords":71,"body":77},"content:15.Api:2.Manage Riddles:3.Stats.md","/api/manage-riddles/stats","Stats - Manage Riddles","Learn how to analyze Riddles via API",[72,73,74,75,76],"Accessing the Stats API","What is tracked in the stats?","How can I use the stats data and which endpoints are available?","Stats data structure","FAQ / Troubleshooting","  Stats  To analyze your Riddles, you can use the   Riddle Stats API  to retrieve stats for any of your Riddles, projects or for your personal project.  This can help you to analyze the performance of your Riddles, to optimize them, and to get insights into your audience. Dealing with this programmatically via the API allows you to automate this process.  In the next sections we will cover different aspects and endpoints of the Stats API.  Accessing the Stats API  To learn how to access the Riddle API please refer to the   Getting started  guide. If you are already familiar with the API, you can find all available Stats API endpoints   here .  What is tracked in the stats?  Any interaction with a Riddle is tracked. This includes views, starts, finishes, time spent, leads generated, and more. In general, everything you see on your Riddle stats dashboard is available via the API.  In addition to that   project and user wide stats  are tracked as well and can be requested via the API.  How can I use the stats data and which endpoints are available?  The stats endpoints serve very distinct purposes and structure the data in different ways:     Fetch:  This endpoint provides raw stats data for a single Riddle, project or user. This is useful if you want to analyze the performance of a Riddle on a high level.    Overview fetch:  This endpoint provides the raw stats data for a Riddle, project or user but splits up the given time range into multiple data points. This is useful if you want to get insights over a period of time, giving you multiple data points to analyze.    Breakdown:  This endpoint provides a detailed stats breakdown of a Riddle with all its associated labels/titles. This is useful if you want to analyze the performance of a Riddle on a low/block level and make it additionally human readable.    Project breakdown :  This endpoint provides a detailed stats breakdown of all Riddles of a project. This is useful if you want to compare the performance of multiple Riddles of a project. Running into a timeout? Try specifying a smaller time range (with   dateFrom  and   dateTo  JSON params).    User breakdown:  This endpoint provides a detailed stats breakdown of all user + project Riddle stats.  This is useful if you want to compare the performance of multiple Riddles of various projects. Please note that this endpoint is the slowest of all breakdowns as it accumulates the most data in one response. Running into a timeout? Try specifying a smaller time range (with   dateFrom  and   dateTo  JSON params).  Stats data structure  We have come up with our own format for the stats data. As your Riddle is a collection of blocks, you can think of the stats data as a combination of global stats (views, finishes) and a collection of individual block stats. Please note that this explanation is not applicable to 1.0 Riddles.  An example stats object looks like this:     {\n       \"global_stats\"  : {\n           \"core_metrics\"  : {\n               \"view\"  :   20  ,\n               \"start\"  :   6  ,\n               \"time\"  :   2737546  ,\n               \"lead\"  :   5  ,\n               \"timeActive\"  :   434477  ,\n               \"lead_completed\"  :   4  ,\n               \"finish\"  :   4\n           },\n           \"device\"  : {\n               \"mobile\"  :   8  ,\n               \"desktop\"  :   12\n           },\n           \"os\"  : {\n               \"iOS\"  :   8  ,\n               \"Mac OS\"  :   10  ,\n               \"Windows\"  :   2\n           },\n           \"region\"  : {\n               \"GB\"  :   16  ,\n               \"DE\"  :   2  ,\n               \"US\"  :   2\n           },\n           \"domain\"  : {\n               \"riddle.com\"  :   19  ,\n               \"yourdomain.com\"  :   1\n           }\n       },\n       \"block_1_stats\"  : {\n           \"core_metrics\"  : {\n               \"view\"  :   5  ,\n               \"timeActive\"  :   29583  ,\n               \"submit\"  :   5\n           },\n           \"answer\"  : {\n               \"2\"  :   2  ,\n               \"1\"  :   2  ,\n               \"-1\"  :   1\n           }\n       },\n       \"block_2_stats\"  : {\n           \"core_metrics\"  : {\n               \"view\"  :   6\n           },\n           \"form\"  : {\n               \"submit\"  :   5\n           }\n       },\n       \"reset_stats\"  : {\n           \"core_metrics\"  : {\n               \"view\"  :   6  ,\n               \"start\"  :   3  ,\n               \"time\"  :   120788  ,\n               \"timeActive\"  :   69082  ,\n               \"finish\"  :   3  ,\n               \"lead_completed\"  :   3  ,\n               \"lead\"  :   2  ,\n               \"times_reset\"  :   1\n           },\n           \"device\"  : {\n               \"desktop\"  :   6\n           },\n           \"os\"  : {\n               \"Mac OS\"  :   6\n           },\n           \"region\"  : {\n               \"GB\"  :   6\n           },\n           \"domain\"  : {\n               \"riddle.com\"  :   6\n           }\n       }\n   }\n  Let's go through the different parts of the stats object in the following sections.  Global Stats (\"global_stats\")  These are the global stats for the Riddle. They are not specific to a block. They can be divided into the categories:   core_metrics: most important and easiest metrics such as views, finishes, time / timeActive (in milliseconds), ...  device: device type (mobile, desktop, ...)  os: operating system (iOS, Windows, ...)  region: region with 2 chars (GB, DE, ...)  domain: domain of the website where the Riddle was viewed. Riddle.com is the default showcase domain.  Block Stats  These are the stats for each block. They can be divided into the categories:   core_metrics: views  answer: the amount of times each answer was selected; to find answer IDs refer to the Riddle GET API endpoint.  form: the amount of times the form was submitted / skipped  Reset Stats  If you choose to reset stats for a Riddle, the stats for the Riddle will be reset and the stats for the reset Riddle will be stored in the \"reset_stats\" object.  This makes sure no data is really lost; only hidden for the stats dashboard and the user.  FAQ / Troubleshooting   Q: Can I access this API with my subscription plan?   A:  The Stats API is available for the Business and Enterprise plan. If you are on the Pro plan you can still analyze your Riddles via the stats dashboard in the Creator.   Q: Can I access stats for a date range?   A:  Yes, you can access stats for a date range. To do this use the   stats fetch endpoint  and specify the params \"dateFrom\" & \"dateTo\" in your request.   Q: How can I access my accumulated project stats?   A:  To do this you need to specify the namespace (this is   project ) and the project ID (param entityId) in your request to the   stats fetch endpoint , example body for project 123:     {\n       \"namespace\"  :   \"project\"  ,\n       \"entityId\"  :   123\n   }\n   Q: How can I access Riddle stats?   A:  To do this you need to specify the namespace (this is   riddle ) and your Riddle UUID (param entityId) in your request to the   stats fetch endpoint , example body for Riddle abc123:     {\n       \"namespace\"  :   \"riddle\"  ,\n       \"entityId\"  :   \"abc123\"\n   }\n   Q: How can I get insights over a period of time, giving me multiple data points to analyze?   A:  To build a chart as easy as possible with the stats data you can use the   overview fetch endpoint  instead of the normal fetch endpoint. The difference in between those two endpoints is that the overview fetch endpoint splits up the given time range into multiple data points. E.g. if you request for a whole month (= 30 days), 15 data points will be returned with each representing two days (30 / 15 = 2).   Q: How does the Riddle / Project / user stats breakdown response look like?  An example response to   the Riddle breakdown endpoint  looks like this:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : {\n           \"general\"  : {\n               \"device\"  : {\n                   \"mobile\"  :   5  ,\n                   \"desktop\"  :   3\n               },\n               \"os\"  : {\n                   \"iOS\"  :   5  ,\n                   \"Windows\"  :   2  ,\n                   \"Mac OS\"  :   1\n               },\n               \"core_metrics\"  : {\n                   \"view\"  :   8  ,\n                   \"lead\"  :   4  ,\n                   \"start\"  :   4  ,\n                   \"time\"  :   8315  ,\n                   \"finish\"  :   4\n               },\n               \"domain\"  : {\n                   \"riddle.com\"  :   8\n               },\n               \"region\"  : {\n                   \"DE\"  :   6  ,\n                   \"GB\"  :   1\n               }\n           },\n           \"blocks\"  : [\n               {\n                   \"id\"  :   2  ,\n                   \"title\"  :   \"My Riddle title\"  ,\n                   \"metrics\"  : {\n                       \"view\"  :   0  ,\n                       \"time\"  :   0  ,\n                       \"submit\"  :   4\n                   },\n                   \"choices\"  : [\n                       {\n                           \"id\"  :   1  ,\n                           \"title\"  :   \"Choice 1\"  ,\n                           \"count\"  :   1\n                       },\n                       {\n                           \"id\"  :   2  ,\n                           \"title\"  :   \"Choice 2\"  ,\n                           \"count\"  :   2\n                       },\n                       {\n                           \"id\"  :   3  ,\n                           \"title\"  :   \"Choice 3\"  ,\n                           \"count\"  :   1\n                       }\n                   ]\n               }\n           ],\n           \"results\"  : [\n               {\n                   \"id\"  :   3  ,\n                   \"title\"  :   \"Thanks for your vote!\"  ,\n                   \"metrics\"  : {\n                       \"view\"  :   4\n                   },\n                   \"socialShares\"  : []\n               }\n           ]\n       }\n   }\n  If you choose to request a breakdown for either a project or a full user, the response will be similar but an array of all concerned Riddles (either all project Riddles OR all user + project Riddles) will be returned.  Here's a high level overview of the structure of the response:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : {\n           \"RIDDLE_ID1\"  : {\n               \"general\"  : {\n                   ...\n               },\n           },\n           \"RIDDLE_ID2\"  : {\n               \"general\"  : {\n                   ...\n               },\n           }\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":79,"path":80,"dir":81,"title":82,"description":83,"keywords":84,"body":89},"content:15.Api:4.Build Riddles:0.Getting started.md","/api/build-riddles/getting-started","build-riddles","Getting started - Build Riddles","Learn how to build Riddles dynamically via API",[85,86,87,88,16],"Request format","Example: Build a poll","Limits","FAQ","  Getting started  You can use the   Riddle Builder API  to create and edit Riddles dynamically via API. This opens up a lot of possibilities, such as:   building Riddles dynamically based on user input  building Riddles based on data from a database, spreadsheet or from other sources  building daily Riddles for contests or promotions   Tip:  The same build configuration can also be applied on top of Riddles generated by the AI, so you can let the AI write the content while you stay in control of the result pages, design and publish settings.   Click here  to learn more.  Request format  Every request to the   build  endpoint has   two levels :   the   root  of the payload - which Riddle type to build and how to handle the build itself  the    build  object  inside it - the content, design and settings of the Riddle     {\n       \"type\"  :   \"Quiz\"  ,           // \u003C- root: what to build & how\n       \"project\"  :   123  ,\n       \"publish\"  :   true  ,\n       \"build\"  : {                // \u003C- the Riddle itself\n           \"title\"  :   \"...\"  ,\n           \"blocks\"  : [],\n           \"results\"  : []\n       }\n   }\n  1. Root properties     Property  Required  Type  Description  Default     type  ✓  string  The Riddle type to build     build  ✓  object  The build configuration (see below)     publish   boolean  Publish the Riddle right after it was built  false    queue   boolean  Build the Riddle   asynchronously  - the response contains an initialized, still empty Riddle  false    project   integer  The project ID the Riddle should be created in  null    strictProperties   boolean  Reject a build configuration property (in any config depth, level) that no Riddle type or block knows (  400 ) instead of silently ignoring it - and with it the undocumented   bare-value item shorthand  false   Note:  If you use a personal project API key (= access to all of the projects in your account), you can use   project  to create the Riddle in a specific project.   Click here  to learn more.  2. The build configuration  The   build  object holds the Riddle itself. Not all properties are available for every Riddle type.     Property  Required  Type  Description  Available for...  Default     title  ✓  string  The title of the Riddle   All types     blocks  ✓  object   The blocks that make up the Riddle (questions, forms, ...). The order in which you send them is the exact order of the Riddle. Objects only - see   item formats  All types except Leaderboard and Placeholder, which have no blocks     result   object  The   single  result page shown after the Riddle is completed. Leave it out to get the default result page for that Riddle type  Poll, Form, Personality, Predictor, Minigame, Story     results   array   Several  result pages, segmented by the score the visitor reached (  minPercentage /  maxPercentage ). Leave it out to get the default result pages  Quiz     preset   object  The   design  (preset & palette) the Riddle should use   All types     publish   object  The   publish settings  (lead collection, email automation, integrations, ...)   All types     logic   object  The   flow  of the Riddle  Quiz, Poll, Form, Story     leaderboards   array  The   leaderboards  the Riddle should report to  Quiz, Predictor, Minigame   On top of those, each Riddle type accepts a few type specific properties (e.g.   personalities  and   attributes  for a personality test). They are documented on the page of each Riddle type.   Note:  An unsupported property is ignored by default, so a typo like   titel  instead of   title  builds successfully and does nothing. Set   strictProperties  to   true  to have it rejected with a   400  instead. When   editing an existing Riddle  it always is, and that cannot be turned off.   Note:  Do not confuse the two   publish  properties:   publish  in the   root  is a boolean that publishes the Riddle after building it, while   publish  inside    build  is the object holding the publish   settings . They can be combined.  Example: Build a poll  A minimal poll: one question with two answers, and a result page.     {\n       \"type\"  :   \"Poll\"  ,\n       \"project\"  :   123  ,\n       \"build\"  : {\n           \"title\"  :   \"Favorite color poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"What's your favorite color?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"green\"   },\n                       {   \"title\"  :   \"red\"   }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thank you\"  ,\n               \"description\"  :   \"Thanks for your vote.\"\n           }\n       }\n   }\n  Every block, settings object and result page on the following pages plugs into this same payload. What changes from Riddle to Riddle is what goes into   blocks , not the structure around it.  Limits  The Riddle Builder API applies the following limits to every build:     Limit  Value    Blocks per Riddle  500   Items per block (answers, form fields, personalities, ...)  100   Distinct media URLs per build  15   Blocks in a Riddle that can use custom   logic  250   Riddles per   batch  request  100  FAQ   Q: Can I access this API?   A:  The Builder API is part of the Business and Enterprise subscription plans.   Q: How do I access this API?   A:  With an API key, the same way as every other Riddle endpoint - see the   API getting started guide .   Q: Where can I find the builder endpoint?   A:  In the   API reference .   Q: Which Riddle types are currently supported?   A:  All of them:   poll ,   quiz ,   personality test ,   form ,   predictor ,   leaderboard ,   minigame ,   story  and   placeholder .   Q: What happens if I send a property that does not exist?   A:  In a   POST /riddle-builder  build it is ignored, so a typo like   titel  instead of   title  builds successfully and does nothing. Set the root property   strictProperties  to   true  to get a   400  instead, naming the offending key and listing the properties that are supported in its place. On an   edit  unknown properties are always rejected.   Q: Can I change a Riddle after it was built?   A:  Yes, with   PUT /riddle-builder/{UUID} , which applies the same build configuration as a merge - only what you send changes. It also works for Riddles the   Riddle AI  generated. See   editing Riddles .   Q: Can I publish the built Riddle right after building it?   A:  Yes, with   \"publish\": true  in the root of the payload. See   publishing the built Riddle .   Q: Are there any limits?   A:  Yes, on blocks, items, media URLs, logic and batch size - see the   limits table  above.   Q: Can I use this API to create monetized Riddles?   A:  Yes, with the    Ad  block , in every Riddle type.   Q: Can I use this API to create Riddles with a specific design?   A:  Yes, if   the Riddle is built in a project . Either let it use the project's default preset, or name the preset and palette yourself with the   preset  property. Both are covered in the   preset settings .  Next steps  Here are a few things you can do next - they are all covered in the following pages:   Build a   quiz ,   poll ,   personality test ,   form ,   predictor ,   minigame ,   story  or   placeholder   Learn the item format every collection uses: an array of objects  Configure the   design , the   publish settings  and the   flow/logic  of your Riddle   Handle the errors a build can answer with   Read an existing Riddle back  or   edit it  with the same build configuration  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":91,"path":92,"dir":81,"title":93,"description":94,"keywords":95,"body":103},"content:15.Api:4.Build Riddles:1.Exception handling.md","/api/build-riddles/exception-handling","Exception handling - Build Riddles","Learn how to handle exceptions when building Riddles via API",[96,97,98,99,98,100,101,102],"All builder error codes","Block property validation exception","Example","Block property value invalid","Block type missing","Block type invalid","Errors of asynchronous builds","  Exception handling  The build configuration can be faulty in many ways:   The structure of the build object is invalid  The properties of the blocks are invalid  The values of the properties are invalid  In the next sections we will go over the different types of errors that can occur and how to handle them. Each section contains the   unique error code  you receive -   check the exception handling section  for more information about exceptions and their unique exception codes.  All builder errors are returned with HTTP status   400  and share the same response shape:     Property  Type  Description  Default     success  boolean  Always   false  for an error     code  integer  The HTTP status code     error  string  The unique error code, e.g.   RIDDLE_BUILDER_BLOCK_TYPE_INVALID     message  string  A human readable description of what went wrong, usually prefixed with the block that caused it     validationErrors  array  Only for   RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION  - one entry per invalid property   All builder error codes     Error code  When it happens     RIDDLE_BUILDER_BLOCK_TYPE_MISSING  A block object has no   type  property    RIDDLE_BUILDER_BLOCK_TYPE_INVALID  A block's   type  is not a type the current Riddle type supports    RIDDLE_BUILDER_BLOCK_REQUIRED_PROPERTY_MISSING  A property a block requires was not sent    RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION  One or more property values did not pass validation - see   validationErrors    RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_INVALID  Validation passed, but the value could not be applied when building the block (e.g. it references something that does not exist)    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_INVALID_NODE  A   logic  node is malformed, e.g. its   blockId  is missing or not a positive integer    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_NON_EXISTING_BLOCK  A logic node references a block ID the Riddle does not contain    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_INVALID_RULE  An answer rule is invalid, e.g. it names an answer the block does not have    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_NON_UNIQUE_RULES  The same answer is used more than once in the rules of one node    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_CIRCULAR_REFERENCE  The logic tree points back to a block that already appeared earlier in the same path    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_DEAD_ENDS  A logic path ends without leading to a result    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_UNUSED_BLOCKS  The logic tree does not use every block of the Riddle    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_LINEAR_ONLY_ALLOWED  Answer branching was used in a Riddle that only supports a linear flow (e.g. flashcards)    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_CONDITION_INVALID_MAPPABLE  A   condition branching  node's   condition.field  does not refer to a value that block offers    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_CONDITION_OPERATOR_NOT_ALLOWED  A condition's   operator  is not one of the operators allowed for the kind of field its   condition.field  refers to    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_SCORE_RANGE_OVERLAP  Two   score branching  ranges overlap, or a range's   min  is greater than its   max    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_DELETED_BLOCK_STILL_REFERENCED  Only when   editing a Riddle : a block the request deletes is still referenced by the Riddle's custom logic    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_RESET_CONFLICT   \"logic\": {\"$reset\": true}  was combined with other logic configuration in the same object   Note:  Validation   may  stop at the   first  validation that fails, so fixing one error can reveal the next one. E.g. errors of a single block, however, are collected and reported together in   validationErrors .  Block property validation exception   Error code:  RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION  This error occurs when the value of a property of a block is invalid. The response will contain a   validationErrors  array with all the errors that occurred.  Example  In this example we use a Predictor build config in which the   title  is not a string and the   items  property is missing.  The API returns the following:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION\"  ,\n       \"message\"  :   \"PredictorPickTheWinnerBlock: Block properties are invalid: Property   \\\"  title  \\\"  : Input is not a string. | PredictorPickTheWinnerBlock: Property   \\\"  items  \\\"   is required but not set\"  ,\n       \"validationErrors\"  : [\n           {\n               \"message\"  :   \"Input is not a string.\"  ,\n               \"code\"  :   \"NOT_STRING\"  ,\n               \"property\"  :   \"title\"\n           },\n           {\n               \"message\"  :   \"PredictorPickTheWinnerBlock: Property   \\\"  items  \\\"   is required but not set\"  ,\n               \"code\"  :   \"REQUIRED\"  ,\n               \"property\"  :   \"items\"\n           }\n       ]\n   }\n  As you can see the main   message  of the error names the block that is causing the issue and already lists every concrete problem, separated by   | . To handle the errors programmatically, check the   validationErrors  array instead; each validation error contains a   message ,   code , and   property .  Values outside a fixed list  Many properties accept only one of a fixed set of values - a media block's   mediaFit , a Recommended Content block's   sortBy , a Riddle timer's   format , a Placeholder condition's   tagMode , and so on. Sending anything else is rejected with the code   NOT_ALLOWED_VALUE , and the message   names the property and enumerates every accepted value , so you never have to look the list up to fix the call:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION\"  ,\n       \"message\"  :   \"PresetRiddleTimerBlock: Block properties are invalid: PresetRiddleTimerBlock: Property   \\\"  format  \\\"   has value   \\\"  mm:ss  \\\"  , which is not an allowed value. Allowed: s, m_s, x_m_x_s.\"  ,\n       \"validationErrors\"  : [\n           {\n               \"message\"  :   \"PresetRiddleTimerBlock: Property   \\\"  format  \\\"   has value   \\\"  mm:ss  \\\"  , which is not an allowed value. Allowed: s, m_s, x_m_x_s.\"  ,\n               \"code\"  :   \"NOT_ALLOWED_VALUE\"  ,\n               \"property\"  :   \"format\"\n           }\n       ]\n   }\n  This holds for every such property of every block and Riddle type.   null  is not handled here: a property that may be   null  still accepts it, and one that may not is reported as the missing/not-nullable error it is, not as a value outside the list.  URLs must be   http  or   https  Every URL a build configuration carries - a result page's   redirectUrl , a result builder button's   url , a share block's   url , an interactive-graphic hotspot's   actionUrl /  ctaUrl , the DOI   confirmationPageUrl , the showcase   customQrCodeDestination , an   Ad  block's iframe   url , a personality result's CTA URL, and every media   url /  attributionUrl /  previewImageUrl  - ends up in front of a visitor's browser. Only ordinary web addresses are therefore accepted: anything whose scheme is not   http  or   https  is rejected with the code   UNSUPPORTED_URL_SCHEME , even though it is a syntactically valid URL.     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION\"  ,\n       \"message\"  :   \"ResultRedirectBlock: Block properties are invalid: Property   \\\"  redirectUrl  \\\"  : Only http and https URLs are supported here, got   \\\"  ftp  \\\"  .\"  ,\n       \"validationErrors\"  : [\n           {\n               \"message\"  :   \"Only http and https URLs are supported here, got   \\\"  ftp  \\\"  .\"  ,\n               \"code\"  :   \"UNSUPPORTED_URL_SCHEME\"  ,\n               \"property\"  :   \"redirectUrl\"\n           }\n       ]\n   }\n  A value that is not a URL at all is still reported as the invalid URL it is, not as an unsupported scheme.  Block property value invalid   Error code:  RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_INVALID  This happens if the validation of the properties succeeded but when creating the block the values are invalid. There are too many possible errors to list them all here, but the error message will give you a hint about what went wrong.  Example  Adding an integration with a name which does not exist:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_INVALID\"  ,\n       \"message\"  :   \"Cannot add   \\\"  webhook  \\\"   integration with name   \\\"  webhook.riddle.com  \\\"   to Riddle as it does not exist\"\n   }\n  Block type missing  If we try to build a Riddle without setting the   type  property in a Riddle block the API will return the following error:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_TYPE_MISSING\"  ,\n       \"message\"  :   \"PredictorBuilder: No block type found in block config.\"\n   }\n  In this case the   PredictorBuilder  throws the exception. This can happen with other embedded blocks as well, e.g. the result page builder blocks.  Block type invalid   Error code:  RIDDLE_BUILDER_BLOCK_TYPE_INVALID  The block has a   type , but it is not one the surrounding builder supports - for example a   Prediction  block in a Quiz, or a form field type that is not available via the API:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_TYPE_INVALID\"  ,\n       \"message\"  :   \"Block type   \\\"  Prediction  \\\"   not supported in QuizBuilder.\"\n   }\n  For form fields the message additionally lists every type you can use:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_TYPE_INVALID\"  ,\n       \"message\"  :   \"Form field type   \\\"  Signature  \\\"   is not allowed in the builder API. Available: Name, Email, Phone, URL, Number, Country, ShortText, LongText, Checkbox, DatePicker, TimePicker, Dropdown, RadioButtons, Rating, Media, Content, Privacy, Captcha\"\n   }\n  Errors of asynchronous builds  Riddles that are built with   queue: true  or via the   batch endpoint  are processed   after  the response was sent, so none of the errors above can be returned to you - the request answers with an initialized, still empty Riddle instead, and a rejected build configuration simply leaves that Riddle empty.  Build your configuration synchronously (without   queue ) while you develop it, and only switch to queued or batch builds once it is known to be valid. To check a queued or batch payload   before  sending it, dry-run it with    POST /riddle-builder/validate  - it reports the same errors as the table above per item, without creating anything.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":105,"path":106,"dir":81,"title":107,"description":108,"keywords":109,"body":111},"content:15.Api:4.Build Riddles:2.Project.md","/api/build-riddles/project","Build Riddles in your projects - Build Riddles","Learn how to build Riddles in your projects via API",[110,98],"Permissions","  Build Riddles in your projects  By default the project of the accessing API key will be used - this means that if you use an API key created in your personal project the Riddle will always be added to your personal space.  To change this you can specify the   project  in the root to create the Riddle in a specific project.     Property  Required  Type  Description  Default     project   integer  The ID of the project the Riddle should be created in  the project of the API key  The project ID is resolved like this:   If   project  is set, that project is used - no matter which key you use, as long as the key has access to that project.  Otherwise, a   project API key  builds in its own project.  Otherwise (a   personal API key  without   project ), the Riddle is created in your personal space.  Permissions  Your API key needs the   create Riddle  permission in the project you name, otherwise the request is rejected with an access error. The same applies to the   batch endpoint , where   project  is applied to every Riddle of the batch.  The built Riddle belongs to the project, not to you personally: it is visible to everyone with access to that project, and the    preset  property resolves against the   project's  presets and palettes. Without a project, your personal preset is used instead.   Tip:    GET /riddle-builder/presets/{projectId}  returns the presets and palettes available for exactly that project - call it with the same ID you build in to get the values   preset  expects.  Example  The following example adds the built Riddle to the project with the ID   123 :     {\n       \"type\"  :   \"Poll\"  ,\n       \"project\"  :   123  ,\n       \"build\"  : {\n           \"title\"  :   \"Favorite color poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"What's your favorite color?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"green\"   },\n                       {   \"title\"  :   \"red\"   }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thank you\"  ,\n               \"description\"  :   \"Thanks for your vote.\"\n           }\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":113,"path":114,"dir":115,"title":116,"description":117,"keywords":118,"body":134},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:1.Poll.md","/api/build-riddles/riddle-types-and-other-blocks/poll","riddle-types-and-other-blocks","Create Poll - Build Riddles","Learn how to build Polls via API",[119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,16],"Properties every poll question shares","Add Single/multiple choice questions","Add Likert / matrix question","Add order it question","Add upvote question","Add Net Promoter Score question","Add Rate It question","Add Swiper question","Add Reaction Poll question","Add TextEntry question","Add TierList question","Add This or That question","Add a Question Bank block","Result page","Full example","  Create Poll  When building a poll you can add:    SingleChoice  and   MultipleChoice  questions  Other question formats:   Likert /  Matrix ,   Order ,   Upvote ,   NetPromoterScore ,   RateIt ,   Swiper ,   Reaction ,   TextEntry ,   TierList , and   ThisOrThat  A   QuestionBank  block that draws its questions from a   question bank  instead of carrying them itself   Form fields   General blocks  One result page  Properties every poll question shares  Unless a question type is listed as an exception below, all poll question blocks accept these:     Property  Required  Type  Description  Default     title  ✓  string  The question     description   string  The description of the question     media   string|object  An image, video, or social media embed shown with the question. Adding it automatically switches its display on. See   Use media     mediaOrientation   string  How that media is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original .   Settings  inherits the Riddle-wide setting  Settings    isRequired   boolean  If set to   false , the user can skip the question  true  Every question type supports a slightly different subset - the per-type tables below are exhaustive. A property a question type does not support is ignored rather than applied, so if a setting does not show up in the Riddle, check the table for that type first. The one exception is   otherOption , which is rejected outright when sent to a question type without an \"Other\" answer.  Every collection on this page -   items , a Likert   scale , a TierList's   tiers  - follows the shared   item formats : an array of objects, the entry's text in its   title . In a poll an item object is:     Item property  Required  Type  Description  Default     title  ✓  string  The item text     description   string  A secondary line under the item     media   string|object  An image or video for this individual item   A question can hold at most   100 items , and a whole build may reference at most   15 media  files.  Add Single/multiple choice questions  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   SingleChoice  or   MultipleChoice     title  ✓  string  The question     items  ✓  object   2-100 possible choices, each an object with its   title  plus an optional description or media - see   item formats     description   string  The description of the question     media   string|object  Media to display with the question     itemsShuffled   boolean  If set to   true , the order of the items/choices will be shuffled  false    isRequired   boolean  If set to   false , the user can skip the question  true    layoutType   string  The layout of the items, either   Rows  or   Columns  Rows    canWrapItems   boolean  Whether items may wrap onto a new line  true    isHeightFlexible   boolean  Whether each item's height flexes with its content  true    otherOption   object  Adds an \"Other\" answer with a free-text entry the user fills in:   {\"isEnabled\": boolean, \"label\": string} . Both keys are optional and independent of each other   isEnabled  false,   label  \"Other\"    answerMediaOrientation   string  How the media of the individual answer items is cropped:   Settings ,   Wide ,   Square ,   Tall ,   Original  Wide    isDescriptionVisible   boolean  Whether the per-answer descriptions are shown. One shared flag for the whole question, not one per answer: giving any item a   description  switches it on, sending   false  keeps the descriptions stored but hidden  derived from the items    maxSelections   integer   MultipleChoice  only: how many options may be picked at most (1-100)  2    hasUnlimitedSelections   boolean   MultipleChoice  only: lift the   maxSelections  cap entirely  true    areRemainingVotesVisible   boolean   MultipleChoice  only: show the user how many selections are left  true  Example     {\n       \"title\"  :   \"The best noodles?\"  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Spaghetti\"   },\n           {   \"title\"  :   \"Fusilli\"   }\n       ]\n   }\n  Here the difference between   SingleChoice  and   MultipleChoice  is that with   SingleChoice  the user can only select one answer, while with   MultipleChoice  the user can select multiple answers. Apart from that, they are the same for the build configuration - except for the three selection-cap properties above, which only a   MultipleChoice  question has.   Note:    otherOption  only exists on   SingleChoice  and   MultipleChoice ; sending it on any other poll question type is rejected with a validation error. It must be an object; Its two keys are independent of each other:   label  renames the \"Other\" answer but does not add it, and   isEnabled  on its own adds it with the default label \"Other\". Set both to add a renamed one:     {\n       \"otherOption\"  : {\n           \"isEnabled\"  :   true  ,\n           \"label\"  :   \"Something else\"\n       }\n   }\n  An example using all properties:     {\n       \"title\"  :   \"Which toppings do you want?\"  ,\n       \"type\"  :   \"MultipleChoice\"  ,\n       \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Cheese\"   },\n           {   \"title\"  :   \"Pineapple\"   },\n           {   \"title\"  :   \"Mushrooms\"   }\n       ],\n       \"itemsShuffled\"  :   true  ,\n       \"layoutType\"  :   \"Columns\"  ,\n       \"maxSelections\"  :   2  ,\n       \"hasUnlimitedSelections\"  :   false  ,\n       \"areRemainingVotesVisible\"  :   true  ,\n       \"otherOption\"  : {\n           \"isEnabled\"  :   true  ,\n           \"label\"  :   \"Something else\"\n       }\n   }\n  Add Likert / matrix question  A matrix question allows you to ask a question with multiple items and a scale. The user can select one answer for each item.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Matrix     title  ✓  string  The question     items  ✓  object   The statements (the matrix rows), each an object with its   title  - see   item formats     description   string  The description of the question     media   string|object  Media to display with the question     itemsShuffled   boolean  If set to   true , the order of the items/statements will be shuffled  false    scale   object  |object  The scale the user can choose from, e.g. 'Bad', 'Medium', 'Good' (2-100 entries). Each entry is an object with its   title ; key the collection by the value a rating stands for if you do not want the default 0, 1, 2, ... - see   item formats  5 scale items from 'Strongly agree' to 'Strongly disagree', plus 'N/A'    isNaEnabled   boolean  If set to   true , the user can select 'Not applicable' for each item  false    isSingleChoiceEnabled   boolean  If set to   true , the user can select only one answer per item  true    isMobileViewEnabled   boolean  Whether the dedicated, stacked mobile layout is used  true    isRequired   boolean  If set to   false , the user can skip the question  true   Note:  A matrix question renders as a grid rather than a list of answers, so it does not have   layoutType ,   canWrapItems ,   isHeightFlexible ,   otherOption ,   answerMediaOrientation ,   maxSelections ,   hasUnlimitedSelections  or   areRemainingVotesVisible  either - sending one is ignored like any other unsupported property, or rejected outright with   strictProperties: true  (see   Getting started ). Its   items  and   scale  entries carry no   description  or   media  of their own either - only their   title  (plus, for   scale , the custom scoring value as the entry's key). It does support   isRequired ,   media  and   mediaOrientation  for the question itself, like every other question.  Example  Here is an example with only the required configuration properties:     {\n       \"title\"  :   \"I am happy with the following aspects of Riddle.\"  ,\n       \"description\"  :   \"Choose one from 'Strongly agree' to 'Strongly disagree'\"  ,\n       \"type\"  :   \"Matrix\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Design\"   },\n           {   \"title\"  :   \"Usability\"   },\n           {   \"title\"  :   \"Performance\"   }\n       ]\n   }\n  For the next example we additionally shuffle the items, customize the scale (and its values) and set the other flags.     {\n       \"title\"  :   \"I am happy with the following aspects of Riddle.\"  ,\n       \"description\"  :   \"Choose one from 'Bad' to 'Good'\"  ,\n       \"type\"  :   \"Matrix\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Design\"   },\n           {   \"title\"  :   \"Usability\"   },\n           {   \"title\"  :   \"Performance\"   }\n       ],\n       \"itemsShuffled\"  :   true  ,\n       \"scale\"  : {\n           \"0\"  : {   \"title\"  :   \"Bad\"   },\n           \"2\"  : {   \"title\"  :   \"Medium\"   },\n           \"4\"  : {   \"title\"  :   \"Good\"   }\n       },\n       \"isNaEnabled\"  :   true  ,\n       \"isSingleChoiceEnabled\"  :   false\n   }\n  As you can see in the above example,   scale  can be keyed by the value that will be saved in the database (e.g. the user selects   Bad  => scale value 0 is saved as the response). By default the scale values are a series of auto incremented integers: send   scale  as a plain array to get them, e.g.   {\"scale\": [{\"title\": \"Bad\"}, {\"title\": \"Medium\"}, {\"title\": \"Good\"}]} .  Add order it question  An order it question allows you to ask a question with multiple items and the user can drag and drop them into the order they prefer.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Order     title  ✓  string  The question     items  ✓  object   2-100 items to rank, each an object with its   title  plus an optional description or media - see   item formats     description   string  The description of the question     media   string|object  Media to display with the question     itemsShuffled   boolean  If set to   true , the order of the items is shuffled before the user ranks them  false    isRequired   boolean  If set to   false , the user can skip the question  true    layoutType   string  The layout of the items, either   Rows  or   Columns  Rows    rankFormat   string  How the ranks of the items are displayed, either   Number ,   Letter  or   NumberEnum . Supplying it also switches the rank display on  Number    isRankFormatEnabled   boolean  Explicitly switch the rank display on/off. Setting   rankFormat  already switches it on; use   isRankFormatEnabled: false  to disable it again while keeping the format configured     isReverseOrder   boolean  Count the rank labels down from the highest number instead of up from 1. Purely a label concern - it does not change the user's actual ordering  false    upDownButtons   boolean  If set to   true , up and down buttons are shown on desktop instead of drag and drop  true    answerMediaOrientation   string  How the media of the individual items is cropped  Wide    isDescriptionVisible   boolean  Whether the per-answer descriptions are shown. One shared flag for the whole question, not one per answer: giving any item a   description  switches it on, sending   false  keeps the descriptions stored but hidden  derived from the items   Note:  An order question has no   canWrapItems ,   isHeightFlexible  or   otherOption .  Example     {\n       \"title\"  :   \"What are your favorite animals?\"  ,\n       \"description\"  :   \"Drag and drop the items into the order you prefer\"  ,\n       \"type\"  :   \"Order\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Dog\"   },\n           {   \"title\"  :   \"Cat\"   },\n           {   \"title\"  :   \"Bird\"   },\n           {   \"title\"  :   \"Fish\"   }\n       ],\n       \"layoutType\"  :   \"Rows\"  ,\n       \"rankFormat\"  :   \"Number\"  ,\n       \"isReverseOrder\"  :   false  ,\n       \"upDownButtons\"  :   false\n   }\n  Add upvote question  An upvote question allows you to ask a question with multiple items and the user can select one or more items to upvote.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Upvote     title  ✓  string  The question     items  ✓  object   2-100 possible choices, each an object with its   title  - see   item formats     description   string  The description of the question     media   string|object  Media to display with the question     isRequired   boolean  If set to   false , the user can skip the question  true    maxVotes   integer  The maximum number of items the user can upvote  1    areRemainingVotesVisible   boolean  Show the user how many upvotes they have left  true    isUpvoteSorted   boolean  Re-order the items by their upvote count (most upvoted first)  true    answerMediaOrientation   string  How the media of the individual items is cropped  Wide    isDescriptionVisible   boolean  Whether the per-answer descriptions are shown. One shared flag for the whole question, not one per answer: giving any item a   description  switches it on, sending   false  keeps the descriptions stored but hidden  derived from the items   Note:  An upvote question renders as a plain vote list, so it has no   layoutType ,   canWrapItems  or   isHeightFlexible .  Example     {\n       \"title\"  :   \"What do you like most about Riddle?\"  ,\n       \"description\"  :   \"Select one or more items\"  ,\n       \"type\"  :   \"Upvote\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Design\"   },\n           {   \"title\"  :   \"Usability\"   },\n           {   \"title\"  :   \"Performance\"   }\n       ],\n       \"maxVotes\"  :   2  ,\n       \"isUpvoteSorted\"  :   true  ,\n       \"areRemainingVotesVisible\"  :   true\n   }\n  Add Net Promoter Score question  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   NetPromoterScore     title  ✓  string  The question     positiveTitle  ✓  string  The title of the positive score, e.g.   I completely agree     negativeTitle  ✓  string  The title of the negative score, e.g.   I completely disagree     description   string  The description of the question     media   string|object  Media to display with the question     isRequired   boolean  If set to   false , the user can skip the question  true   Note:  An NPS question always shows the fixed 0-10 scale, so it has no   items  and no layout properties (  layoutType ,   canWrapItems ,   isHeightFlexible ).  Example     {\n       \"title\"  :   \"How likely are you to recommend Riddle to a friend?\"  ,\n       \"description\"  :   \"Select one of the options below\"  ,\n       \"type\"  :   \"NetPromoterScore\"  ,\n       \"positiveTitle\"  :   \"I completely agree\"  ,\n       \"negativeTitle\"  :   \"I completely disagree\"\n   }\n  Add Rate It question  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   RateIt     title  ✓  string  The question     items  ✓  object   2-100 things to rate, each an object with its   title  plus an optional description or media - see   item formats     description   string  The description of the question     media   string|object  Media to display with the question     itemsShuffled   boolean  If set to   true , the order of the items is shuffled  false    isRequired   boolean  If set to   false , the user can skip the question  true    layoutType   string  The layout of the items, either   Rows  or   Columns  Columns    canWrapItems   boolean  Whether items may wrap onto a new line  true    isHeightFlexible   boolean  Whether each item's height flexes with its content  true    displayType   string  The display type of the rating, either   Stars  or   Numbers  Stars    starCount   integer  The number of stars to display (if   displayType  is   Stars ); allowed range 1-10  5    numberMin   integer  The lowest number to display (if   displayType  is   Numbers ); allowed range -10 to 10  1    numberMax   integer  The highest number to display (if   displayType  is   Numbers ); allowed range -10 to 10  10    isRateItSortedAfterVote   boolean  Re-sort the rated items once a vote is in  false    answerMediaOrientation   string  How the media of the individual items is cropped  Wide    isDescriptionVisible   boolean  Whether the per-answer descriptions are shown. One shared flag for the whole question, not one per answer: giving any item a   description  switches it on, sending   false  keeps the descriptions stored but hidden  derived from the items   Note:    starCount  and   numberMin /  numberMax  are mutually exclusive. If   displayType  is set to   Stars , you cannot set   numberMin  or   numberMax . If   displayType  is set to   Numbers , you cannot set   starCount . Setting the properties for the wrong   displayType  will throw a validation error.  Example     {\n       \"title\"  :   \"How would you rate Riddle?\"  ,\n       \"type\"  :   \"RateIt\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Design\"   },\n           {   \"title\"  :   \"Usability\"   },\n           {   \"title\"  :   \"Performance\"   }\n       ],\n       \"itemsShuffled\"  :   true  ,\n       \"displayType\"  :   \"Numbers\"  ,\n       \"numberMin\"  :   1  ,\n       \"numberMax\"  :   5\n   }\n  Add Swiper question  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Swiper     title  ✓  string  The question     description   string  The description of the question     media   string|object  Media to display with the question     items   object   Exactly two swiper items (FIRST: negative, SECOND: positive); described in detail below. The item's text is its   title  - see   item formats  the two default Riddle swipe buttons    isRequired   boolean  If set to   false , the user can skip the question  true    textPosition   string  Where the item text sits relative to the card:   BelowCard  or   Overlay  BelowCard    buttonType   string  The look of the two swipe buttons:   Riddle ,   Emoji ,   Media  or   Text . Set it after   items  if you want to override what the item contents imply  Riddle    colorLikeButtonBackground   string  The background color of the like button  #59e1abff    colorLikeButtonIcon   string  The color of the like button icon  #000000ff    colorLikeButtonText   string  The color of the like button text  #000000ff    colorDislikeButtonBackground   string  The background color of the dislike button  #000000ff    colorDislikeButtonIcon   string  The color of the dislike button icon  #ffffff    colorDislikeButtonText   string  The color of the dislike button text  #ffffff  Specifying negative / positive items  If you want to specify the negative / positive items in more detail, pass two objects in the   items  array. Each of them has the following properties:     Property  Required  Type  Description  Default     title   string  The title of the item     emoji   string  The emoji to display in the item, e.g.   👍  or   👎     media   string|object  The image or video to display in the item    Note:  Each item needs exactly one of   title ,   emoji , and   media  - an item is either a text card, an emoji card or a media card. Sending an item with none of them, or with more than one of them, is rejected with a validation error.  Example     {\n       \"title\"  :   \"How do you feel about Riddle?\"  ,\n       \"description\"  :   \"Swipe left or right to answer\"  ,\n       \"type\"  :   \"Swiper\"  ,\n       \"items\"  : [\n           {\n               \"emoji\"  :   \"😞\"\n           },\n           {\n               \"emoji\"  :   \"😍\"\n           }\n       ],\n       \"textPosition\"  :   \"Overlay\"  ,\n       \"buttonType\"  :   \"Emoji\"\n   }\n  Add Reaction Poll question  A reaction poll allows users to react to a question using a scale, e.g. from 'strongly disagree' to 'strongly agree'.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Reaction     title  ✓  string  The question     description   string  The description of the question     media   string|object  Media to display with the question     reactionType   string  One of the built-in scales:   AgreeDisagree  or   LikeDislike     reactionScale   string[]  A custom scale, lowest to highest, e.g.   \"Bad\", \"Okay\", \"Good\"     isRequired   boolean  If set to   false , the user can skip the question  true   Note:  You need   exactly one  of   reactionType  and   reactionScale . Leaving both out is rejected (  PollReactionBlock must have either \"reactionType\" or \"reactionScale\" set. ), and so is setting both (  PollReactionBlock cannot have a \"reactionType\" set when \"reactionScale\" is defined. ) - neither silently wins over the other.   Note:  A custom   reactionScale  must contain at least 3 items and an odd number of items - an even number of items will be rejected. The scale is scored symmetrically around 0, so   [\"Bad\", \"Okay\", \"Good\"]  stores the scores -1, 0 and 1.  Example: predefined reaction scale     {\n       \"title\"  :   \"How do you feel about Riddle?\"  ,\n       \"description\"  :   \"Select one of the options below\"  ,\n       \"type\"  :   \"Reaction\"  ,\n       \"reactionType\"  :   \"AgreeDisagree\"\n   }\n  Example: custom reaction scale     {\n       \"title\"  :   \"How do you feel about Riddle?\"  ,\n       \"description\"  :   \"Select one of the options below\"  ,\n       \"type\"  :   \"Reaction\"  ,\n       \"reactionScale\"  : [\n           \"Bad\"  ,\n           \"Okay\"  ,\n           \"Good\"\n       ]\n   }\n  Add TextEntry question  A free-text question: the person taking the Poll can type anything, there is no correct answer.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   TextEntry     title  ✓  string  The question     description   string  The description of the question     media   string|object  Media to display with the question     isRequired   boolean  If set to   false , the user can skip the   question  true    label   string  A label shown above the text input     inputDescription   string  A description shown with the text input     placeholder   string  Placeholder text shown inside the empty input     prefilledText   string  Prefilled value for the input     isAnswerRequired   boolean  Whether the   text input itself  must be filled in before the respondent can continue  false    requiredMessage   string  Message shown when the input is required but left empty. Only allowed together with   isAnswerRequired: true     maxLength   integer  Maximum number of characters accepted (>= 0)     regex   string  Regex to validate the input; setting it also switches advanced validation on     validationMessage   string  Message shown when the regex validation fails. Only allowed together with   regex     isAdvancedValidationEnabled   boolean  Explicitly switch length/regex validation on/off. Setting   regex  or   validationMessage  already switches it on; use   isAdvancedValidationEnabled: false  to disable it again while keeping   regex  configured    Note:  There are genuinely   two independent  \"required\" flags on this question type:   isRequired  (shared with every other poll question - can the respondent skip the whole question) and   isAnswerRequired  (specific to   TextEntry  - once the respondent engages with the question, must the text field itself be filled in). They default differently (  isRequired  defaults   true ,   isAnswerRequired  defaults   false ) and neither implies the other.  Example     {\n       \"title\"  :   \"What's your favorite noodle dish?\"  ,\n       \"type\"  :   \"TextEntry\"  ,\n       \"placeholder\"  :   \"e.g. Spaghetti Carbonara\"  ,\n       \"isAnswerRequired\"  :   true  ,\n       \"requiredMessage\"  :   \"Please tell us your favorite dish\"  ,\n       \"regex\"  :   \"^[A-Za-z ]+$\"  ,\n       \"validationMessage\"  :   \"Please only use letters and spaces\"\n   }\n  Add TierList question  A drag-and-drop ranking question: the person taking the Poll sorts a list of items into named tiers (e.g. \"S\"/\"A\"/\"B\"/\"C\"/\"D\"/\"F\").  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   TierList     title  ✓  string  The question     tiers  ✓  object   At least 2 tiers, in order; see below. The tier label is its   title  - see   item formats     description   string  The description of the question     media   string|object  Media to display with the question     isRequired   boolean  If set to   false , the user can skip the question  true    items   object   The items to sort into tiers, at least 1 if the key is sent at all. May start empty and be added later. The item text is its   title  - see   item formats     isItemTitleEnabled   boolean  Explicitly switch the display of each item's title on/off. Giving any item a   title  already switches it on - see below  true    isItemMediaEnabled   boolean  Explicitly switch the display of each item's media on/off. Giving any item a   media  already switches it on - see below  true    itemMediaOrientation   string  How each item's own media is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings  Each entry in   tiers  supports:     Property  Required  Type  Description  Default     title  ✓  string  The name of the tier, e.g. \"S\"     colorBg   string  Background color of the tier     colorText   string  Text color of the tier   Each entry in   items  supports:     Property  Required  Type  Description  Default     title   string  The item's label     media   string|object  An image or video for this item    Note:  Giving   any  item a   title  (even an empty string) or a   media  switches the corresponding shared display flag (  isItemTitleEnabled /  isItemMediaEnabled ) on for the whole question. Both default to   true  already, so this only matters if you had previously switched one off and now add new item content - an explicit   isItemTitleEnabled /  isItemMediaEnabled  in the same build always wins over the automatic switch-on.  Example     {\n       \"title\"  :   \"Rank these noodle dishes\"  ,\n       \"type\"  :   \"TierList\"  ,\n       \"tiers\"  : [\n           {   \"title\"  :   \"S\"   },\n           {   \"title\"  :   \"A\"   },\n           {   \"title\"  :   \"B\"   },\n           {   \"title\"  :   \"F\"   }\n       ],\n       \"items\"  : [\n           {   \"title\"  :   \"Spaghetti Carbonara\"   },\n           {   \"title\"  :   \"Fusilli Pesto\"   },\n           {   \"title\"  :   \"Instant noodles\"   }\n       ]\n   }\n  Add This or That question  A head-to-head comparison: the person taking the Poll is shown two contenders at a time and picks one, until every pair has been decided.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   ThisOrThat     title  ✓  string  The question     items  ✓  object   The contenders -   one flat list  of at least 2, never a list of pairs. The pairs are formed from this list positionally, so the order decides who competes against whom. Each contender is an object with its   title  - see   item formats     description   string  The description of the question     media   string|object  Media to display with the question     isRequired   boolean  If set to   false , the user can skip the question  true    isProgressbarEnabled   boolean  Show a progress bar counting the decided pairs  false    isItemTitleEnabled   boolean  Explicitly switch the display of each contender's title on/off. Giving any contender a   title  already switches it on - see below  true    isItemMediaEnabled   boolean  Explicitly switch the display of each contender's media on/off. Giving any contender a   media  already switches it on - see below  true    itemMediaOrientation   string  How each contender's own media is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original  Square    separator   string  What is shown between the two contenders:   Versus ,   Colon ,   At ,   Dash ,   Slash , or   X  Versus  Each entry in   items  supports:     Property  Required  Type  Description  Default     title   string  The contender's label     media   string|object  An image or video for this contender   Each contender needs a   title , a   media , or both - a contender with neither is a blank half of a comparison and is rejected.   Note:  Giving   any  contender a   title  (even an empty string) or a   media  switches the corresponding shared display flag (  isItemTitleEnabled /  isItemMediaEnabled ) on for the whole question. Both default to   true  already, so this only matters if you had previously switched one off and now add new contender content - an explicit   isItemTitleEnabled /  isItemMediaEnabled  in the same build always wins over the automatic switch-on.  Example     {\n       \"title\"  :   \"Which one do you prefer?\"  ,\n       \"type\"  :   \"ThisOrThat\"  ,\n       \"separator\"  :   \"Versus\"  ,\n       \"isProgressbarEnabled\"  :   true  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Cats\"   },\n           {   \"title\"  :   \"Dogs\"   },\n           {   \"title\"  :   \"Hamsters\"   },\n           {   \"title\"  :   \"Fish\"   }\n       ]\n   }\n  Add a Question Bank block  A   QuestionBank  block has no questions of its own: it draws them from a   question bank  - a reusable pool of questions managed outside the Riddle - when the Riddle is viewed. The build configuration only   references  the bank by its ID; it never creates or edits the bank's questions.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   QuestionBank     questionBankId  ✓  integer  The ID of an existing question bank whose   riddleType  is   Poll . A bank built for a Quiz, a bank of a different project, or an ID that does not exist is rejected     title   string  A plain-text label for the block (no HTML)     isRequired   boolean  Whether the drawn question has to be answered before continuing  true    randomizationType   string   TimeBased  re-draws the questions every   refreshInterval  hours,   None  draws once and leaves the selection fixed  TimeBased    refreshInterval   integer  How often the draw is refreshed, in   hours  (minimum   1 ). Only meaningful together with   randomizationType: \"TimeBased\"  24    questionBankBlocks  ✓  object   One entry per block type the bank should draw into, see below. At least one entry is required - a block with none draws nothing at all   The   questionBankBlocks  array  Each entry says which kind of question is drawn from the bank, and how it is filtered:     Property  Required  Type  Description  Default     blockType  ✓  string   SingleChoice ,   MultipleChoice ,   Reaction ,   Upvote ,   Order ,   Swiper ,   RateIt ,   Matrix , or   NetPromoterScore . Each block type may appear at most once     isEnabled   boolean  Whether this block type actually draws from the bank  false    questionBankCriteria   object   Filters for the draw, see below. Omitted or empty means no filter - every item of that block type is eligible    Each entry of   questionBankCriteria :     Property  Required  Type  Description  Default     category  ✓  string  A category of the bank's items. Must be unique within one   questionBankCriteria  array     difficultyRange   integer   Exactly two integers   [min, max]  between 1 and 10,   min  \u003C=   max . An empty array means no difficulty filter      maxNumberOfQuestions   integer  At most this many questions are drawn from that category. Omit it to compute a default automatically, never send an explicit   null  computed automatically   Note:  Omitting   maxNumberOfQuestions  computes a default of at most 5, and at least 1, based on how many published items in the bank match the category and   difficultyRange . Sending an explicit   null  is rejected.   Note:  The bank's inventory is not checked while building. Asking for more questions than the bank actually holds is reported as a   warning when publishing , never as a build error - call   GET /question-bank/riddle-items/{riddleUUID}/{blockId}  to see which items a block would draw right now.   Note:  A   QuestionBank  block always draws from the bank's   published  state. A bank with unpublished changes keeps serving its last published questions, so publish the bank after changing its items.   Note:  Sending   questionBankBlocks  when   editing an existing Riddle  replaces the whole array, like every other repeating collection of the Builder API.  Example     {\n       \"type\"  :   \"QuestionBank\"  ,\n       \"title\"  :   \"Random question of the day\"  ,\n       \"questionBankId\"  :   4712  ,\n       \"randomizationType\"  :   \"TimeBased\"  ,\n       \"refreshInterval\"  :   24  ,\n       \"questionBankBlocks\"  : [\n           {\n               \"blockType\"  :   \"SingleChoice\"  ,\n               \"isEnabled\"  :   true  ,\n               \"questionBankCriteria\"  : [\n                   {\n                       \"category\"  :   \"Sports\"  ,\n                       \"difficultyRange\"  : [  1  ,   5  ],\n                       \"maxNumberOfQuestions\"  :   3\n                   }\n               ]\n           }\n       ]\n   }\n  Result page  In a poll only one result page is allowed which is specified in   build.result . Basic results have a   title  and   description  property.  Example in   build.result :     {\n       \"title\"  :   \"Thank you!\"  ,\n       \"description\"  :   \"We are happy to have you here\"\n   }\n  If you want to create complex result pages with texts, images, answered blocks, ...   click here to learn how to build advanced result pages .  Full example  Example with all available question types + options:     {\n       \"type\"  :   \"Poll\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Poll example (Builder API)\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"What's your favorite color?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/png\"  ,\n                   \"mediaOrientation\"  :   \"Wide\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Red\"   },\n                       {\n                           \"title\"  :   \"Blue\"  ,\n                           \"description\"  :   \"Like the sky\"  ,\n                           \"media\"  :   \"https://httpbin.io/image/webp\"\n                       },\n                       {   \"title\"  :   \"Green\"   },\n                       {   \"title\"  :   \"Yellow\"   }\n                   ],\n                   \"itemsShuffled\"  :   true  ,\n                   \"layoutType\"  :   \"Columns\"  ,\n                   \"canWrapItems\"  :   true  ,\n                   \"isHeightFlexible\"  :   true  ,\n                   \"answerMediaOrientation\"  :   \"Square\"  ,\n                   \"otherOption\"  : {\n                       \"isEnabled\"  :   true  ,\n                       \"label\"  :   \"Something else\"\n                   }\n               },\n               {\n                   \"title\"  :   \"What are your favorite animals?\"  ,\n                   \"type\"  :   \"MultipleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Dog\"   },\n                       {   \"title\"  :   \"Cat\"   },\n                       {   \"title\"  :   \"Bird\"   },\n                       {   \"title\"  :   \"Fish\"   }\n                   ],\n                   \"isRequired\"  :   false  ,\n                   \"maxSelections\"  :   2  ,\n                   \"hasUnlimitedSelections\"  :   false  ,\n                   \"areRemainingVotesVisible\"  :   true\n               },\n               {\n                   \"title\"  :   \"I am happy with the following aspects of Riddle.\"  ,\n                   \"description\"  :   \"Choose one from 'Bad' to 'Good'\"  ,\n                   \"type\"  :   \"Matrix\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Design\"   },\n                       {   \"title\"  :   \"Usability\"   },\n                       {   \"title\"  :   \"Performance\"   }\n                   ],\n                   \"itemsShuffled\"  :   true  ,\n                   \"scale\"  : {\n                       \"0\"  : {   \"title\"  :   \"Bad\"   },\n                       \"2\"  : {   \"title\"  :   \"Medium\"   },\n                       \"4\"  : {   \"title\"  :   \"Good\"   }\n                   },\n                   \"isNaEnabled\"  :   true  ,\n                   \"isSingleChoiceEnabled\"  :   false  ,\n                   \"isMobileViewEnabled\"  :   true\n               },\n               {\n                   \"title\"  :   \"Rank these animals\"  ,\n                   \"description\"  :   \"Drag and drop the items into the order you prefer\"  ,\n                   \"type\"  :   \"Order\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Dog\"   },\n                       {   \"title\"  :   \"Cat\"   },\n                       {   \"title\"  :   \"Bird\"   },\n                       {   \"title\"  :   \"Fish\"   }\n                   ],\n                   \"itemsShuffled\"  :   true  ,\n                   \"layoutType\"  :   \"Rows\"  ,\n                   \"rankFormat\"  :   \"Number\"  ,\n                   \"isReverseOrder\"  :   false  ,\n                   \"upDownButtons\"  :   false  ,\n                   \"answerMediaOrientation\"  :   \"Wide\"\n               },\n               {\n                   \"title\"  :   \"What do you like most about Riddle?\"  ,\n                   \"description\"  :   \"Select one or more items\"  ,\n                   \"type\"  :   \"Upvote\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Design\"   },\n                       {   \"title\"  :   \"Usability\"   },\n                       {   \"title\"  :   \"Performance\"   }\n                   ],\n                   \"maxVotes\"  :   2  ,\n                   \"isUpvoteSorted\"  :   true  ,\n                   \"areRemainingVotesVisible\"  :   true\n               },\n               {\n                   \"title\"  :   \"How would you rate Riddle?\"  ,\n                   \"type\"  :   \"RateIt\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Design\"   },\n                       {   \"title\"  :   \"Usability\"   },\n                       {   \"title\"  :   \"Performance\"   }\n                   ],\n                   \"itemsShuffled\"  :   true  ,\n                   \"layoutType\"  :   \"Columns\"  ,\n                   \"displayType\"  :   \"Numbers\"  ,\n                   \"numberMin\"  :   1  ,\n                   \"numberMax\"  :   5  ,\n                   \"isRateItSortedAfterVote\"  :   true\n               },\n               {\n                   \"title\"  :   \"How likely are you to recommend Riddle to a friend?\"  ,\n                   \"description\"  :   \"Select one of the options below\"  ,\n                   \"type\"  :   \"NetPromoterScore\"  ,\n                   \"positiveTitle\"  :   \"I completely agree\"  ,\n                   \"negativeTitle\"  :   \"I completely disagree\"\n               },\n               {\n                   \"title\"  :   \"Hot or not: Riddle\"  ,\n                   \"description\"  :   \"Swipe left or right to answer\"  ,\n                   \"type\"  :   \"Swiper\"  ,\n                   \"items\"  : [\n                       {\n                           \"emoji\"  :   \"😞\"\n                       },\n                       {\n                           \"emoji\"  :   \"😍\"\n                       }\n                   ],\n                   \"textPosition\"  :   \"Overlay\"  ,\n                   \"buttonType\"  :   \"Emoji\"  ,\n                   \"colorLikeButtonBackground\"  :   \"#59e1abff\"  ,\n                   \"colorDislikeButtonBackground\"  :   \"#000000ff\"\n               },\n               {\n                   \"title\"  :   \"How do you feel about Riddle?\"  ,\n                   \"description\"  :   \"Select one of the options below\"  ,\n                   \"type\"  :   \"Reaction\"  ,\n                   \"reactionType\"  :   \"AgreeDisagree\"\n               },\n               {\n                   \"title\"  :   \"Anything else you would like to tell us?\"  ,\n                   \"type\"  :   \"TextEntry\"  ,\n                   \"label\"  :   \"Your feedback\"  ,\n                   \"placeholder\"  :   \"e.g. I love the TierList question\"  ,\n                   \"isAnswerRequired\"  :   true  ,\n                   \"requiredMessage\"  :   \"Please leave us a short note\"  ,\n                   \"maxLength\"  :   500\n               },\n               {\n                   \"title\"  :   \"Rank these noodle dishes\"  ,\n                   \"type\"  :   \"TierList\"  ,\n                   \"tiers\"  : [\n                       {\n                           \"title\"  :   \"S\"  ,\n                           \"colorBg\"  :   \"#59e1ab\"  ,\n                           \"colorText\"  :   \"#000000\"\n                       },\n                       {\n                           \"title\"  :   \"A\"\n                       },\n                       {\n                           \"title\"  :   \"B\"\n                       },\n                       {\n                           \"title\"  :   \"F\"\n                       }\n                   ],\n                   \"items\"  : [\n                       {\n                           \"title\"  :   \"Spaghetti Carbonara\"\n                       },\n                       {\n                           \"title\"  :   \"Fusilli Pesto\"\n                       },\n                       {\n                           \"title\"  :   \"Instant noodles\"\n                       }\n                   ],\n                   \"isItemTitleEnabled\"  :   true  ,\n                   \"itemMediaOrientation\"  :   \"Square\"\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thank you!\"  ,\n               \"description\"  :   \"We are happy to have you here\"\n           }\n       }\n   }\n  Next steps  Now that you know the basics of building a poll, you might want to learn how to:    Add form fields to your Riddle   Use the Ad block to monetize your Riddle or add Content blocks   Define the publish settings: Enable DOI, email automation, add integrations, and more   Define the preset and palette you want to use   Define the logic / flow of your Riddle   Build an advanced result page   Add media, such as images, videos, and social media content   Serve this Riddle through a Placeholder, so you can swap what an embed shows without changing the embed code  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":136,"path":137,"dir":115,"title":138,"description":139,"keywords":140,"body":150},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:2.Quiz.md","/api/build-riddles/riddle-types-and-other-blocks/quiz","Create Quiz - Build Riddles","Learn how to build Quizzes via API",[141,120,142,143,144,145,146,131,147,148,149,133,16],"Properties every quiz question shares","Add \"Type the answer\" questions","Add \"Order it\" questions","Add flashcard questions","Add TypeRush questions","Add GuessIt questions","Answer explanations","Answer explanations & scores per item","Result pages","  Create Quiz  When building a quiz you can add:   Quiz questions with answer explanations:   SingleChoice ,   MultipleChoice , and   TextEntry  (\"Type the answer\")  Quiz questions of type   Order ,   Flashcard ,   TypeRush , and   GuessIt  A   QuestionBank  block that draws its questions from a   question bank  instead of carrying them itself   Form fields   General blocks  Multiple result pages: segment users based on their score  Properties every quiz question shares     Property  Required  Type  Description  Default     type  ✓  string   SingleChoice ,   MultipleChoice ,   TextEntry ,   Order ,   Flashcard ,   TypeRush , or   GuessIt     title  ✓  string  The question     description   string  The description of the question     media   string|object  An image, video, or social media embed shown with the question. Adding it automatically switches its display on. See   Use media     mediaOrientation   string  How that media is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original .   Settings  inherits the Riddle-wide setting  Settings    isRequired   boolean  If set to   false , the user can skip the question. Not available on   Flashcard  true    score   integer  The score the user gets for answering this question correctly.   GuessIt  has no   score  property at all - it is scored by the number of guesses used instead, see below  1  Every question type supports a slightly different subset - the per-type tables below are exhaustive. A property a question type does not support is ignored rather than applied, so if a setting does not show up in the Riddle, check the table for that type first.  A question can hold at most   100 items/answers , and a whole build may reference at most   15 media  files.  Scoring: per question or per item   score  can be set on the question (all types)   or  on each individual item (  SingleChoice ,   MultipleChoice ,   TypeRush ) - setting it per item switches the question's scoring level to \"per answer\". Do not mix both levels within one question. Per-item   score  values must be >= 0 (>= 1 for   TypeRush ).   Order  is the exception: it is always scored as a single right/wrong answer for the whole sequence, so it only supports the question-level   score  - a per-item   score  is rejected.  Add Single/multiple choice questions  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   SingleChoice  or   MultipleChoice     title  ✓  string  The question     items  ✓  object   2-100 answer options, each an object with its   title  and   isCorrect  - see   item formats  and the section below     description   string  The description of the question     media   string|object  Media to display with the question. Adding it automatically switches its display on     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    itemsShuffled   boolean  If set to   true , the order of the items/choices will be shuffled  false    itemsRightOrWrong   boolean  If set to   true , the items are visually marked as right or wrong after answering  true    isRequired   boolean  If set to   false , the user can skip the question  true    score   integer  The score for answering this question correctly  1    layoutType   string  The layout of the items, either   Rows  or   Columns  Rows    canWrapItems   boolean  Whether items may wrap onto a new line  true    isHeightFlexible   boolean  Whether each item's height flexes with its content  true    answerMediaOrientation   string  How the media of the individual answer items is cropped:   Settings ,   Wide ,   Square ,   Tall ,   Original  Settings    isDescriptionVisible   boolean  Whether the per-answer descriptions are shown. One shared flag for the whole question, not one per answer: giving any item a   description  switches it on, sending   false  keeps the descriptions stored but hidden  derived from the items    explanation   object  An explanation object for the correct answer;   learn more     wrongExplanation   object  An explanation object for the incorrect answer;   learn more     explanationPosition   string  The position of the explanation (if given), either   BelowAnswers  or   Overlay  Overlay    isExplanationMediaEnabled   boolean  Whether the explanation's own media is displayed  true    isExplanationEnabled   boolean  Explicitly switch the answer explanation on/off. Supplying   explanation  already switches it on; use   isExplanationEnabled: false  to disable it again while keeping the explanation content configured     maxSelections   integer   MultipleChoice  only: how many options may be picked at most (1-100)  2    hasUnlimitedSelections   boolean   MultipleChoice  only: lift the   maxSelections  cap entirely  true    nrCorrectAnswersNeeded   integer   MultipleChoice  only: how many correct options the user must pick to score  1    areRemainingVotesVisible   boolean   MultipleChoice  only: show the user how many selections are left  true   hint  and   showCorrectAnswerButton  are   not  available on choice questions - they only exist on   Order ,   TextEntry ,   TypeRush  (hint) and   Order /  TextEntry  (correct-answer button).  Item formats  Choice items follow the shared   item formats : an array of objects, the answer text in   title . What is specific here is   isCorrect , which every answer carries:     {\n       \"title\"  :   \"The best noodles?\"  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Spaghetti\"  ,   \"isCorrect\"  :   true   },\n           {   \"title\"  :   \"Fusilli\"  ,   \"isCorrect\"  :   false   }\n       ]\n   }\n  An item takes more keys as soon as it carries a description, its own media, a score, or an explanation:     {\n       \"title\"  :   \"The best noodles?\"  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"items\"  : [\n           {\n               \"title\"  :   \"Spaghetti\"  ,\n               \"description\"  :   \"The classic\"  ,\n               \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n               \"isCorrect\"  :   true\n           },\n           {\n               \"title\"  :   \"Fusilli\"  ,\n               \"isCorrect\"  :   false\n           }\n       ]\n   }\n  Each item object supports:     Item property  Required  Type  Description  Default     title  ✓  string  The answer text     isCorrect  ✓  boolean  Whether this answer is correct     description   string  A secondary line under the answer     media   string|object  An image or video for this individual answer     score   integer  The score for this answer (>= 0); switches the question to per-answer scoring     explanation   object  An explanation shown for this specific answer; switches the question's explanations to per-answer   At least one item must be marked as correct. In   SingleChoice  questions exactly one item may be correct - marking more than one returns an error.  Want to set answer explanations or the score per item?   Learn more  Add \"Type the answer\" questions  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   TextEntry     title  ✓  string  Title of the block     answers  ✓  object   1-100 accepted answers, each an object with the answer as its   title  - see   item formats     description   string  Description of the block     media   string|object  Media to display with the question. Adding it automatically switches its display on     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    answerSuffix   string  A fixed suffix shown after the input, e.g. a unit like \"km\"     isRequired   boolean  If set to   false , the user can skip the question  true    hint   string  A hint shown with the question     ignoreCase   boolean  Set to true to ignore the case of the answer (e.g. \"hello\" and \"Hello\" would be considered the same)  true    ignoreSpaces   boolean  Set to true to ignore spaces in the answer (e.g. \"hello\" and \"h e l l o\" would be considered the same)  true    lives   integer  How many attempts the user gets to answer the question  3    unlimitedLives   boolean  Set to true to give the user unlimited attempts to answer the question  false    livesText   string  The label for lives  Lives    livesIcon   string  The icon used for the lives widget:   Heart ,   Numeric , or   X  Heart    isLivesDisplayEnabled   boolean  Whether the remaining lives are shown to the user at all  true    showCorrectAnswerButton   boolean  Set to   true  to offer a \"show correct answer\" button  false    score   integer  The score the user gets for answering this question correctly  1    explanation   object  An explanation object for the correct answer;   learn more     wrongExplanation   object  An explanation object for the incorrect answer;   learn more     explanationPosition   string  The position of the explanation (if given), either   BelowAnswers  or   Overlay  Overlay    isExplanationMediaEnabled   boolean  Whether the explanation's own media is displayed  true    isExplanationEnabled   boolean  Explicitly switch the answer explanation on/off. Supplying   explanation  already switches it on; use   isExplanationEnabled: false  to disable it again while keeping the explanation content configured    answers  follows the shared   item formats : an accepted answer carries nothing but its text, so every entry is an object with just a   title .  Example     {\n       \"title\"  :   \"Type 'hello' in either Italian, German, or French.\"  ,\n       \"type\"  :   \"TextEntry\"  ,\n       \"answers\"  : [\n           {   \"title\"  :   \"Ciao\"   },\n           {   \"title\"  :   \"Hallo\"   },\n           {   \"title\"  :   \"Bonjour\"   }\n       ]\n   }\n  Optional properties  By default case and spaces are ignored, the user has three attempts, cannot skip the question, and receives no explanation. To change this behavior you can set   ignoreCase ,   ignoreSpaces ,   lives ,   isRequired , and the   explanation  properties:     {\n       \"title\"  :   \"Type 'hello' in either Italian, German, or French.\"  ,\n       \"type\"  :   \"TextEntry\"  ,\n       \"answers\"  : [\n           {   \"title\"  :   \"Ciao\"   },\n           {   \"title\"  :   \"Hallo\"   },\n           {   \"title\"  :   \"Bonjour\"   }\n       ],\n       \"isRequired\"  :   false  ,\n       \"ignoreCase\"  :   false  ,\n       \"ignoreSpaces\"  :   false  ,\n       \"lives\"  :   1  ,\n       \"livesText\"  :   \"Attempts\"  ,\n       \"livesIcon\"  :   \"Numeric\"  ,\n       \"explanation\"  : {\n           \"title\"  :   \"Correct!\"  ,\n           \"description\"  :   \"Ciao, Hallo, and Bonjour all mean 'hello'\"\n       },\n       \"wrongExplanation\"  : {\n           \"title\"  :   \"Incorrect!\"  ,\n           \"description\"  :   \"Ciao, Hallo, and Bonjour all mean 'hello'\"\n       },\n       \"explanationPosition\"  :   \"BelowAnswers\"\n   }\n  Add \"Order it\" questions  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Order     title  ✓  string  Title of the question     items  ✓  object   2-100 items   in their correct order , each an object with its   title  plus an optional description or media - see   item formats     description   string  Description of the question     media   string|object  Media to display with the question. Adding it automatically switches its display on     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    itemsShuffled   boolean  Whether the items are shuffled before the user starts  true    itemsShuffledOnWrong   boolean  Whether the items are re-shuffled after a wrong attempt  false    isRequired   boolean  If set to   false , the user can skip the question  true    hint   string  A hint shown with the question     score   integer  The score the user gets for answering this question correctly  1    layoutType   string  Set to   Rows  or   Columns  Rows    rankFormat   string  Set to   Number ,   Letter , or   NumberEnum ; setting it also switches the rank badges on  Number    isRankFormatEnabled   boolean  Explicitly switch the rank badges on/off. Setting   rankFormat  already switches them on; use   isRankFormatEnabled: false  to disable them again while keeping the format configured     isRankReverseOrder   boolean  Whether the rank badges count down instead of up  false    answerMediaOrientation   string  How the media of the individual items is cropped:   Settings ,   Wide ,   Square ,   Tall ,   Original  Settings    isDescriptionVisible   boolean  Whether the per-answer descriptions are shown. One shared flag for the whole question, not one per answer: giving any item a   description  switches it on, sending   false  keeps the descriptions stored but hidden  derived from the items    showCorrectAnswerButton   boolean  Set to   true  to show the correct answer button  false    guessesAreUnlimited   boolean  Set to   true  to allow unlimited guesses  false    guesses   integer  How many attempts the user gets  3    guessesIcon   string  Set to   Heart ,   Numeric , or   X  Heart    guessesDisplayLabel   string  The label shown next to the remaining guesses  Lives    guessesDisplayEnabled   boolean  Whether the guesses widget is shown at all  true    explanation   object  An explanation object for the correct answer;   learn more     wrongExplanation   object  An explanation object for the incorrect answer;   learn more     explanationPosition   string  The position of the explanation (if given), either   BelowAnswers  or   Overlay  Overlay    isExplanationMediaEnabled   boolean  Whether the explanation's own media is displayed  true    isExplanationEnabled   boolean  Explicitly switch the answer explanation on/off. Supplying   explanation  already switches it on; use   isExplanationEnabled: false  to disable it again while keeping the explanation content configured     upDownButtons   boolean  If set to   true , up and down buttons are shown to change the order of the items instead of drag and drop  true   Note:  If you set   guessesAreUnlimited  to   true , you must not also send   guesses ,   guessesIcon  or   guessesDisplayLabel  - doing so returns a validation error.   guessesDisplayEnabled  stays allowed either way. Sending   guessesAreUnlimited: false  alongside the other guesses properties is fine.   canWrapItems  and   isHeightFlexible  are not available on   Order  questions.   itemsRightOrWrong  is not available either - an   Order  question is always scored as a single right/wrong answer for the whole sequence, so there is nothing to mark right/wrong per item.  Items are given   in the correct order ; the order you submit is the solution. They follow the shared   item formats : an object per item, its text in   title , plus   description  and   media  when the item carries more. Unlike   SingleChoice /  MultipleChoice , a per-item   score  or   explanation  is not supported on   Order  items - use the question-level   score /  explanation /  wrongExplanation  properties instead;   learn more .  Example  An example with only the required options:     {\n       \"title\"  :   \"Order the following colors from lightest to darkest.\"  ,\n       \"type\"  :   \"Order\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"red\"   },\n           {   \"title\"  :   \"blue\"   },\n           {   \"title\"  :   \"green\"   }\n       ]\n   }\n  An example with extensive configuration:     {\n       \"title\"  :   \"Order the following colors from lightest to darkest.\"  ,\n       \"type\"  :   \"Order\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"red\"   },\n           {   \"title\"  :   \"blue\"   },\n           {   \"title\"  :   \"green\"   }\n       ],\n       \"itemsShuffled\"  :   true  ,\n       \"itemsShuffledOnWrong\"  :   true  ,\n       \"isRequired\"  :   false  ,\n       \"score\"  :   5  ,\n       \"layoutType\"  :   \"Rows\"  ,\n       \"rankFormat\"  :   \"Number\"  ,\n       \"isRankReverseOrder\"  :   true  ,\n       \"showCorrectAnswerButton\"  :   true  ,\n       \"guesses\"  :   3  ,\n       \"guessesIcon\"  :   \"Heart\"  ,\n       \"guessesDisplayLabel\"  :   \"Cat lives\"  ,\n       \"upDownButtons\"  :   false  ,\n       \"explanation\"  : {\n           \"title\"  :   \"Correct!\"  ,\n           \"description\"  :   \"The correct order is red, blue, green\"\n       },\n       \"wrongExplanation\"  : {\n           \"title\"  :   \"Incorrect!\"  ,\n           \"description\"  :   \"The correct order is red, blue, green\"\n       },\n       \"explanationPosition\"  :   \"BelowAnswers\"\n   }\n  Add flashcard questions  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Flashcard     title  ✓  string  Title of the question     backside  ✓  object  The content the user sees when flipping the flashcard; see below     description   string  Description of the question     media   string|object  Media to display on the front of the flashcard     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    hint   string  Hint for the question     score   integer  The score the user gets for answering this question correctly  1    revealAnswerButtonText   string  Label of the button that flips the card     gotItRightButtonText   string  Label of the \"I got it right\" button     gotItWrongButtonText   string  Label of the \"I got it wrong\" button   Flashcards have   no answer explanations  -   explanation ,   wrongExplanation  and   explanationPosition  do not apply.   isRequired  is not available either, and unlike other question types, media display cannot be toggled off.   Note:  A Quiz that contains a   Flashcard  block only accepts   linear  logic -   answer ,   condition , and   score  branching are all rejected. See   Logic settings .  The   backside  object     Property  Required  Type  Description  Default     title  ✓  string  The answer shown on the back of the card     description   string  A longer explanation on the back     media   string|object  Media shown on the back     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings  Example     {\n       \"title\"  :   \"Capital of germany\"  ,\n       \"description\"  :   \"Germany is a country in Europe\"  ,\n       \"hint\"  :   \"Starts with a 'B'\"  ,\n       \"type\"  :   \"Flashcard\"  ,\n       \"revealAnswerButtonText\"  :   \"Flip it\"  ,\n       \"gotItRightButtonText\"  :   \"I knew it\"  ,\n       \"gotItWrongButtonText\"  :   \"No idea\"  ,\n       \"backside\"  : {\n           \"title\"  :   \"Berlin\"  ,\n           \"description\"  :   \"Berlin is the capital of Germany\"  ,\n           \"media\"  :   \"https://httpbin.io/image/png\"\n       }\n   }\n  Add TypeRush questions  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   TypeRush     title  ✓  string  Title of the question     items  ✓  object   1-100 items, each an object carrying its accepted   answers  plus an optional hint, media or score - see   item formats  and the section below     description   string  Description of the question     media   string|object  Media to display with the question. Adding it automatically switches its display on     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    rankFormat   string  Set to   Number ,   Letter , or   NumberEnum  Number    isRankFormatEnabled   boolean  Explicitly switch the rank badges on/off. Setting   rankFormat  already switches them on; use   isRankFormatEnabled: false  to disable them again while keeping the format configured     isRankReverseOrder   boolean  Whether the rank badges count down instead of up  false    isRequired   boolean  If set to   false , the user can skip the question  true    isIgnoringCase   boolean  Set to true to ignore the case of the answer (e.g. \"hello\" and \"Hello\" would be considered the same)  true    isIgnoringSpaces   boolean  Set to true to ignore spaces in the answer (e.g. \"hello\" and \"h e l l o\" would be considered the same)  true    isHintEnabled   boolean  Set to true to enable hints for each item  true    columnTitleHint   string  Header of the hint column  Hint    columnTitleAnswer   string  Header of the answer column  Answer    columnOrder   string  Which column comes first:   HintFirst  or   AnswerFirst  HintFirst    isAnswerMediaVisible   boolean  Whether the media of the individual items is shown  true    answerMediaOrientation   string  How the media of the individual items is cropped:   Settings ,   Wide ,   Square ,   Tall ,   Original  Settings    showCorrectAnswer   boolean  Whether the correct answers are revealed once the timer runs out  true    score   integer  The score the user gets for answering this question correctly; can either be set on question or answer level; must be >= 1  1  TypeRush questions have no answer explanations.  Item objects   items  follows the shared   item formats , with one specialty: a TypeRush item has no   title  of its own - its text   is  its accepted answer, so every entry carries an   answers  list instead.   answers  is a plain list of strings, one per accepted spelling.     Item property  Required  Type  Description  Default     answers  ✓  string   All accepted spellings of this item     hint   string  The hint shown for this item     media   string|object  An image or video for this item     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    score   integer  The score for this item (>= 1); switches the question to per-answer scoring   Example: simple TypeRush     {\n       \"title\"  :   \"Name Germany's three biggest cities\"  ,\n       \"description\"  :   \"A very hard question\"  ,\n       \"type\"  :   \"TypeRush\"  ,\n       \"items\"  : [\n           {   \"answers\"  : [  \"Berlin\"  ] },\n           {   \"answers\"  : [  \"Hamburg\"  ] },\n           {   \"answers\"  : [  \"Munich\"  ,   \"München\"  ] }\n       ],\n       \"score\"  :   5\n   }\n  Example: sophisticated TypeRush   Note:  If you provide a score for the whole question, you must not provide scores for individual answers, and vice versa; if you try to set both, the API will return an error.     {\n       \"title\"  :   \"Name Germany's three biggest cities\"  ,\n       \"description\"  :   \"A very hard question\"  ,\n       \"type\"  :   \"TypeRush\"  ,\n       \"items\"  : [\n           {\n               \"answers\"  : [  \"Berlin\"  ],\n               \"score\"  :   2  ,\n               \"hint\"  :   \"Starts with B\"\n           },\n           {\n               \"answers\"  : [  \"Hamburg\"  ],\n               \"score\"  :   3  ,\n               \"hint\"  :   \"Starts with H\"\n           },\n           {\n               \"answers\"  : [  \"Munich\"  ,   \"München\"  ],\n               \"score\"  :   4  ,\n               \"hint\"  :   \"Starts with M\"\n           }\n       ],\n       \"rankFormat\"  :   \"Letter\"  ,\n       \"columnTitleHint\"  :   \"Clue\"  ,\n       \"columnTitleAnswer\"  :   \"City\"  ,\n       \"columnOrder\"  :   \"AnswerFirst\"  ,\n       \"isRequired\"  :   false  ,\n       \"isIgnoringSpaces\"  :   false  ,\n       \"isHintEnabled\"  :   false\n   }\n  Add GuessIt questions  \"GuessIt\" is a \"guess the picture\" question: the respondent sees an image (optionally blurred) and types their guess into a text field, with hints revealed as their guesses run out.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   GuessIt     title  ✓  string  Title of the question     acceptableAnswers  ✓  object   1-100 accepted answers, each an object with the answer as its   title  - see   item formats     media   string|object  The picture the respondent has to guess. Adding it automatically switches its display on     mode   string   Image  or   Text  Image    guessItTitle   string  A short label shown above the picture (distinct from the question's own   title )     guessesLabel   string  The label shown next to the remaining guesses     numberOfGuesses   integer  How many attempts the respondent gets, 1-10  3    hints   string   Hints that are visible from the start     lockedHints   string   Hints that are progressively revealed as guesses are used up, at most 10. They occupy the   last  guess slots, in the order given - e.g. with 5 guesses and 2 locked hints, the first is revealed after the 4th failed guess and the second after the 5th     hintPosition   string   OnImage  or   BelowImage  OnImage    imageBlurMode   string   Progressive  (gets sharper with each failed guess),   None , or   Always  Progressive    showBlockTitle   boolean  Whether the question's own   title  is shown  true    showHowToPlay   boolean  Whether a \"how to play\" explainer is shown  true    isRequired   boolean  If set to   false , the user can skip the question  true    isIgnoringCase   boolean  Set to true to ignore the case of the answer  true    isIgnoringSpaces   boolean  Set to true to ignore spaces in the answer  true   acceptableAnswers  follows the shared   item formats : an accepted answer carries nothing but its text, so every entry is an object with just a   title .   Note:    GuessIt  has no   score  property - unlike every other quiz question type, it is not scored on a fixed correct/incorrect basis but purely by how many guesses the respondent needed.   lockedHints  cannot hold more entries than   numberOfGuesses  allows guess slots for - e.g. 3 locked hints require at least 3 guesses.  Example     {\n       \"title\"  :   \"Guess the city!\"  ,\n       \"type\"  :   \"GuessIt\"  ,\n       \"media\"  :   \"https://httpbin.io/image/png\"  ,\n       \"acceptableAnswers\"  : [\n           {   \"title\"  :   \"Berlin\"   }\n       ],\n       \"numberOfGuesses\"  :   5  ,\n       \"hints\"  : [  \"It's a capital city\"  ],\n       \"lockedHints\"  : [  \"It's in Germany\"  ,   \"It starts with a 'B'\"  ],\n       \"imageBlurMode\"  :   \"Progressive\"\n   }\n  Add a Question Bank block  A   QuestionBank  block has no questions of its own: it draws them from a   question bank  - a reusable pool of questions managed outside the Riddle - when the Riddle is viewed. The build configuration only   references  the bank by its ID; it never creates or edits the bank's questions.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   QuestionBank     questionBankId  ✓  integer  The ID of an existing question bank whose   riddleType  is   Quiz . A bank built for a Poll, a bank of a different project, or an ID that does not exist is rejected     title   string  A plain-text label for the block (no HTML)     isRequired   boolean  Whether the drawn question has to be answered before continuing  true    randomizationType   string   TimeBased  re-draws the questions every   refreshInterval  hours,   None  draws once and leaves the selection fixed  TimeBased    refreshInterval   integer  How often the draw is refreshed, in   hours  (minimum   1 ). Only meaningful together with   randomizationType: \"TimeBased\"  24    questionBankBlocks  ✓  object   One entry per block type the bank should draw into, see below. At least one entry is required - a block with none draws nothing at all   The   questionBankBlocks  array  Each entry says which kind of question is drawn from the bank, and how it is filtered:     Property  Required  Type  Description  Default     blockType  ✓  string   SingleChoice ,   MultipleChoice ,   Order ,   TextEntry ,   TypeRush , or   Flashcard . Each block type may appear at most once     isEnabled   boolean  Whether this block type actually draws from the bank  false    questionBankCriteria   object   Filters for the draw, see below. Omitted or empty means no filter - every item of that block type is eligible    Each entry of   questionBankCriteria :     Property  Required  Type  Description  Default     category  ✓  string  A category of the bank's items. Must be unique within one   questionBankCriteria  array     difficultyRange   integer   Exactly two integers   [min, max]  between 1 and 10,   min  \u003C=   max . An empty array means no difficulty filter      maxNumberOfQuestions   integer  At most this many questions are drawn from that category. Omit it to compute a default automatically, never send an explicit   null  computed automatically   Note:  Omitting   maxNumberOfQuestions  computes a default of at most 5, and at least 1, based on how many published items in the bank match the category and   difficultyRange . Sending an explicit   null  is rejected.   Note:  The bank's inventory is not checked while building. Asking for more questions than the bank actually holds is reported as a   warning when publishing , never as a build error - call   GET /question-bank/riddle-items/{riddleUUID}/{blockId}  to see which items a block would draw right now.   Note:  A   QuestionBank  block always draws from the bank's   published  state. A bank with unpublished changes keeps serving its last published questions, so publish the bank after changing its items.   Note:  Sending   questionBankBlocks  when   editing an existing Riddle  replaces the whole array, like every other repeating collection of the Builder API.  Example     {\n       \"type\"  :   \"QuestionBank\"  ,\n       \"title\"  :   \"Random history question\"  ,\n       \"questionBankId\"  :   4711  ,\n       \"randomizationType\"  :   \"TimeBased\"  ,\n       \"refreshInterval\"  :   24  ,\n       \"questionBankBlocks\"  : [\n           {\n               \"blockType\"  :   \"SingleChoice\"  ,\n               \"isEnabled\"  :   true  ,\n               \"questionBankCriteria\"  : [\n                   {\n                       \"category\"  :   \"History\"  ,\n                       \"difficultyRange\"  : [  3  ,   7  ],\n                       \"maxNumberOfQuestions\"  :   5\n                   }\n               ]\n           }\n       ]\n   }\n  Answer explanations  You can add an answer explanation to   SingleChoice ,   MultipleChoice ,   TextEntry , and   Order  questions.   Flashcard ,   TypeRush , and   GuessIt  questions do not support explanations.  To do this add an   explanation  object to the quiz question block configuration, consisting of:     Property  Required  Type  Description  Default     title  ✓  string  The title of the explanation     description   string  The description of the explanation     media   string|object  A media URL to an image to display as part of the explanation     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings  If you wish to have an incorrect answer explanation, you can add the   wrongExplanation  with the same properties as   explanation  to the block. If only   explanation  is provided, it will be shown as an explanation for both correct and incorrect answers. Sending   wrongExplanation    without    explanation  returns an error.  To modify where the explanation is shown, you can set the   explanationPosition  property to either   BelowAnswers  or   Overlay . If set to   BelowAnswers , the explanation will be shown below the answer options. If set to   Overlay , the explanation will be shown in an overlay on top of the question (default:   Overlay ). Use   isExplanationMediaEnabled: false  to keep an explanation's media out of the rendered Riddle without removing it. Use   isExplanationEnabled: false  to switch the whole explanation off without removing its configured content - useful if you want to temporarily disable it while keeping the text/title ready to re-enable later.  Example     {\n       \"title\"  :   \"Type 'hello' in either Italian, German, or French.\"  ,\n       \"type\"  :   \"TextEntry\"  ,\n       \"answers\"  : [\n           {   \"title\"  :   \"Ciao\"   },\n           {   \"title\"  :   \"Hallo\"   },\n           {   \"title\"  :   \"Bonjour\"   }\n       ],\n       \"explanation\"  : {\n           \"title\"  :   \"My correct explanation\"  ,\n           \"description\"  :   \"My correct explanation description\"  ,\n           \"media\"  :   \"https://httpbin.io/image/webp\"\n       },\n       \"wrongExplanation\"  : {\n           \"title\"  :   \"My wrong explanation\"  ,\n           \"description\"  :   \"My wrong explanation description\"  ,\n           \"media\"  :   \"https://httpbin.io/image/svg\"\n       },\n       \"explanationPosition\"  :   \"BelowAnswers\"\n   }\n  Answer explanations & scores per item  Just as in the Riddle Creator, you can provide an explanation and score for each item/answer individually. This works for   SingleChoice  and   MultipleChoice  (  TypeRush  supports a per-item   score , but no per-item explanation).   Order  does   not  support a per-item   score  or   explanation  - an   Order  question is always scored as a single right/wrong answer for the whole sequence, and a per-item   score /  explanation  is rejected. Use the question-level   score  for scoring, and the question-level   explanation /  wrongExplanation  for a single correct/incorrect explanation instead;   learn more .   Note:  You must either provide an explanation + a score for each answer, one for all, or none. Per-item   score  values must be >= 0; negative scores will be rejected.   Example   SingleChoice  object:     {\n       \"title\"  :   \"The best noodles?\"  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"explanationPosition\"  :   \"BelowAnswers\"  ,\n       \"items\"  : [\n           {\n               \"title\"  :   \"Spaghetti\"  ,\n               \"isCorrect\"  :   true  ,\n               \"score\"  :   2  ,\n               \"explanation\"  : {\n                   \"title\"  :   \"Correct!\"  ,\n                   \"description\"  :   \"Spaghetti is the best noodle\"\n               }\n           },\n           {\n               \"title\"  :   \"Fusilli\"  ,\n               \"isCorrect\"  :   false  ,\n               \"score\"  :   0  ,\n               \"explanation\"  : {\n                   \"title\"  :   \"Incorrect!\"  ,\n                   \"description\"  :   \"Spaghetti is the best noodle\"\n               }\n           }\n       ]\n   }\n  In the example above   Spaghetti  would be the correct choice and the user would get 2 points for selecting it. If they select   Fusilli  they would get 0 points and see the explanation \"Spaghetti is the best noodle\". This results in a maximum score of 2.   Note:  The optional property   explanationPosition  must be set on the block level although the explanations are set on the item level.  Result pages  In a quiz you can specify multiple result pages to segment users based on their scores. For example users who score between 0-50% will see one result, users who score between 51-100% will see another result. Each result has a   title ,   description ,   minPercentage , and   maxPercentage  property.  As there can be multiple results, we store the results in an array in   build.results :     [\n       {\n           \"title\"  :   \"My result 0-30%\"  ,\n           \"description\"  :   \"Description 1\"  ,\n           \"minPercentage\"  :   0  ,\n           \"maxPercentage\"  :   50\n       },\n       {\n           \"title\"  :   \"My result 31-100%\"  ,\n           \"description\"  :   \"Description 2\"  ,\n           \"minPercentage\"  :   51  ,\n           \"maxPercentage\"  :   100\n       }\n   ]\n  If you want to create complex result pages with texts, images, answered blocks, ...   click here to learn how to build advanced result pages .  Full example  Example with all available blocks + options:     {\n       \"type\"  :   \"Quiz\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Quiz example (Builder API)\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"What's the capital of Germany?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Leipzig\"  ,   \"isCorrect\"  :   false   }\n                   ],\n                   \"explanation\"  : {\n                       \"title\"  :   \"Correct!\"  ,\n                       \"description\"  :   \"Berlin is the capital of Germany\"\n                   },\n                   \"wrongExplanation\"  : {\n                       \"title\"  :   \"Incorrect!\"  ,\n                       \"description\"  :   \"Berlin is the capital of Germany\"\n                   }\n               },\n               {\n                   \"title\"  :   \"What are valid colors in German?\"  ,\n                   \"type\"  :   \"MultipleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"rot\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"schwarz\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"nero\"  ,   \"isCorrect\"  :   false   }\n                   ],\n                   \"maxSelections\"  :   2  ,\n                   \"hasUnlimitedSelections\"  :   false  ,\n                   \"nrCorrectAnswersNeeded\"  :   2  ,\n                   \"explanation\"  : {\n                       \"title\"  :   \"Correct!\"  ,\n                       \"description\"  :   \"Only 'rot' and 'schwarz' are valid colors in German\"\n                   }\n               },\n               {\n                   \"title\"  :   \"Type 'hello' in either Italian, German, or French.\"  ,\n                   \"type\"  :   \"TextEntry\"  ,\n                   \"answers\"  : [\n                       {   \"title\"  :   \"Ciao\"   },\n                       {   \"title\"  :   \"Hallo\"   },\n                       {   \"title\"  :   \"Bonjour\"   }\n                   ],\n                   \"explanation\"  : {\n                       \"title\"  :   \"Correct!\"  ,\n                       \"description\"  :   \"Ciao, Hallo, and Bonjour all mean 'hello'\"\n                   },\n                   \"wrongExplanation\"  : {\n                       \"title\"  :   \"Incorrect!\"  ,\n                       \"description\"  :   \"Ciao, Hallo, and Bonjour all mean 'hello'\"\n                   },\n                   \"ignoreCase\"  :   true  ,\n                   \"ignoreSpaces\"  :   true  ,\n                   \"lives\"  :   3  ,\n                   \"livesIcon\"  :   \"Heart\"\n               },\n               {\n                   \"title\"  :   \"Order the following colors from lightest to darkest.\"  ,\n                   \"type\"  :   \"Order\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"red\"   },\n                       {   \"title\"  :   \"blue\"   },\n                       {   \"title\"  :   \"green\"   }\n                   ],\n                   \"itemsShuffled\"  :   true  ,\n                   \"guesses\"  :   3\n               },\n               {\n                   \"title\"  :   \"Capital of Germany\"  ,\n                   \"description\"  :   \"Germany is a country in Europe\"  ,\n                   \"hint\"  :   \"Starts with a 'B'\"  ,\n                   \"type\"  :   \"Flashcard\"  ,\n                   \"backside\"  : {\n                       \"title\"  :   \"Berlin\"  ,\n                       \"description\"  :   \"Berlin is the capital of Germany\"\n                   }\n               },\n               {\n                   \"title\"  :   \"Name Germany's three biggest cities\"  ,\n                   \"description\"  :   \"A very hard question\"  ,\n                   \"type\"  :   \"TypeRush\"  ,\n                   \"items\"  : [\n                       {\n                           \"answers\"  : [  \"Berlin\"  ],\n                           \"score\"  :   2  ,\n                           \"hint\"  :   \"Starts with B\"\n                       },\n                       {\n                           \"answers\"  : [  \"Hamburg\"  ],\n                           \"score\"  :   3  ,\n                           \"hint\"  :   \"Starts with H\"\n                       },\n                       {\n                           \"answers\"  : [  \"Munich\"  ],\n                           \"score\"  :   4  ,\n                           \"hint\"  :   \"Starts with M\"\n                       }\n                   ],\n                   \"rankFormat\"  :   \"Letter\"  ,\n                   \"columnTitleHint\"  :   \"Clue\"  ,\n                   \"columnTitleAnswer\"  :   \"City\"  ,\n                   \"columnOrder\"  :   \"AnswerFirst\"\n               },\n               {\n                   \"title\"  :   \"Guess the city!\"  ,\n                   \"type\"  :   \"GuessIt\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/png\"  ,\n                   \"acceptableAnswers\"  : [\n                       {   \"title\"  :   \"Berlin\"   }\n                   ],\n                   \"guessItTitle\"  :   \"Which city is this?\"  ,\n                   \"numberOfGuesses\"  :   5  ,\n                   \"hints\"  : [  \"It's a capital city\"  ],\n                   \"lockedHints\"  : [  \"It's in Germany\"  ,   \"It starts with a 'B'\"  ],\n                   \"hintPosition\"  :   \"BelowImage\"  ,\n                   \"imageBlurMode\"  :   \"Progressive\"  ,\n                   \"showHowToPlay\"  :   true\n               }\n           ],\n           \"results\"  : [\n               {\n                   \"title\"  :   \"Not so good...\"  ,\n                   \"description\"  :   \"There's room for improvement\"  ,\n                   \"minPercentage\"  :   0  ,\n                   \"maxPercentage\"  :   50\n               },\n               {\n                   \"title\"  :   \"Well done!\"  ,\n                   \"description\"  :   \"You're a winner\"  ,\n                   \"minPercentage\"  :   51  ,\n                   \"maxPercentage\"  :   100\n               }\n           ]\n       }\n   }\n  Next steps  Now that you know the basics of building a quiz, you might want to learn how to:    Add form fields to your Riddle   Use the Ad block to monetize your Riddle or add Content blocks   Connect your built Riddle to leaderboard(s)   Define the publish settings: Enable DOI, email automation, add integrations, and more   Define the preset and palette you want to use   Define the logic / flow of your Riddle   Build advanced result pages   Add media, such as images, videos, and social media content   Serve this Riddle through a Placeholder, so you can swap what an embed shows without changing the embed code  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":152,"path":153,"dir":115,"title":154,"description":155,"keywords":156,"body":157},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:3.Form.md","/api/build-riddles/riddle-types-and-other-blocks/form","Create Form - Build Riddles","Learn how to build Forms via API",[132,133,16],"  Create Form  Building a standalone form to exclusively collect user data can be done via the API.  When building a form you can add:    Form fields : a   FormBuilder  block with many fields, single standalone   FormField  blocks, or an embedded   FormSelect   General blocks :   Content ,   Quote , and   Ad  One result page  A form has no question blocks -   SingleChoice ,   Order , and the other question types of the other Riddle types are not available here. Everything else works the same as in any other build: at most 500 blocks, 100 items per block, and 15 media per build.  Result page  In a form only one result page is allowed which is specified in   build.result . Basic results only consist of a   title  and   description  property.  Example:     {\n       \"title\"  :   \"Thank you!\"  ,\n       \"description\"  :   \"We are happy to have you here\"\n   }\n  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 the block types a form accepts: a   Content  and a   Quote  block, an   Ad  block, a   FormBuilder  with several field types, and a standalone   FormField .   Note:  The example below uses dynamic variables to personalize the result page.   Click here to learn more about dynamic variables .     {\n       \"type\"  :   \"Form\"  ,\n       \"build\"  : {\n           \"title\"  :   \"My data collection form\"  ,\n           \"blocks\"  : [\n               {\n                   \"type\"  :   \"Content\"  ,\n                   \"title\"  :   \"Join our newsletter\"  ,\n                   \"description\"  :   \"It only takes a minute.\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n                   \"mediaOrientation\"  :   \"Wide\"\n               },\n               {\n                   \"title\"  :   \"Please enter your data.\"  ,\n                   \"description\"  :   \"We only need the basics.\"  ,\n                   \"type\"  :   \"FormBuilder\"  ,\n                   \"isRequired\"  :   true  ,\n                   \"fields\"  : [\n                       {\n                           \"title\"  :   \"Your email\"  ,\n                           \"type\"  :   \"Email\"  ,\n                           \"placeholder\"  :   \"Enter your email address\"  ,\n                           \"isRequired\"  :   true  ,\n                           \"requiredMessage\"  :   \"We need your email to get back to you.\"\n                       },\n                       {\n                           \"title\"  :   \"Your name\"  ,\n                           \"type\"  :   \"Name\"  ,\n                           \"autocomplete\"  :   \"given-name\"  ,\n                           \"maxLength\"  :   40\n                       },\n                       {   \"title\"  :   \"Your country\"  ,   \"type\"  :   \"Country\"   },\n                       {\n                           \"title\"  :   \"How did you hear about us?\"  ,\n                           \"type\"  :   \"Dropdown\"  ,\n                           \"items\"  : [\n                               {   \"title\"  :   \"Search engine\"   },\n                               {   \"title\"  :   \"Social media\"   },\n                               {   \"title\"  :   \"A friend\"   }\n                           ]\n                       },\n                       {\n                           \"type\"  :   \"Privacy\"  ,\n                           \"privacyText\"  :   \"\u003Cp>We store your data to get back to you. See our privacy policy.\u003C/p>\"  ,\n                           \"requiredConsentForAddRiddleData\"  : {\n                               \"isEnabled\"  :   true  ,\n                               \"isRequired\"  :   true  ,\n                               \"label\"  :   \"\u003Cp>May we combine your answers with your email?\u003C/p>\"  ,\n                               \"checkboxText\"  :   \"\u003Cp>Yes, you may\u003C/p>\"\n                           }\n                       }\n                   ]\n               },\n               {\n                   \"title\"  :   \"Anything else you would like to tell us?\"  ,\n                   \"type\"  :   \"FormField\"  ,\n                   \"fieldType\"  :   \"LongText\"  ,\n                   \"label\"  :   \"Your message\"  ,\n                   \"placeholder\"  :   \"Type your message here\"  ,\n                   \"maxLength\"  :   500\n               },\n               {\n                   \"type\"  :   \"Ad\"  ,\n                   \"iframe\"  : {\n                       \"url\"  :   \"https://ads.your-website.com/ad.html\"  ,\n                       \"height\"  :   250\n                   },\n                   \"showNextButtonDelay\"  :   3\n               },\n               {\n                   \"type\"  :   \"Quote\"  ,\n                   \"title\"  :   \"What our customers say\"  ,\n                   \"quoteText\"  :   \"The only way to do great work is to love what you do.\"  ,\n                   \"quoteAuthor\"  :   \"Steve Jobs\"\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thank you!\"  ,\n               \"description\"  :   \"Thank you for entering your data %name. We will get back to you soon.\"\n           }\n       }\n   }\n   Tip:  Instead of building the fields here, you can reuse a form you already published by adding a    FormSelect  block with that form's UUID. It is left out of the example above because it only builds with a UUID that actually exists in your project.  Next steps  Now that you know the basics of building a form, you might want to learn how to:    Add form fields to your Riddle   Use the Ad block to monetize your Riddle or add Content blocks   Define the publish settings: Enable DOI, email automation, add integrations, and more   Define the preset and palette you want to use   Define the logic / flow of your Riddle   Build an advanced result page   Add media, such as images, videos, and social media content   Serve this Riddle through a Placeholder, so you can swap what an embed shows without changing the embed code  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":159,"path":160,"dir":115,"title":161,"description":162,"keywords":163,"body":169},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:4.Form fields.md","/api/build-riddles/riddle-types-and-other-blocks/form-fields","Add form fields - Build Riddles","Learn how to build Form fields via API",[164,165,166,167,168,133],"Add a form builder","Customizing form fields","Adding single standalone form field blocks","Embed an already published form","Referencing form fields later","  Add form fields  Form fields can be added to any Riddle type (Poll, Quiz, Form, Predictor, Personality, Minigame, Story).  You can choose between two options:    Add a form builder  to this Riddle   Add a single standalone form field block  to this Riddle   Embed  an already published Riddle form from your (personal) project  Embedding another form allows you to reuse a form you have already created (= central data collection) but also allows you to build more complex forms than with the builder API.  Add a form builder  Like any other block you might add, such as   SingleChoice , you can add form fields to the Riddle build by adding a   FormBuilder  block item to the   blocks  array.  Properties  The form fields / builder block consists of:     Property  Required  Type  Description  Default     type  ✓  string  Set to   FormBuilder     title  ✓  string  The title of the form builder     fields  ✓  object   1-100 form fields, each an object with the field label as its   title  and a   type  - see   item formats  and the section below. Each field type must be one of the   available form fields     description   string  The description of the form builder     isRequired   boolean  Whether the form is required; if set to false the form can be skipped  false    media   string|object  Media to display as part of the form builder. Adding it automatically switches its display on. See   Use media   Example  The   FormBuilder  block isolated:     {\n       \"title\"  :   \"My form builder\"  ,\n       \"type\"  :   \"FormBuilder\"  ,\n       \"fields\"  : [\n           {   \"title\"  :   \"Your email\"  ,   \"type\"  :   \"Email\"   },\n           {   \"title\"  :   \"Your name\"  ,   \"type\"  :   \"Name\"   }\n       ]\n   }\n  Used in a poll build:     {\n       \"type\"  :   \"Poll\"  ,\n       \"build\"  : {\n           \"title\"  :   \"My new poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"The best noodles?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Spaghetti\"   },\n                       {   \"title\"  :   \"Fusilli\"   }\n                   ]\n               },\n               {\n                   \"title\"  :   \"My form builder\"  ,\n                   \"type\"  :   \"FormBuilder\"  ,\n                   \"fields\"  : [\n                       {   \"title\"  :   \"Your email\"  ,   \"type\"  :   \"Email\"   },\n                       {   \"title\"  :   \"Your name\"  ,   \"type\"  :   \"Name\"   }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thank you!\"  ,\n               \"description\"  :   \"We are happy to have you here\"\n           }\n       }\n   }\n   Note:  You can add as many form builders as you like   as long as you stay within the 500 blocks limit .  The   fields  format   fields  follows the shared   item formats : an array of objects, one per field. What is specific here is that a field carries two values of its own - its label, which is its   title , and its   type :     \"fields\"  : [\n       {   \"title\"  :   \"Your email\"  ,   \"type\"  :   \"Email\"   },\n       {   \"title\"  :   \"Your name\"  ,   \"type\"  :   \"Name\"  ,   \"isRequired\"  :   true   }\n   ]\n  Every other option of a field is a key of the same object - see the property table below.  Available form fields     Field type  Description     Name  Single-line name input    Email  Email input with email validation    Phone  Phone number input    URL  URL input    Number  Numeric input    Country  Country picker    ShortText  Single-line free text    LongText  Multi-line free text    Checkbox  A single checkbox with its own label text    DatePicker  Date input or date picker    TimePicker  Time input    Dropdown  Select one option from a list (see below)    RadioButtons  Select one option from visible radio buttons (see below)    Rating  Star rating (see   starCount )    Media  A non-interactive image/video inside the form (see below)    Content  A non-interactive rich text block inside the form (see below)    Privacy  The GDPR consent block: privacy notice + consent checkboxes (see below)    Captcha  Spam protection: Riddle's own captcha, Google reCAPTCHA, or Cloudflare Turnstile (see below)  The field type you send to the API is case-sensitive, and the names above are the Builder API names - reading a Riddle back with   riddle_get  returns the same names, even though the internal storage uses slightly different ones (e.g.   Dropdown  is stored as   DropDown ).  Customizing form fields  Beyond   title  and   type , a field object takes the options of its type - this is where you customize the field and how it behaves.  Here is an example how an   Email  field can be customized inside a   FormBuilder  block:     {\n       \"title\"  :   \"My form builder\"  ,\n       \"type\"  :   \"FormBuilder\"  ,\n       \"fields\"  : [\n           {\n               \"title\"  :   \"Your email\"  ,\n               \"type\"  :   \"Email\"  ,\n               \"placeholder\"  :   \"Enter your email address\"  ,\n               \"isRequired\"  :   true  ,\n               \"requiredMessage\"  :   \"We will never share your email with anyone else.\"\n           }\n       ]\n   }\n  Form field properties  Each form field supports different options. Unlike other blocks, a form field   rejects  a property its type does not support - you get a   Property \"x\" not available in form field type \"y\"  error rather than a silently ignored value. This table illustrates what options are available for which type:     Property  Required  Type  Description  Available for...  Default     description   string  Description of the field   all input types     isDescriptionEnabled   boolean  Whether the description is shown. Sending a   description  switches it on; sending   false  keeps the description stored but hidden   all input types  derived from   description    placeholder   string  Placeholder text  Name, Email, Phone, URL, Number, ShortText, LongText, Country, Dropdown     prefilledText   string  Prefilled value; setting it also switches prefilling on  Name, Email, Phone, URL, Number, ShortText, LongText     isPrefilledTextEnabled   boolean  Whether the prefilled value is used. Sending   false  keeps it stored but unused  Name, Email, Phone, URL, Number, ShortText, LongText  derived from   prefilledText    isRequired   boolean  Whether the field is required   all input types  false    requiredMessage   string  Message shown when the field is required but not filled   all input types     isHidden   boolean  Whether the field is hidden; useful in combination with the Riddle data layer  Name, Email, Phone, URL, Number, ShortText, LongText  false    regex   string  Regex to validate the field; setting it also switches advanced validation on  Name, Email, Phone, URL, ShortText     regexValidationMessage   string  Message shown when the regex validation fails  Name, Email, Phone, URL, ShortText     isAdvancedValidationEnabled   boolean  Whether the regex validation runs. Sending a   regex  switches it on; sending   false  keeps the regex stored but inactive  Name, Email, Phone, URL, ShortText, LongText  derived from   regex    checkboxText   string  Text shown next to the checkbox  Checkbox     starCount   integer  Number of rating stars to display; allowed range 0-10  Rating  5    maxLength   integer  Maximum number of characters accepted (>= 0)  Name, Number, ShortText, LongText  25    autocomplete   string  The browser autofill hint for this field, e.g.   email ,   given-name ,   tel ,   postal-code ,   off . Accepts the values of the HTML autocomplete spec  Name, Email, Phone, URL, Number, Country, ShortText, LongText     customWebhookId   string  Your own identifier for this field, sent along in webhooks and integrations   all input types     dateFormat   string   ddMMyyyy_dot ,   ddMMyyyy_slash ,   MMddyyyy_dot ,   MMddyyyy_slash ,   yyyy ,   MM , or   dd  DatePicker  ddMMyyyy_slash    datePickerType   string   Picker  (calendar overlay) or   Input  (typed input)  DatePicker  Input    timeFormat   string   HHmmss_colon ,   HHmm_colon , or   hhmma_colon  TimePicker  HHmm_colon    items   object   1-100 options, each an object with the option text as its   title  - see   item formats  Dropdown, RadioButtons     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original   all input types , Media  Settings  The three   is...Enabled  flags follow the general   feature toggle  rule: supplying the content switches the feature on, and an explicit flag always wins.  Two properties depend on another one:    requiredMessage  may only be set on a field that is also   isRequired: true  - otherwise the build fails.   regexValidationMessage  may only be set together with   regex .   Media ,   Content ,   Privacy  and   Captcha  are not input fields and have their own, separate property sets - see the sections below.  Adding radio buttons and dropdowns  The   RadioButtons  and   Dropdown  field types can be used to create a list of options. You can add as many options as you like in the   items  array, which follows the shared   item formats : an object per option, its text in   title . Unlike the surrounding   fields , an option needs no   type .   Note:  On the public API, the   fields  array of a   FormBuilder  block (and the   items  array of a   Dropdown  or   RadioButtons  field) is limited to a maximum of 100 entries.  Example   FormBuilder  object:     {\n       \"title\"  :   \"My form builder\"  ,\n       \"type\"  :   \"FormBuilder\"  ,\n       \"fields\"  : [\n           {\n               \"title\"  :   \"Your favorite color\"  ,\n               \"type\"  :   \"RadioButtons\"  ,\n               \"items\"  : [\n                   {   \"title\"  :   \"Red\"   },\n                   {   \"title\"  :   \"Green\"   },\n                   {   \"title\"  :   \"Blue\"   }\n               ]\n           },\n           {\n               \"title\"  :   \"Your favorite animal\"  ,\n               \"type\"  :   \"Dropdown\"  ,\n               \"items\"  : [\n                   {   \"title\"  :   \"Dog\"   },\n                   {   \"title\"  :   \"Cat\"   },\n                   {   \"title\"  :   \"Fish\"   }\n               ]\n           }\n       ]\n   }\n  An option object also takes a stable   id  of your own:     \"items\"  : [\n       {   \"id\"  :   10  ,   \"title\"  :   \"Red\"   },\n       {   \"id\"  :   20  ,   \"title\"  :   \"Green\"   }\n   ]\n  Learn more about setting custom ids   here .  Adding content and media fields  The   Content  and   Media  field types can be used to add additional information to your form.     Field  Property  Required  Type  Description  Default     Content   text  ✓  string  The rich text to display     Media   media  ✓  string|object  The image or video to display     Media   mediaOrientation   string  Set to   Settings ,   Wide ,   Square ,   Tall  or   Original  Settings  Example   FormBuilder  with   Content  and   Media  fields:     {\n       \"title\"  :   \"My form builder\"  ,\n       \"type\"  :   \"FormBuilder\"  ,\n       \"fields\"  : [\n           {\n               \"type\"  :   \"Content\"  ,\n               \"text\"  :   \"\u003Ch2>Welcome to the survey!\u003C/h2>\u003Cp>Please fill out the form below.\u003C/p>\"\n           },\n           {\n               \"type\"  :   \"Media\"  ,\n               \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n               \"mediaOrientation\"  :   \"Wide\"\n           }\n       ]\n   }\n   Note:  Neither field carries a   title  - a   Content  field is its   text  and a   Media  field is its   media . This is the one place in   fields  where   title  is not part of the field.  Adding a privacy / GDPR consent field  The   Privacy  field holds your privacy notice plus the two consent checkboxes a lead capture form needs to be legally usable in the EU. There are always exactly these two checkboxes - you cannot add your own.     Property  Required  Type  Description  Default     privacyText   string  Your privacy notice, shown above the checkboxes     requiredConsentForAddRiddleData   object  Consent to combining the visitor's Riddle answers with their form data  enabled    requiredConsentForTracking   object  Consent to the custom trackers configured for this Riddle  disabled    isLeadIdVisible   boolean  Whether the lead's unique ID is shown to them  false    isSaveByRiddleMessageVisible   boolean  Whether a \"your data has been saved\" confirmation is shown  false  Both consent objects take the same properties:     Property  Required  Type  Description  Default     isEnabled   boolean  Whether this checkbox is shown to the visitor at all     isRequired   boolean  Whether the visitor must tick it to submit     label   string  The question above the checkbox     description   string  Additional explanation     checkboxText   string  The text next to the checkbox itself      {\n       \"title\"  :   \"My form builder\"  ,\n       \"type\"  :   \"FormBuilder\"  ,\n       \"fields\"  : [\n           {   \"title\"  :   \"Your email\"  ,   \"type\"  :   \"Email\"   },\n           {\n               \"type\"  :   \"Privacy\"  ,\n               \"privacyText\"  :   \"\u003Cp>We store your email to send you the results. See our privacy policy.\u003C/p>\"  ,\n               \"requiredConsentForAddRiddleData\"  : {\n                   \"isEnabled\"  :   true  ,\n                   \"isRequired\"  :   true  ,\n                   \"label\"  :   \"\u003Cp>May we combine your answers with your email?\u003C/p>\"  ,\n                   \"checkboxText\"  :   \"\u003Cp>Yes, you may\u003C/p>\"\n               },\n               \"requiredConsentForTracking\"  : {\n                   \"isEnabled\"  :   false\n               }\n           }\n       ]\n   }\n  Double opt-in (DOI) confirmation is   not  part of this field - it is a Riddle-wide publish setting, see   publish settings .  Adding a captcha field     Property  Required  Type  Description  Default     captchaType   string   riddle  (Riddle's own question/answer challenge),   google  (reCAPTCHA), or   cloudflare  (Turnstile)  riddle    label   string  The challenge question -   riddle  type only     description   string  Additional explanation -   riddle  type only     key   string  The vendor's site key -   google /  cloudflare  only     secret   string  The vendor's secret key -   google /  cloudflare  only   A   google  or   cloudflare  captcha is rejected unless   both    key  and   secret  are set (empty strings do not count) - a vendor captcha cannot work without them.   Note:    secret  is write-only. It is never returned when you read a Riddle back as a build configuration, so a credential is not handed out to anyone who can read the Riddle's structure.   key  is returned - it is the public site key the widget renders into the page anyway. Because a read never returns the secret, re-sending a fetched configuration as an   edit  keeps the stored one; only a create has to supply it.     {\n       \"type\"  :   \"Captcha\"  ,\n       \"captchaType\"  :   \"cloudflare\"  ,\n       \"key\"  :   \"0x4AAA...\"  ,\n       \"secret\"  :   \"0x4AAA...\"\n   }\n  Adding single standalone form field blocks  If you want to add a single form field instead of a full form builder, you can do so by adding the respective form field type directly to the   blocks  array.     Property  Required  Type  Description  Default     type  ✓  string  Set to   FormField     title  ✓  string  The title of the form field     fieldType  ✓  string  The type of the form field, must be one of the   available form fields     description   string  The description of the form field     media   string|object  Media to display as part of the form field. Adding it automatically switches its display on     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    label   string  A label shown alongside the form field     isRequired   boolean  Whether the field is required  false  In addition to the common properties, each form field type supports the same options as described in the   Customizing form fields  section.  Embed an already published form  You can embed a form from your (personal) project by adding a block of the   FormSelect  type to the   blocks  array.  Properties  The form select block consists of:     Property  Required  Type  Description  Default     form  ✓  string  The UUID of the form you want to embed   The referenced Riddle must exist, must be of type   Form , and must be accessible to you - otherwise the build fails.  Example  The   FormSelect  block isolated:     {\n       \"type\"  :   \"FormSelect\"  ,\n       \"form\"  :   \"hQ3SYWur\"\n   }\n  Used in a poll build:     {\n       \"type\"  :   \"Poll\"  ,\n       \"build\"  : {\n           \"title\"  :   \"My new poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"The best noodles?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Spaghetti\"   },\n                       {   \"title\"  :   \"Fusilli\"   }\n                   ]\n               },\n               {\n                   \"type\"  :   \"FormSelect\"  ,\n                   \"form\"  :   \"hQ3SYWur\"\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thank you!\"  ,\n               \"description\"  :   \"We are happy to have you here\"\n           }\n       }\n   }\n  Referencing form fields later  Form fields are what   leaderboards  and   dynamic variables  refer back to. You can either reference a field by its label (e.g.   \"Your email\" ) or by the canonical field key that reading the Riddle back reports (e.g.   email1 ). You can also pin your own   id  on a field - see   custom IDs .  Full example  A complete Form request body with the standalone field blocks from this page built into it.     {\n       \"type\"  :   \"Form\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Form example (Builder API)\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"Your favorite animal\"  ,\n                   \"type\"  :   \"FormField\"  ,\n                   \"fieldType\"  :   \"Dropdown\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Dog\"   },\n                       {   \"title\"  :   \"Cat\"   },\n                       {   \"title\"  :   \"Fish\"   }\n                   ]\n               },\n               {\n                   \"title\"  :   \"Your email\"  ,\n                   \"type\"  :   \"FormField\"  ,\n                   \"fieldType\"  :   \"Email\"  ,\n                   \"placeholder\"  :   \"Enter your email address\"  ,\n                   \"isRequired\"  :   true  ,\n                   \"requiredMessage\"  :   \"We will never share your email with anyone else.\"\n               }\n           ]\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":171,"path":172,"dir":115,"title":173,"description":174,"keywords":175,"body":178},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:5.Personality.md","/api/build-riddles/riddle-types-and-other-blocks/personality","Create a Personality Test - Build Riddles","Learn how to build Personality Tests via API",[176,177,132,133,16],"Setting personalities","Add single/multiple choice questions","  Create Personality Test  When building a personality test you can add:    SingleChoice  and   MultipleChoice  questions   Form fields   General blocks  One result page  Setting personalities  For each personality test build configuration   you must define at least two personalities . This is done in the   personalities  property of the   build  object.   personalities  and   otherResults  follow the shared   item formats : an array of objects, the entry's text in its   title , plus the properties below.  Properties     Property  Required  Type  Description  Default     title  ✓  string  The title of the personality     description   string  The description of the personality     media   string|object  Media to display as part of the personality. Adding it automatically switches its display on. See   Use media     minScore   integer  Lower bound (0-100, in percent of the achievable score) of the window in which this personality wins     maxScore   integer  Upper bound (0-100) of that window     ctaButtonText   string  Label of a call-to-action button on this personality's result. Setting either CTA property switches the button on     ctaButtonURL   string  Target URL of that button     otherResults   object   Additional score bands shown when this personality is   not  the winning one; see below. The band's text is its   title  - see   item formats     areOtherResultsMediaEnabled   boolean  Whether the media of those other results is displayed  true    areOtherResultsEnabled   boolean  Whether the other results are shown at all. Sending   otherResults  switches it on; send   false  to keep them configured but hidden - see   feature toggles  derived from   otherResults    isIncludeCTAButtonEnabled   boolean  Whether the call-to-action button is shown at all. Sending either CTA property switches it on; send   false  to keep it configured but hidden  derived from the CTA properties  Other results per personality  Each entry of   otherResults  describes what a visitor sees for this personality when another one won:     Property  Required  Type  Description  Default     title  ✓  string  The title of this band     description   string  Its description     media   string|object  Media for this band. Adding it automatically switches its display on     minScore   integer  Lower bound (0-100) of the band     maxScore   integer  Upper bound (0-100) of the band     ctaButtonText   string  Label of a call-to-action button for this band     ctaButtonURL   string  Target URL of that button   Supplying   otherResults  replaces the two score bands a personality ships with by default.  Example  For the example let's add a SingleChoice question (which is described further in the next section):     {\n       \"type\"  :   \"Personality\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Introvert or extrovert?\"  ,\n           \"personalities\"  : [\n               {\n                   \"title\"  :   \"Introvert\"  ,\n                   \"description\"  :   \"Prefers solitary activities and quiet environments.\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/jpeg\"\n               },\n               {\n                   \"title\"  :   \"Extrovert\"  ,\n                   \"description\"  :   \"Enjoys socializing and being around others.\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/png\"\n               }\n           ],\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"Do you enjoy social gatherings?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {\n                           \"title\"  :   \"Yes\"  ,\n                           \"scores\"  : [  0  ,   1  ]\n                       },\n                       {\n                           \"title\"  :   \"No\"  ,\n                           \"scores\"  : [  1  ,   0  ]\n                       }\n                   ]\n               }\n           ]\n       }\n   }\n  Add single/multiple choice questions  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   SingleChoice  or   MultipleChoice     title  ✓  string  Title of the question     items  ✓  object   2-100 answer options, each an object with its   title  and its   scores  - see   item formats  and the specification below     description   string  The description of the question     media   string|object  Media to display as part of the question. Adding it automatically switches its display on     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    itemsShuffled   boolean  If set to   true , the order of the items/choices will be shuffled  false    layoutType   string  The layout of the items, either   Rows  or   Columns  Rows    canWrapItems   boolean  Whether items may wrap onto a new line  true    isHeightFlexible   boolean  Whether each item's height flexes with its content  true    maxSelections   integer   MultipleChoice  only: how many options may be picked at most (1-100)  2    hasUnlimitedSelections   boolean   MultipleChoice  only: lift the   maxSelections  cap entirely  true    areRemainingVotesVisible   boolean   MultipleChoice  only: show the user how many selections are left  true    isDescriptionVisible   boolean  Whether the per-answer descriptions are shown. One shared flag for the whole question, not one per answer: giving any item a   description  switches it on  derived from the items  Personality questions have no   isRequired  - they are always answered.  Example     {\n       \"title\"  :   \"Do you enjoy social gatherings?\"  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"items\"  : [\n           {\n               \"title\"  :   \"Yes\"  ,\n               \"scores\"  : [  0  ,   1  ]\n           },\n           {\n               \"title\"  :   \"No\"  ,\n               \"scores\"  : [  1  ,   0  ]\n           }\n       ]\n   }\n   items  follows the shared   item formats : an array of objects, the answer text in   title . What is specific here is   scores , which every answer needs. Each item object consists of:     Property  Required  Type  Description  Default     title  ✓  string  The answer text     scores  ✓  integer[]  An array of integers representing the score for each personality. The order of the scores must match the order of the personalities defined in the   personalities  array     description   string  The description of the item     media   string|object  Media to display as part of the item   Every item must carry   exactly as many scores as there are personalities , and each score must be an integer - a mismatch is rejected with a validation error. Setting an item   description  or   media  automatically switches the display of descriptions/media on for that question.   Note:  The   items  array of a   SingleChoice /  MultipleChoice  question and the   personalities  array are each limited to a maximum of 100 entries; a build may reference at most 15 media.   Editing the personalities later:  a   PUT  sending   personalities  merges them by   id , exactly like   blocks :\n  \"$create\": true  adds one,   \"$delete\": true  removes one - but their   order is not editable , there is no   $personalitiesOrder  (a new personality is appended at the end; reorder them in the Creator). The scores stored on the existing answers follow their personality by identity, so a personality that stays keeps its scores, an added one starts at   0  on every answer, and a deleted one takes its scores with it. See\n  Editing the personalities .  Result page  In a personality test only one result page is allowed which is specified in   build.result . Basic results have a   title  and   description  property.  Example in   build.result :     {\n       \"title\"  :   \"Thank you!\"  ,\n       \"description\"  :   \"We are happy to have you here\"\n   }\n   Tip:  The \"winning personality\" and \"other personalities\" are available as blocks in the result page (also used in the full example below). Use them along text, images, etc to create a more engaging result experience.   Learn more  Full example  Example with all available options:     {\n       \"type\"  :   \"Personality\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Personality example (Builder API)\"  ,\n           \"personalities\"  : [\n               {\n                   \"title\"  :   \"Pikachu\"  ,\n                   \"description\"  :   \"You are energetic and love to be around friends.\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/webp\"  ,\n                   \"minScore\"  :   51  ,\n                   \"maxScore\"  :   100  ,\n                   \"ctaButtonText\"  :   \"Meet Pikachu\"  ,\n                   \"ctaButtonURL\"  :   \"https://your-website.com/pikachu\"  ,\n                   \"areOtherResultsMediaEnabled\"  :   true  ,\n                   \"otherResults\"  : [\n                       {\n                           \"title\"  :   \"A little bit of Pikachu\"  ,\n                           \"description\"  :   \"You share some of Pikachu's energy.\"  ,\n                           \"media\"  :   \"https://httpbin.io/image/svg\"  ,\n                           \"minScore\"  :   0  ,\n                           \"maxScore\"  :   25\n                       },\n                       {\n                           \"title\"  :   \"Almost a Pikachu\"  ,\n                           \"description\"  :   \"You are nearly as energetic as Pikachu!\"  ,\n                           \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n                           \"minScore\"  :   25  ,\n                           \"maxScore\"  :   50  ,\n                           \"ctaButtonText\"  :   \"Meet Pikachu\"  ,\n                           \"ctaButtonURL\"  :   \"https://your-website.com/pikachu\"\n                       }\n                   ]\n               },\n               {\n                   \"title\"  :   \"Bulbasaur\"  ,\n                   \"description\"  :   \"You are calm and enjoy nature.\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/png\"  ,\n                   \"minScore\"  :   0  ,\n                   \"maxScore\"  :   50  ,\n                   \"ctaButtonText\"  :   \"Meet Bulbasaur\"  ,\n                   \"ctaButtonURL\"  :   \"https://your-website.com/bulbasaur\"\n               }\n           ],\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"Which vegetables do you like?\"  ,\n                   \"description\"  :   \"Pick up to two.\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/webp\"  ,\n                   \"mediaOrientation\"  :   \"Wide\"  ,\n                   \"type\"  :   \"MultipleChoice\"  ,\n                   \"itemsShuffled\"  :   true  ,\n                   \"layoutType\"  :   \"Columns\"  ,\n                   \"canWrapItems\"  :   true  ,\n                   \"isHeightFlexible\"  :   true  ,\n                   \"maxSelections\"  :   2  ,\n                   \"hasUnlimitedSelections\"  :   false  ,\n                   \"areRemainingVotesVisible\"  :   true  ,\n                   \"items\"  : [\n                       {\n                           \"title\"  :   \"Carrot\"  ,\n                           \"description\"  :   \"Crunchy and sweet\"  ,\n                           \"media\"  :   \"https://httpbin.io/image/svg\"  ,\n                           \"scores\"  : [\n                               0  ,\n                               1\n                           ]\n                       },\n                       {\n                           \"title\"  :   \"Broccoli\"  ,\n                           \"scores\"  : [\n                               1  ,\n                               0\n                           ]\n                       },\n                       {\n                           \"title\"  :   \"Spinach\"  ,\n                           \"scores\"  : [\n                               0  ,\n                               1\n                           ]\n                       }\n                   ]\n               },\n               {\n                   \"title\"  :   \"What is your favorite time of the day?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"layoutType\"  :   \"Rows\"  ,\n                   \"items\"  : [\n                       {\n                           \"title\"  :   \"Morning\"  ,\n                           \"scores\"  : [\n                               1  ,\n                               0\n                           ]\n                       },\n                       {\n                           \"title\"  :   \"Afternoon\"  ,\n                           \"scores\"  : [\n                               1  ,\n                               0\n                           ]\n                       },\n                       {\n                           \"title\"  :   \"Evening\"  ,\n                           \"scores\"  : [\n                               0  ,\n                               1\n                           ]\n                       }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"blocks\"  : [\n                   {\n                       \"type\"  :   \"WinningPersonality\"\n                   },\n                   {\n                       \"type\"  :   \"Text\"  ,\n                       \"text\"  :   \"\u003Ch2>Thank you for taking the test!\u003C/h2>\u003Cp>We hope you enjoyed finding out which pokemon matches your personality.\u003C/p>\"\n                   },\n                   {\n                       \"type\"  :   \"OtherPersonalities\"\n                   },\n                   {\n                       \"type\"  :   \"Share\"  ,\n                       \"label\"  :   \"Share this personality test!\"\n                   }\n               ]\n           }\n       }\n   }\n  Next steps  Now that you know the basics of building a personality test, you might want to learn how to:    Add form fields to your Riddle   Use the Ad block to monetize your Riddle or add Content blocks   Define the publish settings: Enable DOI, email automation, add integrations, and more   Define the preset and palette you want to use   Define the logic / flow of your Riddle   Build an advanced result page   Add media, such as images, videos, and social media content   Serve this Riddle through a Placeholder, so you can swap what an embed shows without changing the embed code  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":180,"path":181,"dir":115,"title":182,"description":183,"keywords":184,"body":187},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:6.Predictor.md","/api/build-riddles/riddle-types-and-other-blocks/predictor","Create Predictor - Build Riddles","Learn how to build Predictors via API",[185,186,132,133,16],"GuessTheScore / PickTheWinner","Scoring","  Create Predictor  When building a predictor you can add:   Predictor questions:   GuessTheScore  and   PickTheWinner   Form fields :   FormBuilder , standalone   FormField  blocks, or an embedded   FormSelect   General blocks :   Content ,   Quote , and   Ad  One result page  The scoring rules of the predictor, via   build.scoring  A predictor has   no custom logic tree  -   build.logic  is not available for this Riddle type. What a prediction is worth is configured through   build.scoring  instead (see below).  GuessTheScore / PickTheWinner  Both types describe the same thing - two parties and a prediction about them - but they are   not  configured identically:   PickTheWinner  (pick which of the two wins) supports a   description  and a draw option,   GuessTheScore  (guess the exact result) does not.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   GuessTheScore  or   PickTheWinner     title  ✓  string  The question title     items  ✓  object   Exactly   2  predictor items; see below - see   item formats     description   string   PickTheWinner  only: a description below the title     isDrawEnabled   boolean   PickTheWinner  only: whether a tie between the two items is a pickable outcome  true   Note:    items  must contain exactly 2 items - no more, no less - for both   GuessTheScore  and   PickTheWinner . A predictor item carries the name of its party in   title  and takes no   description  or   media  - its visuals are the properties below (see   item formats ).  Predictor questions have no general   media  - the visuals live on the two items (  backgroundImage ,   logo ).  Example:     {\n       \"title\"  :   \"Who will win?\"  ,\n       \"type\"  :   \"PickTheWinner\"  ,\n       \"items\"  : [\n           {\n               \"title\"  :   \"Team A\"\n           },\n           {\n               \"title\"  :   \"Team B\"\n           }\n       ]\n   }\n  The example above is very basic - if you want to go beyond that, each item in   items  supports:     Property  Required  Type  Description  Default     title  ✓  string  The name of this party, e.g. the team name     backgroundImage   string|object  Media shown as the background of the item; e.g. a stadium photo. See   Use media     logo   string|object  Media shown as the item's logo; e.g. the logo of a sports team     backgroundColor   string  Hex color of the item background  #1D2025    textColor   string  Hex color of the item text  #fff  Example with all optional properties set:     {\n       \"title\"  :   \"Who will win?\"  ,\n       \"type\"  :   \"PickTheWinner\"  ,\n       \"items\"  : [\n           {\n               \"title\"  :   \"Team A\"  ,\n               \"backgroundImage\"  :   \"https://httpbin.io/image/jpeg\"  ,\n               \"logo\"  :   \"https://httpbin.io/image/png\"  ,\n               \"backgroundColor\"  :   \"#FF0000\"  ,\n               \"textColor\"  :   \"#FFFFFF\"\n           },\n           {\n               \"title\"  :   \"Team B\"  ,\n               \"backgroundImage\"  :   \"https://httpbin.io/image/jpeg\"  ,\n               \"logo\"  :   \"https://httpbin.io/image/png\"  ,\n               \"backgroundColor\"  :   \"#0000FF\"  ,\n               \"textColor\"  :   \"#FFFFFF\"\n           }\n       ]\n   }\n   Note:    backgroundImage  and   backgroundColor  may be set together - they are layers, not alternatives: the   backgroundColor  renders as a semi-transparent tint over a grayscaled   backgroundImage . Set only   backgroundColor  for a flat colored item, or set both to tint a photo in your team's color.   Note:  Do not supply an   id  property for predictor items - IDs are automatically assigned as   0  and   1 . An   id  that already matches the item's position (  0  for the first,   1  for the second) is accepted, so a build config you read back via the API stays re-buildable; any other value is rejected.  Scoring   build.scoring  defines how many points a prediction earns. All four values are optional and must be integers of   0  or more:     Property  Required  Type  Description  Default     correct   integer  Points for an exactly correct prediction (the winner, or both scores, match)  30    tendency   integer  Points for calling only the winning side/tendency correctly  10    difference   integer   GuessTheScore : points when the guessed score margin matches, even if the exact scores do not  20    wrong   integer  Points for a prediction that is wrong outright  0  Example:     {\n       \"type\"  :   \"Predictor\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Predictor with custom scoring\"  ,\n           \"scoring\"  : {\n               \"correct\"  :   50  ,\n               \"tendency\"  :   20  ,\n               \"difference\"  :   30  ,\n               \"wrong\"  :   0\n           },\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"Who will win?\"  ,\n                   \"type\"  :   \"PickTheWinner\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Team A\"   },\n                       {   \"title\"  :   \"Team B\"   }\n                   ]\n               }\n           ]\n       }\n   }\n  Result page  In a predictor only one result page is allowed which is specified in   build.result . Basic results have a   title  and   description  property.  Example:     {\n       \"title\"  :   \"Thank you!\"  ,\n       \"description\"  :   \"We are happy to have you here\"\n   }\n  If you want to create complex result pages with texts, images, answered blocks, ...   click here to learn how to build advanced result pages .  Full example  Example with both question types + options, a general block and a form:     {\n       \"type\"  :   \"Predictor\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Predictor example (Builder API)\"  ,\n           \"scoring\"  : {\n               \"correct\"  :   30  ,\n               \"tendency\"  :   10  ,\n               \"difference\"  :   20  ,\n               \"wrong\"  :   0\n           },\n           \"blocks\"  : [\n               {\n                   \"type\"  :   \"Content\"  ,\n                   \"title\"  :   \"Predict this weekend's matches\"  ,\n                   \"description\"  :   \"The most accurate prediction wins.\"\n               },\n               {\n                   \"title\"  :   \"Who will win?\"  ,\n                   \"type\"  :   \"PickTheWinner\"  ,\n                   \"description\"  :   \"Pick the team you think takes the trophy.\"  ,\n                   \"isDrawEnabled\"  :   false  ,\n                   \"items\"  : [\n                       {\n                           \"title\"  :   \"Team A\"  ,\n                           \"backgroundImage\"  :   \"https://httpbin.io/image/jpeg\"  ,\n                           \"logo\"  :   \"https://httpbin.io/image/png\"  ,\n                           \"backgroundColor\"  :   \"#FF0000\"  ,\n                           \"textColor\"  :   \"#FFFFFF\"\n                       },\n                       {\n                           \"title\"  :   \"Team B\"  ,\n                           \"backgroundImage\"  :   \"https://httpbin.io/image/jpeg\"  ,\n                           \"logo\"  :   \"https://httpbin.io/image/webp\"  ,\n                           \"backgroundColor\"  :   \"#0000FF\"  ,\n                           \"textColor\"  :   \"#FFFFFF\"\n                       }\n                   ]\n               },\n               {\n                   \"title\"  :   \"What will be the score?\"  ,\n                   \"type\"  :   \"GuessTheScore\"  ,\n                   \"items\"  : [\n                       {\n                           \"title\"  :   \"Team A\"\n                       },\n                       {\n                           \"title\"  :   \"Team B\"\n                       }\n                   ]\n               },\n               {\n                   \"title\"  :   \"Where should we send your winnings?\"  ,\n                   \"type\"  :   \"FormBuilder\"  ,\n                   \"fields\"  : [\n                       {   \"title\"  :   \"Your name\"  ,   \"type\"  :   \"Name\"   },\n                       {\n                           \"title\"  :   \"Your email\"  ,\n                           \"type\"  :   \"Email\"  ,\n                           \"isRequired\"  :   true  ,\n                           \"requiredMessage\"  :   \"We need your email to notify you.\"\n                       }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thank you!\"  ,\n               \"description\"  :   \"We are happy to have you here\"\n           }\n       }\n   }\n   Note:  A predictor also accepts standalone   FormField  blocks, a   FormSelect , and the   Quote /  Ad  general blocks.   build.logic  is the one thing it does not support.  Next steps  Now that you know the basics of building a predictor, you might want to learn how to:    Add form fields to your Riddle   Use the Ad block to monetize your Riddle or add Content blocks   Define the publish settings: Enable DOI, email automation, add integrations, and more   Define the preset and palette you want to use   Build an advanced result page   Add media, such as images, videos, and social media content   Serve this Riddle through a Placeholder, so you can swap what an embed shows without changing the embed code  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":189,"path":190,"dir":115,"title":191,"description":192,"keywords":193,"body":198},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:7.Leaderboard.md","/api/build-riddles/riddle-types-and-other-blocks/leaderboard","Create and connect to Leaderboard - Build Riddles","Learn how to build Leaderboards and connect Riddles to existing leaderboards via API",[194,195,196,197,29,133],"1. Create a leaderboard","2. Connect a Riddle to an existing leaderboard","Fetch leaderboard entries","Unpublishing and deleting a leaderboard","  Create and connect to Leaderboard  Leaderboards enable you to create more engaging and interactive content with little to zero maintenance, e.g. a weekly quiz with a ranking, or a Predictor for every match of your sports team.  There are   two separate things  you can do, and they use two different parts of the build configuration:     What you want to do  Riddle type you build  Where it is configured    Create a new leaderboard   Leaderboard  the   build  object itself - see   Create a leaderboard   Make a Quiz/Predictor/Minigame report to an existing leaderboard   Quiz ,   Predictor ,   Minigame   build.leaderboard.connections  - see   Connect a Riddle  Both can be combined: create the leaderboard first, then reference its UUID in the Riddles you build afterwards.  1. Create a leaderboard  A leaderboard is a Riddle type of its own, but a very reduced one: it has   no    blocks , no   logic , no   publish  settings and no result page. The properties below are everything a leaderboard build config can express.  Build properties     Property  Required  Type  Description  Default     title  ✓  string  The title of the leaderboard     riddleConnections   string   UUIDs of the Riddles that should report to this leaderboard right away; maximum: 10     preset   object   Preset settings  of the leaderboard; this is where every display setting of the leaderboard lives - see below    Note:  A leaderboard's own display settings - the podium colors and the email verification requirement - are keys of the    preset  object , not build properties of their own.   isEmailValidationRequired ,   color1st ,   color2nd  and   color3rd  are no longer accepted at the top level of   build ; send them as   preset.isEmailVerificationEnabled  and   preset.color1st /  color2nd /  color3rd  instead. That is also exactly how a read-back reports them, so a fetched configuration can be sent back unchanged. Sent at the top level they are now an unknown property: silently ignored in a plain create, and rejected with a   400  under    strictProperties  or when   editing  a leaderboard.   Note:    riddleConnections  is not create-only.    PUT /riddle-builder/{UUID}  accepts it on an existing leaderboard to add or drop connected Riddles at any time - it   replaces  the whole list, so resend every UUID you want to keep together with any new ones.   Note:  Every UUID in   riddleConnections  must be an existing   Quiz ,   Predictor  or   Minigame  that already has a   Name  and an   Email  field - the same requirements as connecting from the other side, described in section 2.  Leaderboard preset settings  On top of the   shared preset settings  (  preset /  presetId ,   palette ,   language ,   ads ,   customStrings ,   footerText ,   footerBranding ,   isRiddleFooterVisible ,   isShareButtonVisible ), a leaderboard's   preset  accepts:     Property  Required  Type  Description  Default     isCompactView   boolean  Whether entries are rendered in the compact, single-line view  false    entriesAbove   integer  How many entries are shown above the visitor's own entry  1    entriesBelow   integer  How many entries are shown below the visitor's own entry  3    isTotalEntriesEnabled   boolean  Whether the total number of entries is displayed  false    isOneVotePerIdentifierEnabled   boolean  Whether every identifier (e.g. email address) may only appear once  false    isBadwordFilterEnabled   boolean  Whether nicknames are run through the bad-word filter  false    badwordFilterCustomList   string  Additional comma-separated words to filter     quizTimeMultiplier   integer  0-100; how strongly the time a visitor needed influences the ranking  0    isEmailVerificationEnabled   boolean  Whether visitors have to confirm their email address before their entry appears on the leaderboard. It is never switched on for you, so send it explicitly whenever only confirmed participants should be ranked  false    color1st   string  CSS color of the first-place row on the podium  #D38807    color2nd   string  CSS color of the second-place row on the podium  #A9A9A9    color3rd   string  CSS color of the third-place row on the podium  #C2691C  The three podium colors are independent of each other: sending one leaves the other two at whatever the leaderboard already shows. A read-back only reports the ones that differ from the defaults above - the rest are listed in   omittedDefaults , like every other property still at its default.  Example  The smallest possible leaderboard - a title and nothing else:     {\n       \"type\"  :   \"Leaderboard\"  ,\n       \"build\"  : {\n           \"title\"  :   \"My leaderboard\"\n       }\n   }\n  A leaderboard that two existing Riddles report to right away, with email verification switched on:     {\n       \"type\"  :   \"Leaderboard\"  ,\n       \"build\"  : {\n           \"title\"  :   \"My leaderboard\"  ,\n           \"riddleConnections\"  : [  \"SampleUUID1\"  ,   \"SampleUUID2\"  ],\n           \"preset\"  : {\n               \"isEmailVerificationEnabled\"  :   true\n           }\n       }\n   }\n  Example  Every property a leaderboard build config accepts, including the leaderboard-specific   preset  settings:     {\n       \"type\"  :   \"Leaderboard\"  ,\n       \"project\"  :   123  ,\n       \"publish\"  :   true  ,\n       \"build\"  : {\n           \"title\"  :   \"Season leaderboard\"  ,\n           \"riddleConnections\"  : [  \"SampleUUID1\"  ,   \"SampleUUID2\"  ],\n           \"preset\"  : {\n               \"language\"  :   \"en\"  ,\n               \"isEmailVerificationEnabled\"  :   true  ,\n               \"color1st\"  :   \"#ffd700\"  ,\n               \"color2nd\"  :   \"#c0c0c0\"  ,\n               \"color3rd\"  :   \"#cd7f32\"  ,\n               \"isCompactView\"  :   false  ,\n               \"entriesAbove\"  :   2  ,\n               \"entriesBelow\"  :   5  ,\n               \"isTotalEntriesEnabled\"  :   true  ,\n               \"isOneVotePerIdentifierEnabled\"  :   true  ,\n               \"isBadwordFilterEnabled\"  :   true  ,\n               \"badwordFilterCustomList\"  :   \"spam,troll\"  ,\n               \"quizTimeMultiplier\"  :   20\n           }\n       }\n   }\n  Replace   SampleUUID1 /  SampleUUID2  with UUIDs of Riddles that exist in the same project - or leave   riddleConnections  out entirely to create an empty leaderboard and connect Riddles to it later, as described next.  2. Connect a Riddle to an existing leaderboard  Connections are configured in   build.leaderboard  of the   Riddle  you build, not of the leaderboard.  Requirements   Only   quizzes, predictors and minigames  can be connected - they are the only types that produce a ranking. Polls, personality tests, forms and stories cannot.  The Riddle needs a   Name  and an   Email  field (see   form fields ), or an explicit   nickname /  identifier  mapping.  A minigame consisting of   nothing but  a   WheelSpinner  block cannot be connected - a wheel only produces a win/loss outcome, not a rankable score. Add another minigame block (e.g. a   Sudoku ).  Connecting   multiple  Riddles to a single leaderboard requires our   Enterprise  subscription.  Connection properties     Property  Required  Type  Description  Default     connections  ✓  string   1-3 UUIDs of the leaderboards this Riddle reports to. Duplicate UUIDs are collapsed into one connection     identifier   string  Which field identifies the visitor; overrides auto-detection. Must be an   Email  field     nickname   string  Which field provides the displayed name; overrides auto-detection. Must be a   Name  field or a data layer variable   Example  With no   identifier /  nickname  given, the first   Email  field becomes the identifier and the first   Name  field the nickname:     {\n       \"type\"  :   \"Quiz\"  ,\n       \"build\"  : {\n           \"title\"  :   \"My quiz\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"What's the capital of Germany?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Leipzig\"  ,   \"isCorrect\"  :   false   }\n                   ]\n               },\n               {\n                   \"title\"  :   \"My form\"  ,\n                   \"type\"  :   \"FormBuilder\"  ,\n                   \"fields\"  : [\n                       {   \"title\"  :   \"Your email\"  ,   \"type\"  :   \"Email\"   },\n                       {   \"title\"  :   \"Your name\"  ,   \"type\"  :   \"Name\"   }\n                   ]\n               }\n           ],\n           \"leaderboard\"  : {\n               \"connections\"  : [  \"Fw5uSygx\"  ]\n           }\n       }\n   }\n  Identifier and nickname fields  Auto-detection is only right as long as there is exactly one obvious candidate. Map the fields explicitly whenever your form holds several email or text fields, or when the value should come from the data layer instead of a visible field.  Both properties accept three input forms:     Input form  Example  When to use it    The field   label   \"Your email\"  Matched case-insensitively, ignoring surrounding whitespace   The   canonical field key   \"email1\" ,   \"email2\" ,   \"name1\"  The field type in lowercase plus its position among the fields of that type (  email2  = second   Email  field). This is exactly what the API emits when you read the Riddle back, so a fetched build config can be sent back unchanged   A   data layer variable   \"dataLayer:customerId\"  The value is passed in when the Riddle is opened rather than typed by the visitor  Example with both mapped explicitly - the second email field identifies the visitor, and the second name field provides the displayed name:     {\n       \"type\"  :   \"Quiz\"  ,\n       \"build\"  : {\n           \"title\"  :   \"My quiz\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"What's the capital of Germany?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Leipzig\"  ,   \"isCorrect\"  :   false   }\n                   ]\n               },\n               {\n                   \"title\"  :   \"My form\"  ,\n                   \"type\"  :   \"FormBuilder\"  ,\n                   \"fields\"  : [\n                       {   \"title\"  :   \"Your private email\"  ,   \"type\"  :   \"Email\"   },\n                       {   \"title\"  :   \"Your work email\"  ,   \"type\"  :   \"Email\"   },\n                       {   \"title\"  :   \"Your real name\"  ,   \"type\"  :   \"Name\"   },\n                       {   \"title\"  :   \"Your display name\"  ,   \"type\"  :   \"Name\"   }\n                   ]\n               }\n           ],\n           \"leaderboard\"  : {\n               \"connections\"  : [  \"Fw5uSygx\"  ],\n               \"identifier\"  :   \"Your work email\"  ,\n               \"nickname\"  :   \"Your display name\"\n           }\n       }\n   }\n  The exact same mapping by canonical key - and a   nickname  taken from the data layer instead of a visible field:     {\n       \"leaderboard\"  : {\n           \"connections\"  : [  \"Fw5uSygx\"  ],\n           \"identifier\"  :   \"email2\"  ,\n           \"nickname\"  :   \"dataLayer:customerName\"\n       }\n   }\n  Rules:    identifier  must point at an   Email  field,   nickname  at a   Name  field (or, for   nickname , at a data layer variable). Any other field type - a   ShortText , for example - is rejected, naming the allowed types.  If a label is shared by more than one eligible field, the request is rejected as ambiguous and lists the candidate keys - use one of those canonical keys instead.   identifier  and   nickname  cannot resolve to the same field.  If both resolve to form fields (i.e. neither is a   dataLayer:  variable), they must live on the   same    FormBuilder  block.  A nickname is mandatory: without a   Name  field and without an explicit   nickname , the connection is rejected.  Connecting to a leaderboard that has email verification enabled (  preset.isEmailVerificationEnabled , see section 1) requires an identifier - either an   Email  field in the Riddle or an explicit   identifier .   Tip:  To show the leaderboard on the result page and to fully engage the user, add the   Leaderboard  block to the result page.   Click here  to learn more.  Fetch leaderboard entries  To read the entries of a leaderboard, e.g. to display them in your own frontend or to determine the winners of a contest, use the   /riddle-leaderboard/entries/{UUID}  API endpoint.     Property  Required  Type  Description  Default     page  ✓  integer  The page you want to return     limit   integer  How many results the page should contain (maximum: 50)  50    search   string  Search term; exact match for an email address, or partial match for a nickname   Example payload:     {\n       \"page\"  :   1  ,\n       \"limit\"  :   50\n   }\n  Unpublishing and deleting a leaderboard  A leaderboard with active Riddle connections   cannot be unpublished  - the connected Riddles depend on it, and you will get an   UNPUBLISH_CONFLICTING_INTERDEPENDENCE_LEADERBOARD  validation error. For the same reason, a connected Riddle cannot be deleted while the leaderboard still points at it.  To get rid of such a leaderboard,   delete  it instead: deleting a leaderboard is always allowed and cleans up the connected Riddles automatically. Unpublishing becomes possible once the connections themselves are gone.  Troubleshooting  Make sure that..   the leaderboard UUID is correct  the leaderboard is in the same project as the Riddle you are creating  you have added a   FormBuilder  with a   Name  and an   Email  field to your Riddle  when you want to connect multiple Riddles: you are   subscribed to our Enterprise plan  Full example  A quiz connected to the published leaderboard   Fw5uSygx , with the identifier and nickname fields mapped explicitly because the form holds two email fields.     {\n       \"type\"  :   \"Quiz\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Season quiz\"  ,\n           \"blocks\"  : [\n               {\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"title\"  :   \"What's the capital of Germany?\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Leipzig\"  ,   \"isCorrect\"  :   false   }\n                   ]\n               },\n               {\n                   \"type\"  :   \"FormBuilder\"  ,\n                   \"title\"  :   \"Enter the ranking\"  ,\n                   \"fields\"  : [\n                       {   \"title\"  :   \"Your email\"  ,   \"type\"  :   \"Email\"   },\n                       {   \"title\"  :   \"Work email\"  ,   \"type\"  :   \"Email\"   },\n                       {   \"title\"  :   \"Your name\"  ,   \"type\"  :   \"Name\"   }\n                   ]\n               }\n           ],\n           \"leaderboard\"  : {\n               \"connections\"  : [  \"Fw5uSygx\"  ],\n               \"identifier\"  :   \"Your email\"  ,\n               \"nickname\"  :   \"Your name\"\n           },\n           \"results\"  : [\n               {\n                   \"minPercentage\"  :   0  ,\n                   \"maxPercentage\"  :   100  ,\n                   \"title\"  :   \"Thanks for playing!\"\n               }\n           ]\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":200,"path":201,"dir":115,"title":202,"description":203,"keywords":204,"body":208},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:8.Minigame.md","/api/build-riddles/riddle-types-and-other-blocks/minigame","Create Minigame - Build Riddles","Learn how to build Minigames via API",[205,206,207,132,133,16],"Adding a SlotMachine","Adding a WheelSpinner","Adding a Sudoku","  Create Minigame  When building a minigame you can add:   A   SlotMachine  block  A   WheelSpinner  block (also called   Wheel of fortune )  A   Sudoku  block   Form fields :   FormBuilder , standalone   FormField  blocks, or an embedded   FormSelect   General blocks :   Content ,   Quote , and   Ad  One result page  Other minigames you may know from the Creator (e.g. Crosswords or Minesweeper) cannot be built through the API yet - only the three block types below are accepted.  Adding a SlotMachine  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   SlotMachine     title  ✓  string  The title of the slot machine     description   string  The description of the slot machine     media   string|object  Media to display as part of the block. See   Use media     startBalance   integer  The starting balance of the user  10    winningProbability   string  Set to   Low ,   Medium  or   High  Medium    winTitle   string  Title of the message shown once the player lands a winning combination     winDescription   string  Description of that win message     winMedia   string|object  Media of that win message     hasCustomSymbolsEnabled   boolean  Whether custom reel symbols are rendered instead of the default emoji  false    customSymbols   object   Up 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 .     Property  Required  Type  Description  Default     symbolKey  ✓  string  Which symbol to replace:   :recycle: ,   :cherries: ,   :lemon: ,   :grapes: ,   :bell: , or   :dollar:     media  ✓  string|object  The 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     {\n       \"title\"  :   \"Spin the slot machine\"  ,\n       \"description\"  :   \"Try your luck!\"  ,\n       \"type\"  :   \"SlotMachine\"  ,\n       \"startBalance\"  :   1000  ,\n       \"winningProbability\"  :   \"High\"  ,\n       \"winTitle\"  :   \"Jackpot!\"  ,\n       \"winDescription\"  :   \"You won a 20% voucher.\"  ,\n       \"customSymbols\"  : [\n           {\n               \"symbolKey\"  :   \":cherries:\"  ,\n               \"media\"  :   \"https://httpbin.io/image/jpeg\"\n           }\n       ]\n   }\n  Adding a WheelSpinner  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   WheelSpinner     title  ✓  string  The title of the wheel spinner     items  ✓  object   The items on the wheel, 2-30; see   WheelSpinnerItem  properties below - see   item formats     description   string  The description of the wheel spinner     media   string|object  Media to display as part of the block     isMediaVisible   boolean  Whether the items' own media renders on the wheel segments  false    areEmojisEnabled   boolean  Whether emoji are rendered on the wheel segments  false    isCopyToClipboardButtonEnabled   boolean  Whether the result offers a \"copy to clipboard\" button for the awarded item, e.g. a discount code  true  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     Property  Required  Type  Description  Default     type  ✓  string  Set to either   Win ,   Loss , or   FreeSpin     title  ✓  string  The title of the item     percent  ✓  integer  The percentage of the wheel this item takes up; 0-100     award  required if   type  is   Win  string  The award the user gets, e.g. a voucher code     backgroundColor   string  The background color of the item  rgba(255, 255, 255, 1)    textColor   string  The text color of the item  rgba(0, 0, 0, 1)    media   string|object  Media 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     {\n       \"title\"  :   \"Spin the wheel\"  ,\n       \"description\"  :   \"Try your luck!\"  ,\n       \"type\"  :   \"WheelSpinner\"  ,\n       \"items\"  : [\n           {\n               \"title\"  :   \"Win 100$\"  ,\n               \"type\"  :   \"Win\"  ,\n               \"percent\"  :   50  ,\n               \"award\"  :   \"100$\"\n           },\n           {\n               \"title\"  :   \"Lose 50$\"  ,\n               \"type\"  :   \"Loss\"  ,\n               \"percent\"  :   30  ,\n               \"award\"  :   \"-50$\"\n           },\n           {\n               \"title\"  :   \"Free spin\"  ,\n               \"type\"  :   \"FreeSpin\"  ,\n               \"percent\"  :   20  ,\n               \"award\"  :   \"Free spin\"\n           }\n       ]\n   }\n  Adding a Sudoku  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Sudoku     title  ✓  string  The title of the sudoku block     description   string  The description of the sudoku block     media   string|object  Media to display as part of the block. Adding it automatically switches its display on     mediaOrientation   string  How it is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    difficulty   integer  The difficulty level of the sudoku; 0-100  50    areRulesVisible   boolean  Whether the rules are visible to the user  true    isConflictHighlightingAllowed   boolean  Whether conflict highlighting is allowed  false    isGuessCheckingAllowed   boolean  Whether guess checking is allowed  false    refreshInterval   string  The interval in which the sudoku automatically refreshes; set to a value of:   None ,   Hourly ,   Daily ,   Weekly , or   Monthly  None    score   integer  Points awarded for solving the puzzle  1    successMessage   string  Message shown once the puzzle is solved. Setting a non-empty message switches the success message on; an empty string switches it off     isSuccessMessageEnabled   boolean  Whether the success message is shown. Sending   false  keeps the message stored but hidden. See   feature toggles  derived from   successMessage    successMessageMedia   string|object  Media of that success message     isSuccessMessageMediaEnabled   boolean  Whether the success message's own media is displayed  false  The puzzle itself is generated for you from   difficulty  - you cannot supply a grid or a solution.  Example     {\n       \"title\"  :   \"Sudoku Challenge\"  ,\n       \"description\"  :   \"Solve the puzzle!\"  ,\n       \"type\"  :   \"Sudoku\"  ,\n       \"difficulty\"  :   70  ,\n       \"areRulesVisible\"  :   true  ,\n       \"isConflictHighlightingAllowed\"  :   true  ,\n       \"isGuessCheckingAllowed\"  :   true  ,\n       \"refreshInterval\"  :   \"Weekly\"\n   }\n  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:     {\n       \"title\"  :   \"Thank you!\"  ,\n       \"description\"  :   \"Thanks for playing\"\n   }\n  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:     {\n       \"type\"  :   \"Minigame\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Minigame example (Builder API)\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"Spin the slot machine\"  ,\n                   \"description\"  :   \"Try your luck!\"  ,\n                   \"type\"  :   \"SlotMachine\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n                   \"startBalance\"  :   1000  ,\n                   \"winningProbability\"  :   \"High\"  ,\n                   \"winTitle\"  :   \"Jackpot!\"  ,\n                   \"winDescription\"  :   \"You won a 20% voucher.\"  ,\n                   \"winMedia\"  :   \"https://httpbin.io/image/png\"  ,\n                   \"customSymbols\"  : [\n                       {\n                           \"symbolKey\"  :   \":cherries:\"  ,\n                           \"media\"  :   \"https://httpbin.io/image/webp\"\n                       },\n                       {\n                           \"symbolKey\"  :   \":bell:\"  ,\n                           \"media\"  :   \"https://httpbin.io/image/svg\"\n                       }\n                   ]\n               },\n               {\n                   \"title\"  :   \"Spin the wheel\"  ,\n                   \"description\"  :   \"Try your luck!\"  ,\n                   \"type\"  :   \"WheelSpinner\"  ,\n                   \"isCopyToClipboardButtonEnabled\"  :   true  ,\n                   \"areEmojisEnabled\"  :   false  ,\n                   \"isMediaVisible\"  :   false  ,\n                   \"items\"  : [\n                       {\n                           \"title\"  :   \"Win 100$\"  ,\n                           \"type\"  :   \"Win\"  ,\n                           \"percent\"  :   50  ,\n                           \"award\"  :   \"100$\"  ,\n                           \"backgroundColor\"  :   \"rgba(89, 225, 171, 1)\"  ,\n                           \"textColor\"  :   \"rgba(0, 0, 0, 1)\"\n                       },\n                       {\n                           \"title\"  :   \"Lose 50$\"  ,\n                           \"type\"  :   \"Loss\"  ,\n                           \"percent\"  :   30  ,\n                           \"backgroundColor\"  :   \"rgba(0, 0, 0, 1)\"  ,\n                           \"textColor\"  :   \"rgba(255, 255, 255, 1)\"\n                       },\n                       {\n                           \"title\"  :   \"Free spin\"  ,\n                           \"type\"  :   \"FreeSpin\"  ,\n                           \"percent\"  :   20\n                       }\n                   ]\n               },\n               {\n                   \"title\"  :   \"Sudoku Challenge\"  ,\n                   \"description\"  :   \"Solve the puzzle!\"  ,\n                   \"type\"  :   \"Sudoku\"  ,\n                   \"difficulty\"  :   70  ,\n                   \"areRulesVisible\"  :   true  ,\n                   \"isConflictHighlightingAllowed\"  :   true  ,\n                   \"isGuessCheckingAllowed\"  :   true  ,\n                   \"refreshInterval\"  :   \"Weekly\"  ,\n                   \"score\"  :   5  ,\n                   \"successMessage\"  :   \"Well done - you solved it!\"\n               },\n               {\n                   \"title\"  :   \"Where should we send your prize?\"  ,\n                   \"type\"  :   \"FormBuilder\"  ,\n                   \"fields\"  : [\n                       {   \"title\"  :   \"Your name\"  ,   \"type\"  :   \"Name\"   },\n                       {\n                           \"title\"  :   \"Your email\"  ,\n                           \"type\"  :   \"Email\"  ,\n                           \"isRequired\"  :   true  ,\n                           \"requiredMessage\"  :   \"We need your email to send you the prize.\"\n                       }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thanks for playing!\"  ,\n               \"description\"  :   \"We hope you had fun.\"\n           }\n       }\n   }\n  Next steps  Now that you know the basics of building a minigame, you might want to learn how to:    Add form fields to your Riddle   Use the Ad block to monetize your Riddle or add Content blocks   Define the publish settings: Enable DOI, email automation, add integrations, and more   Define the preset and palette you want to use   Build an advanced result page   Add media, such as images, videos, and social media content   Serve this Riddle through a Placeholder, so you can swap what an embed shows without changing the embed code  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":210,"path":211,"dir":115,"title":212,"description":213,"keywords":214,"body":217},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:9.Story.md","/api/build-riddles/riddle-types-and-other-blocks/story","Create Story - Build Riddles","Learn how to build Stories via API",[215,216,132,133,16],"Logic","Interactive Graphic Block","  Create Story  A Story is Riddle's long-form format - quiz meets blog post: a rich text story with images, videos and embeds. Building one via the API works just like a Form: general content blocks plus form fields, with no questions, personalities, or scoring.  When building a story you can add:    General blocks :   Content ,   Quote , and   Ad  The   InteractiveGraphic  block, see   below   Form fields : a   FormBuilder  block with many fields, single standalone   FormField  blocks, or an embedded   FormSelect  One optional result page  Optional   logic  A story has no question blocks -   SingleChoice ,   Order , and the other question types of the other Riddle types are not available here, and so there is no scoring and no leaderboard support either.  Logic  A   logic  tree is accepted for a Story, but since there are no answer-bearing blocks to branch on, only linear flow control (moving from one block to the next, or ending early) is meaningful here - see   logic settings  for the general syntax.  Interactive Graphic Block  The   InteractiveGraphic  block shows an image with clickable hotspots on it - a floor plan, a map, an infographic or a product shot. Every hotspot can open an info pop-up, link to a URL, continue the Riddle or jump to another image of the same block.  A block holds one or more images (  images ), and every image holds its hotspots (  hotspots ). Both are arrays of objects (see   item formats ); neither an image nor a hotspot carries a   title  - each is described by its own properties below.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   InteractiveGraphic     images  ✓  object   The graphic images of this block (at least one); see below - see   item formats     title   string  The title of the block     description   string  The description of the block     hotspotBackgroundColor   string  Hex color of the hotspot pins  #1a1a64    hotspotTextColor   string  Hex color of the hotspot pins' text  #ffffff    isHotspotNumbersEnabled   boolean  Whether the hotspots are numbered   1..n , in the order they appear in   hotspots . Areas are numbered too, in the same sequence as the pins  false    isHotspotMediaEnabled   boolean  Whether the images inside the hotspot pop-ups are displayed. Giving any hotspot a   media  switches this on; sending   false  keeps those images stored but hidden. See   feature toggles  true    hotspotMediaOrientation   string  How the pop-up media is cropped:   Wide ,   Square ,   Tall , or   Original  Wide   Note:  This block has no   media  of its own - its first graphic image is what a share preview uses.  Images  Every entry of   images  is an object:     Property  Required  Type  Description  Default     media  ✓  string|object  The background image the hotspots are placed on. See   Use media     label   string  Names the image in the Creator and in the hotspot's \"jump to image\" list. It is never shown to your visitors     hotspots  ✓  object   The clickable hotspots on this image; see below. At least one is required - an image with none is a picture nobody can interact with. See   item formats    Note:    media  and at least one   hotspots  entry are required when you create an image - an image without media renders as an empty canvas, whether it is the block's first image or one a hotspot jumps to, while its hotspots still show. When you edit an existing image the media is already stored, so you only resend it if you want to change it.  Hotspots  Every entry of an image's   hotspots  is an object. Its   action  decides what a click does - and which of the other properties are accepted at all: sending one that does not belong to the chosen action is rejected rather than ignored.     Property  Required  Type  Description  Default     x   number  Horizontal position of the hotspot's center, in percent of the image (  0 -  100 , decimals allowed)  50    y   number  Vertical position of the hotspot's center, in percent of the image (  0 -  100 , decimals allowed)  50    action   string   showInfo ,   openUrl ,   goToNextBlock ,   noAction , or   goToImage:\u003CimageId>  showInfo    label   string  Names the hotspot in the Creator; it is never shown to your visitors     title   string  Headline of the info pop-up (  showInfo  only)     description   string  Text of the info pop-up (  showInfo  only)     media   string|object  Image of the info pop-up (  showInfo  only)     ctaLabel   string  Label of the pop-up's call-to-action button (  showInfo  only)     ctaUrl   URL  Target of the pop-up's call-to-action button (  showInfo  only)     actionUrl   URL  The URL to open (  openUrl  only)     displayType   string   dot  for a pin,   area  for a clickable region covering part of the image  dot    areaShape   string   circle  or   rectangle  (  area  only)  circle    areaWidth   number  Width of the region, in percent of the image (  4 -  100 ) (  area  only)  16    areaHeight   number  Height of the region, in percent of the image (  4 -  100 ) (  area  only)  16    areaSize   number  Sets both   areaWidth  and   areaHeight  at once, in percent of the image (  4 -  100 ) (  area  only)  16   Note:  An   area  hotspot has no pin, but it is not invisible - its region is shaded faintly over the image, and it takes part in the numbering like any other hotspot. The whole region reacts to a click, not just its centre.   Note:    areaWidth ,   areaHeight  and   areaSize  accept values up to   100 , but the Riddle is rendered with anything above   80  shown as   80  - so   80  is the effective maximum region size.  One hotspot per action  The table above is long because it covers five actions at once. In practice a single hotspot only ever uses the handful of properties that belong to its own   action  - here is each of them on its own.    showInfo  - open a pop-up.  The default action, and the only one that uses   title ,   description ,   media ,   ctaLabel  and   ctaUrl . At its smallest it is a pin with a headline and a text:     {\n       \"x\"  :   25.5  ,\n       \"y\"  :   40  ,\n       \"title\"  :   \"Kitchen\"  ,\n       \"description\"  :   \"Where the coffee lives.\"\n   }\n  The same pop-up with an image and a button below it:     {\n       \"x\"  :   25.5  ,\n       \"y\"  :   40  ,\n       \"action\"  :   \"showInfo\"  ,\n       \"title\"  :   \"Kitchen\"  ,\n       \"description\"  :   \"Where the coffee lives.\"  ,\n       \"media\"  :   \"https://httpbin.io/image/png\"  ,\n       \"ctaLabel\"  :   \"Read more\"  ,\n       \"ctaUrl\"  :   \"https://www.riddle.com/help\"\n   }\n  The button only appears when both   ctaLabel  and   ctaUrl  are set, and   media  is shown only while the block's   isHotspotMediaEnabled  is on - sending any hotspot a   media  switches it on for you.    openUrl  - leave for a URL.  No pop-up, so there is nothing to write into   title  or   description ; the target goes into   actionUrl , not into   ctaUrl :     {\n       \"x\"  :   80  ,\n       \"y\"  :   12  ,\n       \"action\"  :   \"openUrl\"  ,\n       \"actionUrl\"  :   \"https://www.riddle.com\"\n   }\n    goToImage:\u003Ctarget>  - jump to another image of the same block.  Name the target by its   label  or by its   id ; see   connecting images  for the rules:     {\n       \"x\"  :   50  ,\n       \"y\"  :   90  ,\n       \"label\"  :   \"Up to the first floor\"  ,\n       \"action\"  :   \"goToImage:First floor\"\n   }\n    goToNextBlock  - continue the Riddle.  The click ends the block, exactly as the continue button would:     {\n       \"x\"  :   92  ,\n       \"y\"  :   92  ,\n       \"action\"  :   \"goToNextBlock\"\n   }\n    noAction  - a marker that does nothing.  Useful with   isHotspotNumbersEnabled  to number a feature of the image without offering anything to open:     {\n       \"x\"  :   60  ,\n       \"y\"  :   30  ,\n       \"action\"  :   \"noAction\"\n   }\n  Areas instead of pins   displayType  is independent of the action: every one of the five can be a   dot  pin or an   area  covering part of the image. A circular area over the top-left quarter, sized with the shorthand   areaSize :     {\n       \"x\"  :   25  ,\n       \"y\"  :   25  ,\n       \"action\"  :   \"showInfo\"  ,\n       \"title\"  :   \"The lobby\"  ,\n       \"displayType\"  :   \"area\"  ,\n       \"areaSize\"  :   30\n   }\n  A rectangle needs its two sides separately, because   areaWidth  is a percentage of the image's width and   areaHeight  one of its height:     {\n       \"x\"  :   50  ,\n       \"y\"  :   85  ,\n       \"action\"  :   \"openUrl\"  ,\n       \"actionUrl\"  :   \"https://www.riddle.com\"  ,\n       \"displayType\"  :   \"area\"  ,\n       \"areaShape\"  :   \"rectangle\"  ,\n       \"areaWidth\"  :   60  ,\n       \"areaHeight\"  :   12.5\n   }\n   x /  y  stay the   centre  of the region in both cases, so this last hotspot is a banner across the lower part of the image, running from 20% to 80% horizontally and from 78.75% to 91.25% vertically.  How big a hotspot is, and how far apart to place them  The coordinates alone do not tell you how much of the image a hotspot covers, so here are the numbers you need to place them without overlapping:   A   dot  pin is   12 px  across, or   20 px  when   isHotspotNumbersEnabled  is on. That is a fixed size in the player, not a share of the image - so how much of the picture a pin covers depends on how wide your Riddle is rendered, not on   x /  y .  Its   click target is much larger than the pin  - roughly 24 px of margin all around - so a click next to a pin still opens it.  Two   dot  hotspots that end up   closer than 40 px  to each other, on both axes, are merged into a single cluster marker the visitor has to click to separate. Keep them about   48 px  apart to stay separate: at a 600 px wide Riddle that is roughly   6.7%  of the image (about   8%  with that margin), half as much at 1200 px, twice as much at 300 px. There is no percentage that holds at every width.   area  hotspots are never clustered, and overlapping hotspots are never moved apart for you - placing two on the same spot simply stacks them.   areaWidth  and   areaHeight  are percentages of the image's width and height   respectively . So   circle  with different values - or with equal values on an image that is not square - draws an   ellipse , not a circle.  Area sizes are accepted up to   100 , but the player renders at most   80 , so treat   80 as the practical maximum .  Connecting images  A   goToImage:\u003Ctarget>  action jumps to another image of the same block, which lets you build a drill-down: an overview image whose hotspots open detail images.  You can name the target image in two ways:   By its    id  - either the one you assigned yourself in   images , or the one returned when you read the Riddle back.  By its    label  - an exact match on the   label  you gave that image. This is the easier one when you are creating the images and the connection in the same request, because you do not need to invent or look up any ids: label the images and link   \"action\": \"goToImage:Ground floor\" .  IDs are matched first, and a label only if no image has that ID, so a label that happens to look like a number can never take precedence over a real ID. If two images of the block carry the label you point at, the request is rejected as ambiguous - use the ID, or make the labels unique.  A label is a convenience for writing only: what gets stored, and what you get back when you read the Riddle, is always   goToImage:\u003Cid> .  Three rules apply:   A hotspot cannot link to the image it sits on.  A connection is a single hop: an image that is the target of a connection cannot link on to a third image.  An image that a hotspot still links to cannot be deleted - see   Editing  below.  Building this block with an AI agent  This is the one block type whose result you cannot judge from the build configuration. A hotspot's   x /  y  and an area's   areaWidth /  areaHeight  only mean something in relation to the pixels of your image - whether a hotspot actually sits on the door, the product or the city it describes is not visible in the JSON. An agent that only writes JSON is placing coordinates blind, and the hotspots will end up in the wrong places.  So if you let an AI agent build this block, use one that can   open a URL in a browser and see the rendered page  (vision/screenshots). Then build it in a loop instead of in one shot:    Create once : send the block with the images and a first estimate of the hotspots.   Publish : a published Riddle is what the browser shows, so an unpublished edit is invisible.   Look at it : open the Riddle, look at the screenshot, and check every hotspot against the feature it is meant to mark. Open the pop-ups and click the   goToImage:  hotspots too.   Edit only what is off : correct the   x /  y  or the area size of the individual hotspots that missed, addressed by their   id .   Publish and look again , and repeat until it is right.  Do not delete and re-create the block between rounds: the   id  of every image and hotspot is what makes step 4 a two-line request instead of a full resend.  Editing   images  and each image's   hotspots  are addressed by their   id  when you edit a Riddle, so you can change one hotspot without resending the rest - and a   goToImage:  connection survives an edit that does not mention the image it points at. See   Editing Riddles .  Both levels can be reordered with the usual order marker, and neither order is merely cosmetic - the first image is the one the block opens on, and the hotspot numbers follow the order of the   hotspots  array:     {\n       \"blocks\"  : [\n           {\n               \"id\"  :   3  ,\n               \"$imagesOrder\"  : [  2  ,   1  ],\n               \"images\"  : [\n                   {   \"id\"  :   1  ,   \"$hotspotsOrder\"  : [  2  ,   1  ] }\n               ]\n           }\n       ]\n   }\n  Like every order marker, each one has to list   every  id of the collection it orders, exactly once - a partial list is rejected rather than guessed at.  Deleting an image that a hotspot still links to is rejected, so an edit cannot leave a connection pointing at nothing. The error names the image you deleted and the hotspots that still point at it - repoint or delete those hotspots in the same request. Deleting the image that   carries  the hotspot is always fine: the hotspot goes away with its own image.  Example     {\n       \"type\"  :   \"InteractiveGraphic\"  ,\n       \"title\"  :   \"Our office\"  ,\n       \"description\"  :   \"Click around to explore.\"  ,\n       \"isHotspotNumbersEnabled\"  :   true  ,\n       \"images\"  : [\n           {\n               \"label\"  :   \"Ground floor\"  ,\n               \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n               \"hotspots\"  : [\n                   {\n                       \"label\"  :   \"The kitchen\"  ,\n                       \"x\"  :   25.5  ,\n                       \"y\"  :   40  ,\n                       \"action\"  :   \"showInfo\"  ,\n                       \"title\"  :   \"Kitchen\"  ,\n                       \"description\"  :   \"Where the coffee lives.\"  ,\n                       \"media\"  :   \"https://httpbin.io/image/png\"  ,\n                       \"ctaLabel\"  :   \"Read more\"  ,\n                       \"ctaUrl\"  :   \"https://www.riddle.com\"\n                   },\n                   {\n                       \"label\"  :   \"Our website\"  ,\n                       \"x\"  :   80  ,\n                       \"y\"  :   12  ,\n                       \"action\"  :   \"openUrl\"  ,\n                       \"actionUrl\"  :   \"https://www.riddle.com\"  ,\n                       \"displayType\"  :   \"area\"  ,\n                       \"areaShape\"  :   \"rectangle\"  ,\n                       \"areaWidth\"  :   30  ,\n                       \"areaHeight\"  :   12.5\n                   },\n                   {\n                       \"label\"  :   \"Up to the first floor\"  ,\n                       \"x\"  :   50  ,\n                       \"y\"  :   90  ,\n                       \"action\"  :   \"goToImage:First floor\"\n                   }\n               ]\n           },\n           {\n               \"label\"  :   \"First floor\"  ,\n               \"media\"  :   \"https://httpbin.io/image/png\"\n           }\n       ]\n   }\n  A full Story containing this block is at the   end of this page .  Result page  In a story only one result page is allowed which is specified in   build.result , and it is entirely optional. Basic results only consist of a   title  and   description  property.  Example:     {\n       \"title\"  :   \"Thanks for reading!\"  ,\n       \"description\"  :   \"We hope you enjoyed the story\"\n   }\n  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 the block types a story accepts:   Content ,   Quote ,   InteractiveGraphic  and   Ad  blocks plus a form.     {\n       \"type\"  :   \"Story\"  ,\n       \"build\"  : {\n           \"title\"  :   \"A day in the life\"  ,\n           \"blocks\"  : [\n               {\n                   \"type\"  :   \"Content\"  ,\n                   \"title\"  :   \"It all started on a Monday morning...\"  ,\n                   \"description\"  :   \"A story about a very ordinary day\"  ,\n                   \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n                   \"mediaOrientation\"  :   \"Tall\"\n               },\n               {\n                   \"type\"  :   \"Quote\"  ,\n                   \"title\"  :   \"A word of inspiration\"  ,\n                   \"quoteText\"  :   \"The only way to do great work is to love what you do.\"  ,\n                   \"quoteAuthor\"  :   \"Steve Jobs\"  ,\n                   \"quoteMedia\"  :   \"https://httpbin.io/image/png\"  ,\n                   \"quoteTextColor\"  :   \"#ffffff\"  ,\n                   \"quoteBackgroundColor\"  :   \"#000000\"\n               },\n               {\n                   \"type\"  :   \"InteractiveGraphic\"  ,\n                   \"title\"  :   \"Where it all happened\"  ,\n                   \"description\"  :   \"Click around to explore the office.\"  ,\n                   \"isHotspotNumbersEnabled\"  :   true  ,\n                   \"hotspotBackgroundColor\"  :   \"#1a1a64\"  ,\n                   \"hotspotTextColor\"  :   \"#ffffff\"  ,\n                   \"hotspotMediaOrientation\"  :   \"Square\"  ,\n                   \"images\"  : [\n                       {\n                           \"label\"  :   \"Ground floor\"  ,\n                           \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n                           \"hotspots\"  : [\n                               {\n                                   \"label\"  :   \"The kitchen\"  ,\n                                   \"x\"  :   25.5  ,\n                                   \"y\"  :   40  ,\n                                   \"action\"  :   \"showInfo\"  ,\n                                   \"title\"  :   \"Kitchen\"  ,\n                                   \"description\"  :   \"Where the coffee lives.\"  ,\n                                   \"media\"  :   \"https://httpbin.io/image/png\"  ,\n                                   \"ctaLabel\"  :   \"Read more\"  ,\n                                   \"ctaUrl\"  :   \"https://www.riddle.com\"\n                               },\n                               {\n                                   \"label\"  :   \"The reception desk\"  ,\n                                   \"x\"  :   80  ,\n                                   \"y\"  :   12  ,\n                                   \"action\"  :   \"openUrl\"  ,\n                                   \"actionUrl\"  :   \"https://www.riddle.com\"  ,\n                                   \"displayType\"  :   \"area\"  ,\n                                   \"areaShape\"  :   \"rectangle\"  ,\n                                   \"areaWidth\"  :   30  ,\n                                   \"areaHeight\"  :   12.5\n                               },\n                               {\n                                   \"label\"  :   \"Up to the first floor\"  ,\n                                   \"x\"  :   50  ,\n                                   \"y\"  :   90  ,\n                                   \"action\"  :   \"goToImage:First floor\"\n                               }\n                           ]\n                       },\n                       {\n                           \"label\"  :   \"First floor\"  ,\n                           \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n                           \"hotspots\"  : [\n                               {\n                                   \"label\"  :   \"The meeting room\"  ,\n                                   \"x\"  :   60  ,\n                                   \"y\"  :   55  ,\n                                   \"action\"  :   \"showInfo\"  ,\n                                   \"title\"  :   \"Meeting room\"  ,\n                                   \"description\"  :   \"Where the Monday morning started.\"\n                               },\n                               {\n                                   \"label\"  :   \"On with the story\"  ,\n                                   \"x\"  :   50  ,\n                                   \"y\"  :   92  ,\n                                   \"action\"  :   \"goToNextBlock\"\n                               }\n                           ]\n                       }\n                   ]\n               },\n               {\n                   \"type\"  :   \"Ad\"  ,\n                   \"iframe\"  : {\n                       \"url\"  :   \"https://ads.your-website.com/ad.html\"  ,\n                       \"height\"  :   250\n                   },\n                   \"showNextButtonDelay\"  :   3\n               },\n               {\n                   \"title\"  :   \"Want updates on the next story?\"  ,\n                   \"type\"  :   \"FormBuilder\"  ,\n                   \"fields\"  : [\n                       {\n                           \"title\"  :   \"Your email\"  ,\n                           \"type\"  :   \"Email\"  ,\n                           \"isRequired\"  :   true  ,\n                           \"requiredMessage\"  :   \"We need your email to keep you posted.\"\n                       }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thanks for reading!\"  ,\n               \"description\"  :   \"We hope you enjoyed the story\"\n           }\n       }\n   }\n  Next steps  Now that you know the basics of building a story, you might want to learn how to:    Add form fields to your Riddle   Use the Ad block to monetize your Riddle or add Content blocks   Define the publish settings: Enable DOI, email automation, add integrations, and more   Define the preset and palette you want to use   Define the logic / flow of your Riddle   Build an advanced result page   Add media, such as images, videos, and social media content   Serve this Riddle through a Placeholder, so you can swap what an embed shows without changing the embed code  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":219,"path":220,"dir":115,"title":221,"description":222,"keywords":223,"body":227},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:10.Placeholder.md","/api/build-riddles/riddle-types-and-other-blocks/placeholder","Placeholder - Build Riddles","Learn how to build a Placeholder Riddle via API",[224,225,226,133,16],"Build configuration","Conditions","Reading a Placeholder back","  Building a Placeholder  A Placeholder is a Riddle with   no content of its own . It holds a routing rule that is read every time the embed is requested, deciding which   other  Riddle to show in its place. Embed the Placeholder once, and swap what visitors see by changing the rule.   Note:  The Placeholder feature has to be enabled for your account - otherwise building one is rejected with   Placeholder riddles are not enabled.  Build configuration     Property  Required  Type  Description  Default     title  ✓  string  The title of the Placeholder     riddleId   string  The   fallback : the UUID of the Riddle to show when no condition matches     conditions   array  The routing rules, evaluated before the fallback; up to 100. See below     preset   object  The   preset settings     publish   object  The   publish settings   A Placeholder has no   blocks , no   result /  results , no   logic  and no   leaderboards  - there is nothing in it to answer, and its conditions pick a   target Riddle  rather than branch inside one.  The fallback is optional and stays meaningful when left out: a Placeholder with no fallback and no matching condition resolves to nothing at all. In an   edit ,   \"riddleId\": null  clears it.   Note:  An edit may not take away the   last  routing target. A Placeholder routes through exactly two things - the fallback   riddleId  and the   conditions  list - so an edit whose result would have neither is rejected with   \"This edit would leave the Placeholder with no fallback \"riddleId\" and no \"conditions\" at all, which makes it unable to display any Riddle.\"  and nothing is written. That covers both ways of getting there: clearing the fallback of a Placeholder that has no conditions, and sending   \"conditions\": []  on one that has no fallback. Keep at least one of the two - clear the fallback   and  send the conditions that replace it in the same edit.  This guards only that   transition , not the state itself:    Creating  a Placeholder with neither target is still allowed - that is the empty shell the Creator's own \"new Placeholder\" flow starts from, and how one is created before its targets are known.  A Placeholder that already has no target stays editable, so renaming one is never blocked by a target it never had.   Expired conditions count as targets.  A condition whose window has passed is kept on the Placeholder (see   The stored order is not your order ), so removing the fallback of a Placeholder whose only conditions are expired is accepted - whether an expired window resolves to anything at request time is decided when the embed is requested.  Any target - the fallback and every condition's   riddleId  - has to be an existing Riddle of your own account or team. A Placeholder cannot route to   itself , and not to   another Placeholder : chaining is not supported.     {\n       \"type\"  :   \"Placeholder\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Homepage slot\"  ,\n           \"riddleId\"  :   \"abcdef12\"\n       }\n   }\n  Conditions  Each condition targets   either  one specific Riddle   or  a tag, and may be limited to a time window. They are checked in order and the first match wins; if none matches, the fallback   riddleId  is used.     Property  Required  Type  Description  Default     riddleId  either  string  The UUID of the Riddle to show     tag  either  string|integer  A tag name or tag ID - the Riddle to show is picked from the Riddles carrying that tag     tagMode  with   tag  string   lastPublished  (the most recently published Riddle with that tag) or   random     randomRefreshIntervalSeconds   integer  How often a   random  pick is re-drawn, in seconds. Only allowed with   \"tagMode\": \"random\"     from   string  Start of a date window, e.g.   2026-09-01 00:00:00     to   string  End of that date window. Omit it for an open-ended one     dailyFrom   string  Start of a daily time-of-day window, as   HH:MM:SS     dailyTo   string  End of that daily window   Exactly one target per condition: sending   riddleId    and    tag  is rejected, and so is sending neither.   tagMode  is required for a   tag  condition and rejected on a   riddleId  one.  A tag has to   already exist  in the Riddle's own scope (its team's tags, or your personal ones). A tag that cannot be found is an error - a condition never creates one, so a typo is reported instead of silently defining an empty tag.  Time windows  A condition carries   either  a date window (  from , optionally   to )   or  a daily window (  dailyFrom  and   dailyTo , always together) - mixing the two on one condition is rejected. A condition with no window always matches whenever it is reached, which is how you express \"everything else lands here\".     {\n       \"type\"  :   \"Placeholder\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Homepage slot\"  ,\n           \"riddleId\"  :   \"abcdef12\"  ,\n           \"conditions\"  : [\n               {\n                   \"riddleId\"  :   \"12abcdef\"  ,\n                   \"from\"  :   \"2026-12-24 00:00:00\"  ,\n                   \"to\"  :   \"2026-12-26 23:59:59\"\n               },\n               {\n                   \"tag\"  :   \"evergreen\"  ,\n                   \"tagMode\"  :   \"random\"  ,\n                   \"randomRefreshIntervalSeconds\"  :   3600  ,\n                   \"dailyFrom\"  :   \"18:00:00\"  ,\n                   \"dailyTo\"  :   \"23:59:59\"\n               },\n               {\n                   \"tag\"  :   \"daily-quiz\"  ,\n                   \"tagMode\"  :   \"lastPublished\"\n               }\n           ]\n       }\n   }\n  In spoken form: over Christmas show one specific Riddle; on every other day between 18:00 and midnight show a random one tagged   evergreen ; at all other times show the most recently published Riddle tagged   daily-quiz ; and if none of that resolves to a Riddle, show the fallback   abcdef12 .  The condition without a window is written   last  on purpose: it matches whenever it is reached, so anything after it would never be evaluated.  The stored order is not your order  Conditions are normalized on every build and edit, exactly as they are in the Creator: the list is re-sorted by its own priority rules and overlapping windows are trimmed. Reading the Placeholder back with    GET /riddle-builder/{UUID}  can therefore return the conditions in a different order, or with narrower windows, than you sent. Sending that result back is stable - it just is not literal.  Because a stored condition has no ID of its own,   conditions  is   replaced as a whole  by an edit: resend every condition you want to keep. For the same reason the list cannot be reordered with a marker - the order you send is the input to the normalization above. Sending   \"conditions\": []  therefore removes all of them, which is only accepted while the Placeholder keeps a fallback   riddleId  - see   the build configuration  above.  Reading a Placeholder back  A target that has meanwhile been deleted, or turned into a Placeholder itself, can no longer be expressed. Such a condition - or the fallback - is left out of the returned build config and reported in   warnings  instead, naming exactly which one and why.  Full example  A Placeholder with all three kinds of routing in one build config: a specific Riddle over Christmas, a random one tagged   evergreen  in the evenings, the most recently published one tagged   daily-quiz  at all other times, and   abcdef12  as the fallback.     {\n       \"type\"  :   \"Placeholder\"  ,\n       \"project\"  :   123  ,\n       \"publish\"  :   true  ,\n       \"build\"  : {\n           \"title\"  :   \"Homepage slot\"  ,\n           \"riddleId\"  :   \"abcdef12\"  ,\n           \"conditions\"  : [\n               {\n                   \"riddleId\"  :   \"12abcdef\"  ,\n                   \"from\"  :   \"2026-12-24 00:00:00\"  ,\n                   \"to\"  :   \"2026-12-26 23:59:59\"\n               },\n               {\n                   \"tag\"  :   \"evergreen\"  ,\n                   \"tagMode\"  :   \"random\"  ,\n                   \"randomRefreshIntervalSeconds\"  :   3600  ,\n                   \"dailyFrom\"  :   \"18:00:00\"  ,\n                   \"dailyTo\"  :   \"23:59:59\"\n               },\n               {\n                   \"tag\"  :   \"daily-quiz\"  ,\n                   \"tagMode\"  :   \"lastPublished\"\n               }\n           ]\n       }\n   }\n  Next steps  Now that you know how a Placeholder routes, you might want to learn how to:    Build the Riddles it routes to: quiz ,   poll ,   personality ,   form ,   minigame ,   story , or   predictor   Tag those Riddles, so a condition can pick them by tag   Re-route the Placeholder later by editing its conditions   Get the embed code you place once and never touch again   Define the preset and palette you want to use   Define the publish settings   Handle exceptions  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":229,"path":230,"dir":115,"title":231,"description":232,"keywords":233,"body":237},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:11.General blocks.md","/api/build-riddles/riddle-types-and-other-blocks/general-blocks","General blocks - Build Riddles","Learn how to build ad slots, content blocks and more via API",[234,235,236,133],"Content/Text Block","Ad Block","Quote Block","  General blocks  The blocks on this page can be added to any build type, hence considered \"general\".  Content/Text Block  The   Content  block is a simple block that can be used to display a title and description. It can be used as an introduction to the quiz (= cover block) or as a conclusion.  Properties     Property  Required  Type  Description  Default     title  ✓  string  The title of the content block     description   string  The description of the content block     media   string|object  Media to display. Adding it automatically switches its display on. See   Use media     mediaOrientation   string  How it is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings  Example:     {\n       \"type\"  :   \"Content\"  ,\n       \"title\"  :   \"Welcome to the quiz\"  ,\n       \"description\"  :   \"This quiz will test your knowledge about the world\"\n   }\n  Ad Block  In the ad block it is optional to add a   title  and   description .  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Ad     title   string  The title of the ad block     description   string  The description of the ad block     media   string|object  Media to display alongside the ad. Adding it automatically switches its display on     mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    projectSlot   object  An ad slot of your project; see below     iframe   object  A custom iframe ad; see below     isNextButtonVisible   boolean  Whether a \"next\" button is shown so the visitor can continue  true    showNextButtonDelay   integer  How many seconds to wait before that button appears  5    isShowNextButtonAfterDelayEnabled   boolean  Whether that delay applies at all. Sending a   showNextButtonDelay  greater than   0  switches it on; sending   false  keeps the delay stored but shows the button right away. See   feature toggles  derived from   showNextButtonDelay  Adding ad blocks is possible in two ways:   By using   project ad slots  By implementing a custom iframe  Project ad slots  To add an ad to your build using a project ad slot, you need to add the property   projectSlot  in the   Ad  block, consisting of:     Property  Required  Type  Description  Default     slotId  ✓  integer  The ad slot to use     variables   Object  An object with key-value pairs to override ad slot variables    Note:    projectSlot  and   iframe  are mutually exclusive; you cannot set both on the same   Ad  block.  Example:     {\n       \"type\"  :   \"Ad\"  ,\n       \"projectSlot\"  : {\n           \"slotId\"  :   123456\n       }\n   }\n  Example with variables:     {\n       \"type\"  :   \"Ad\"  ,\n       \"projectSlot\"  : {\n           \"slotId\"  :   123456  ,\n           \"variables\"  : {\n               \"ad-variable-key1\"  :   \"override-value1\"\n           }\n       }\n   }\n  Custom iframe  To be more flexible with ads and to be more independent from the Riddle Creator, you can add an   Ad  block with the   iframe  object set, consisting of:     Property  Required  Type  Description  Default     url  ✓  URL  The URL the iframe should link to     height   integer  The height of the iframe in px; automatic resizing does not work with custom iframes  80  Example:     {\n       \"type\"  :   \"Ad\"  ,\n       \"iframe\"  : {\n           \"url\"  :   \"https://ads.your-website.com/ad.html\"  ,\n           \"height\"  :   250\n       }\n   }\n  Quote Block  The   Quote  block can be used to display a quote with a author.  Properties  The quote block consists of:     Property  Required  Type  Description  Default     type  ✓  string  Set to   Quote     title  ✓  string  The title of the quote block     quoteText  ✓  string  The quote text     quoteAuthor  ✓  string  The author of the quote     description   string  The description of the quote block     media   string  A media URL to an image to display as the general image     quoteMedia   string|object  Media to display as the quote image     quoteTextColor   string  Hex color of the quote text  #ffffff    quoteBackgroundColor   string  Hex color behind the quote  #000000    mediaOrientation   string   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings  Example     {\n       \"type\"  :   \"Quote\"  ,\n       \"title\"  :   \"Inspiring Quote\"  ,\n       \"description\"  :   \"A quote to inspire you\"  ,\n       \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n       \"quoteText\"  :   \"The only limit to our realization of tomorrow is our doubts of today.\"  ,\n       \"quoteAuthor\"  :   \"Franklin D. Roosevelt\"  ,\n       \"quoteMedia\"  :   \"https://httpbin.io/image/png\"\n   }\n  Full example  For this example we build a quiz with a content + ad block.     {\n       \"type\"  :   \"Quiz\"  ,\n       \"build\"  : {\n           \"title\"  :   \"General blocks example (Builder API)\"  ,\n           \"blocks\"  : [\n               {\n                   \"type\"  :   \"Content\"  ,\n                   \"title\"  :   \"Welcome to the quiz\"  ,\n                   \"description\"  :   \"This quiz will test your knowledge about France\"\n               },\n               {\n                   \"type\"  :   \"MultipleChoice\"  ,\n                   \"title\"  :   \"What is the capital of France?\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   false   }\n                   ]\n               },\n               {\n                   \"type\"  :   \"Ad\"  ,\n                   \"iframe\"  : {\n                       \"url\"  :   \"https://google.com\"\n                   }\n               },\n               {\n                   \"type\"  :   \"MultipleChoice\"  ,\n                   \"title\"  :   \"How do you say 'hello' in French?\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Bonjour\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"Hallo\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Ciao\"  ,   \"isCorrect\"  :   false   }\n                   ]\n               },\n               {\n                   \"type\"  :   \"Quote\"  ,\n                   \"title\"  :   \"Inspiring Quote\"  ,\n                   \"quoteText\"  :   \"The only limit to our realization of tomorrow is our doubts of today.\"  ,\n                   \"quoteAuthor\"  :   \"Franklin D. Roosevelt\"\n               }\n           ]\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":239,"path":240,"dir":115,"title":241,"description":242,"keywords":243,"body":259},"content:15.Api:4.Build Riddles:3.Riddle types and other blocks:12.Result Pages.md","/api/build-riddles/riddle-types-and-other-blocks/result-pages","Result pages - Build Riddles","Learn how to build result pages via API",[244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,133],"Redirect to a URL","Advanced result pages","Add user's score","Add text","Add button","Add share to social block","Add answered blocks","Add image","Add leaderboard","Add popular choices","Add winning personality","Add other personalities","Add attributes","Add recommended content","Offset any block with margins","  Result pages  A result page is built one of   two mutually exclusive ways  - you pick one per result object:    Simple : send   title  (required) and, optionally,   description  on the   result  (or, for a quiz, each entry of   results ) object.   Complex : send a   blocks  array instead - see   Advanced result pages  below. As soon as you send   blocks ,   title /  description  are no longer accepted on that same object, since the page's content now comes entirely from the blocks.  Sending   title /  description  together with   blocks  on the same result object is rejected - here for the   result  of a Poll:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION\"  ,\n       \"message\"  :   \"Poll result:   \\\"  title  \\\"   is not a supported property here. Supported: blocks.\"\n   }\n   Note:  This rejection is part of the strict key validation, which is always active when you   edit an existing Riddle  and opt-in via   strictProperties  when you create one. Without it, the   title  is silently dropped instead - the result page still comes out as a complex one built from your   blocks .   Note:  For quiz results,   minPercentage /  maxPercentage  are required either way - they define the score range a result applies to and are independent of which of the two shapes above you choose for its content.  For quiz (simple result pages):     {\n       \"blocks\"  : [  ...  ],\n       \"results\"  : [\n           {\n               \"minPercentage\"  :   0  ,\n               \"maxPercentage\"  :   50  ,\n               \"title\"  :   \"Bad result\"  ,\n               \"description\"  :   \"You answered less than 50% of the questions correctly\"\n           },\n           {\n               \"minPercentage\"  :   51  ,\n               \"maxPercentage\"  :   100  ,\n               \"title\"  :   \"Good result\"  ,\n               \"description\"  :   \"You answered more than 50% of the questions correctly\"\n           }\n       ]\n   }\n  For any other Riddle type (simple result page):     {\n       \"blocks\"  : [  ...  ],\n       \"result\"  : {\n           \"title\"  :   \"Thank you!\"  ,\n           \"description\"  :   \"We are happy to have you here\"\n       }\n   }\n  A quiz has one result   per score range : every entry of   results  needs a   minPercentage  (0-100) and a   maxPercentage  (1-100). Every other Riddle type has exactly one result, given as the single   result  object.   title  is required on a simple result page;   description  is optional.  This default (simple) result page   always  consists of:   Your given title and description  A block which allows the user to share the result on different social networks  Additionally it may contain:   For quiz: a block which shows the user how many questions they answered correctly  For personality: a block which shows the user information about their winning personality and other personalities (if available)  In most cases this should suffice - if you want to create result URL redirects or advanced result pages   similar to the functionality in the Creator , keep reading.  Redirect to a URL  If you want to redirect the user to a URL after they have completed the Riddle, you can do this by adding a   redirectUrl  property to the   result  object.     {\n       \"blocks\"  : [  ...  ],\n       \"result\"  : {\n           \"redirectUrl\"  :   \"https://www.riddle.com\"\n       }\n   }\n  This will redirect the user to   https://www.riddle.com  after they have completed the Riddle.   Note:  This result redirecting works for Poll, Quiz, Form, Predictor, and Minigame Riddles. Personality tests and leaderboards do not support it.  Optional properties  There are several options you can choose from when adding a result redirect:     Property  Required  Type  Description  Default     delay   integer  The delay in seconds before the redirect happens  0    isDelayEnabled   boolean  Whether the delay applies at all. A   delay  greater than   0  switches it on; sending   false  keeps the delay stored but redirects immediately. See   feature toggles  derived from   delay    title   string  The title of the result page. This will be displayed in the browser tab     description   string  The description of the result page. This will be displayed in the browser tab     media   string|object  The media shown on the result page. Adding it automatically switches its display on. See   Use media     mediaOrientation   string  How it is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings    openFullscreen   boolean  If   true  the redirect leaves the embed and opens in the parent window instead of inside the Riddle  true   Note:  Only with the   delay  property will the user actually see the title and description.   Note:  For Quiz Riddles, redirects are defined per result inside the   results  array. In this case   minPercentage  and   maxPercentage  are additionally required to define the score range for which this redirect applies.  Example:     {\n       \"blocks\"  : [  ...  ],\n       \"result\"  : {\n           \"redirectUrl\"  :   \"https://www.riddle.com\"  ,\n           \"delay\"  :   5  ,\n           \"title\"  :   \"Thank you!\"  ,\n           \"description\"  :   \"We are happy to have you here\"  ,\n           \"openFullscreen\"  :   false\n       }\n   }\n  Advanced result pages  You can create advanced result pages with texts, images, answered blocks, and more via the API's result builder. See the   result page  documentation to see how this works in the Creator.  Similar to the Riddle's blocks the result page is also structured in blocks.   blocks  is an array of objects (see   item formats ) - every block needs at least its   type . You can add up to 10 blocks to the result page. To do this send a   blocks  array in the   result  object   instead of , not in addition to, a   title  and   description  property - the two are mutually exclusive, see above.  For poll (or any type which only has one result):     {\n       \"blocks\"  : [  ...  ],\n       \"result\"  : {\n           \"blocks\"  : [\n               {\n                   \"type\"  :   \"Text\"  ,\n                   \"text\"  :   \"This is my result page text!\"\n               },\n               ...\n           ]\n       }\n   }\n  For quiz:     {\n       \"blocks\"  : [  ...  ],\n       \"results\"  : [\n           {\n               \"minPercentage\"  :   0  ,\n               \"maxPercentage\"  :   50  ,\n               \"blocks\"  : [\n                   {\n                       \"type\"  :   \"Text\"  ,\n                       \"text\"  :   \"Bad result\"\n                   },\n                   ...\n               ]\n           },\n           {\n               \"minPercentage\"  :   51  ,\n               \"maxPercentage\"  :   100  ,\n               \"blocks\"  : [\n                   {\n                       \"type\"  :   \"Text\"  ,\n                       \"text\"  :   \"Good result\"\n                   },\n                   ...\n               ]\n           }\n       ]\n   }\n  Every result page block consists of a   type  property and additional properties depending on the block type. For example here is the content for the button block   only with required options :     {\n       \"type\"  :   \"Button\"  ,\n       \"label\"  :   \"My new button!\"  ,\n       \"url\"  :   \"https://riddle.com\"\n   }\n  This will create a button with the label \"My new button!\" which links to   https://riddle.com . If we now want to set the optional property   isOpenInNewTabEnabled   to   true  the object for this button would look like this:     {\n       \"type\"  :   \"Button\"  ,\n       \"label\"  :   \"My new button!\"  ,\n       \"url\"  :   \"https://riddle.com\"  ,\n       \"isOpenInNewTabEnabled\"  :   true   \u003C---   optional   property\n   }\n  In the next sections all available blocks are listed with their required and optional properties. These are the available   type  values:     Type  What it does  Available for...     Text  A rich-text block  all Riddle types    Media  An image, video or embedded social media post  all Riddle types    Button  A call-to-action button linking to a URL  all Riddle types    Share  Share buttons for social networks  all Riddle types    ResultScore  The visitor's score  all Riddle types    AnsweredBlocks  What the visitor answered, including vote statistics  all Riddle types    Leaderboard  A leaderboard the Riddle is connected to  all Riddle types    PopularChoices  A ranking of what all respondents predicted  Predictor only    WinningPersonality  The visitor's winning personality  Personality only    OtherPersonalities  The remaining personalities  Personality only    Attributes  A bar per attribute with its score  Personality only    RecommendedContent  Other Riddles to check out next  all Riddle types  A result page needs   at least 1  and accepts   at most 10  blocks. Using a type that is not available for the Riddle type you are building (e.g.   WinningPersonality  in a poll) is rejected with an \"Invalid result builder block type\" error.  Add user's score  Displays the user's score in a given format.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   ResultScore     format   string  The format in which the user's score should be displayed, valid values:   Score  (displays the user's score in an absolute number),   ScoreTotalScore  (displays the user's score in relation to the total score),   ScorePoints  ( displays the user's score in points),   Percentage  (displays the user's score in percentage)  Percentage    colorBg   string  The background color of the score  rgba(0, 0, 0, 0)    colorText   string  The text color of the score   (the palette's text color)    colorCircle   string  The color of the circle   (the palette's text color)    colorCircleBg   string  The background color of the circle  rgba(0,0,0,0.1)    size   integer  The diameter of the score circle in px; 1 or more  96    isFillingEnabled   boolean  Whether the circle fills up proportionally to the score  false  Example     {\n       \"type\"  :   \"ResultScore\"  ,\n       \"format\"  :   \"Score\"  ,\n       \"colorBg\"  :   \"#fff\"  ,\n       \"colorText\"  :   \"#000\"  ,\n       \"colorCircle\"  :   \"#000\"  ,\n       \"colorCircleBg\"  :   \"#fff\"\n   }\n  Add text  Displays a regular text block. You can use HTML tags in the text.   Tip:  Use   dynamic variables  here to personalize the result page text to user input.  Properties     Property  Required  Type  Description  Default     text  ✓  string  The text to be displayed   Example     {\n       \"type\"  :   \"Text\"  ,\n       \"text\"  :   \"This is my result page text!\"\n   }\n  Add button  Displays a call to action button that links to a specified URL on click.   Tip:  Use   dynamic variables  in the label or URL.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Button     label  ✓  string  The button text     url  ✓  string  The URL the button should link to     isOpenInNewTabEnabled   boolean  If   true  the link will open in a new tab  false    isFillingEnabled   boolean  If   true  the button spans the full width of the result page  true    presetId   string  The ID of a button style preset of your project to inherit the styling from     colorBg   string  The background color of the button  #000    colorBgHover   string  The background color of the button on hover  rgba(0,0,0,0.8)    colorBorder   string  The border color of the button  #77baf6ff    colorBorderHover   string  The border color of the button on hover  #93c3ed    colorText   string  The text color of the button  #fff    colorTextHover   string  The text color of the button on hover  #fff    borderRadius   string  The border radius of the button; all corners are the same  18px    borderWidth   string  The border width of the button; all sides are the same  0px    padding   string  The padding of the button; all sides are the same  11px    textCapitalization   string  The text capitalization of the button. Valid values:   capitalize ,   uppercase ,   lowercase ,   none  uppercase    textAlign   string  The text alignment of the button. Valid values:   start ,   end ,   left ,   right ,   center ,   justify ,   inherit  center    textLetterSpacing   string  The letter spacing of the button  0.12rem    textLineHeight   string  The line height of the button  1.4rem    fontSize   string  The font size of the button  1.6rem    fontFamily   string  The font family for this button. Must be one of the values listed below  normal    fontStyle   string  The font style of the button. Valid values:   normal ,   italic ,   oblique  normal    fontWeight   string  The font weight of the button. Valid values:   normal ,   bold ,   bolder ,   lighter ,   inherit ,   n100 ,   n200 ,   n300 ,   n400 ,   n500 ,   n600 ,   n700 ,   n800 ,   n900  n600   Note:    fontFamily  only accepts one of the following values (generic CSS families like   Arial  or   sans-serif  are rejected with a   NOT_ALLOWED_VALUE  error) - use the   Builder API font families endpoint  to fetch this same list at any time (that endpoint requires a Business or Enterprise plan):   ABeeZee ,   Abril Fatface ,   Alex Brush ,   Archivo ,   Arimo ,   Assistant ,   Atkinson Hyperlegible ,   Barlow ,   Baskervville ,   Bebas Neue ,   BioRhyme ,   Bitter ,   Bree Serif ,   Cabin ,   Cabin Sketch ,   Cairo ,   Calistoga ,   Candal ,   Cantarell ,   Cardo ,   Cormorant ,   Cormorant Garamond ,   Cormorant Infant ,   Cormorant SC ,   Cormorant Unicase ,   Courgette ,   Crimson Text ,   Dancing Script ,   DM Sans ,   DM Serif Display ,   DM Serif Text ,   Domine ,   EB Garamond ,   Electrolize ,   Exo ,   Exo 2 ,   Fira Sans ,   Fjalla One ,   Gentium Basic ,   Gentium Book Basic ,   IBM Plex Sans ,   IBM Plex Serif ,   Inconsolata ,   Inter ,   Istok Web ,   Josefin Sans ,   Jost ,   Jura ,   Karla ,   Khand ,   Lato ,   Libre Baskerville ,   Libre Franklin ,   Lora ,   M PLUS 1p ,   M PLUS Rounded 1c ,   Maven Pro ,   Montserrat ,   Montserrat Alternates ,   Mukta ,   Noto Sans ,   Noto Sans JP ,   Noto Sans KR ,   Noto Sans SC ,   Noto Serif ,   Nunito ,   Nunito Sans ,   Old Standard TT ,   Open Sans ,   Open Sans Condensed ,   Oswald ,   Overpass ,   Pacifico ,   Permanent Marker ,   Playball ,   Playfair Display ,   Poppins ,   PT Mono ,   PT Sans ,   PT Serif ,   Quattrocento ,   Quattrocento Sans ,   Qwigley ,   Raleway ,   Red Hat Display ,   Red Hat Text ,   Roboto ,   Roboto Condensed ,   Roboto Mono ,   Roboto Slab ,   Rokkitt ,   Rubik ,   Russo One ,   Sanchez ,   Satisfy ,   Schoolbell ,   Source Code Pro ,   Source Sans Pro ,   Source Serif Pro ,   Spartan ,   Special Elite ,   Spectral ,   Teko ,   Tenor Sans ,   Tinos ,   Titillium Web ,   Ubuntu ,   Unica One ,   Varela ,   Varela Round ,   Vollkorn ,   Work Sans ,   Zilla Slab  Example     {\n       \"type\"  :   \"Button\"  ,\n       \"label\"  :   \"Click me!\"  ,\n       \"url\"  :   \"https://riddle.com\"  ,\n       \"isOpenInNewTabEnabled\"  :   true  ,\n       \"colorBg\"  :   \"_colorBg\"  ,\n       \"colorBgHover\"  :   \"#fff\"  ,\n       \"colorBorder\"  :   \"#fff\"  ,\n       \"colorBorderHover\"  :   \"#fff\"  ,\n       \"colorText\"  :   \"#fff\"  ,\n       \"colorTextHover\"  :   \"#fff\"  ,\n       \"borderRadius\"  :   \"5px\"  ,\n       \"borderWidth\"  :   \"5px\"  ,\n       \"padding\"  :   \"5px\"  ,\n       \"textCapitalization\"  :   \"lowercase\"  ,\n       \"textAlign\"  :   \"inherit\"  ,\n       \"textLetterSpacing\"  :   \"20px\"  ,\n       \"textLineHeight\"  :   \"20px\"  ,\n       \"fontFamily\"  :   \"Poppins\"  ,\n       \"fontSize\"  :   \"20px\"  ,\n       \"fontStyle\"  :   \"oblique\"  ,\n       \"fontWeight\"  :   \"bolder\"\n   }\n  Add share to social block  Displays a share block that allows users to share the result on different social networks.  You can customize the share messages, URLs and all of the share block's design properties.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Share     label   string  The label of the share element  Share    messageTitle   string  The message users will share and will see as the title in the share dialogue   (empty)    messageDescription   string  The description users will see in the share dialogue as a description   (empty)    messageUrl   string  The URL users will share   (empty)  (will go to Riddle showcase, riddle.com/view/X)    messageImage   string|object  The image users will see in the share dialogue   (empty)    isOverwriteValuesEnabled   boolean  Master switch: whether the four   message*  values override the Riddle's own defaults at all  false    networks   array  The networks the user can share the result on. See below to get the available social networks   'facebook', 'whatsapp', 'twitter'    networkConfigs   object  Per-network overrides; see below     colorBg   string  The background color of the share block  #ffffff00    colorButtonBg   string  The background color of the share button  #000    colorButtonBgHover   string  The background color of the share button on hover  #333    colorButtonIcon   string  The color of the share button icon  #fff    colorButtonIconHover   string  The color of the share button icon on hover  #fff    colorBrandIsEnabled   boolean  If   true  the brand color will be used for the share button  false    colorText   string  The text color of the share block  #000    buttonBorderRadius   string  The border radius of the share button  50%    buttonGap   string  The gap between the share buttons  0.8rem    buttonIconSize   string  The size of the share button icon  2.1rem    buttonSize   string  The size of the share button  3.6rem    textCapitalization   string  The text capitalization of the share block. Valid values:   capitalize ,   uppercase ,   lowercase ,   none  uppercase    textAlign   string  The text alignment of the share block. Valid values:   start ,   end ,   left ,   right ,   center ,   justify ,   inherit  inherit    textLetterSpacing   string  The letter spacing of the share block  0.12rem    textLineHeight   string  The line height of the share block  1.4rem    fontFamily   string  The font family for this button. Must be one of the same values listed under   Add button  above  none    fontSize   string  The font size of the share block  1.6rem    fontStyle   string  The font style of the share block. Valid values:   normal ,   italic ,   oblique  normal    fontWeight   string  The font weight of the share block. Valid values:   normal ,   bold ,   bolder ,   lighter ,   inherit ,   n100 ,   n200 ,   n300 ,   n400 ,   n500 ,   n600 ,   n700 ,   n800 ,   n900  n400  Example     {\n       \"type\"  :   \"Share\"  ,\n       \"messageTitle\"  :   \"Share this poll!\"  ,\n       \"messageDescription\"  :   \"This is a description\"  ,\n       \"networks\"  : [  \"facebook\"  ,   \"linkedin\"  ]\n   }\n  Per-network configuration   networks  only switches networks on and off. If you want a   different  share message per network, use   networkConfigs  instead - an object keyed by network name, where each value may contain:     Property  Required  Type  Description  Default     isEnabled   boolean  Whether this network is offered     isOverwriteValuesEnabled   boolean  Whether this network overrides the global share message     title   string  The title shared on this network     description   string  The description shared on this network     url   string  The URL shared on this network     image   string  The image URL shared on this network. Unlike the block's own   messageImage , this only accepts a plain URL string - it is not uploaded to our CDN   Setting any of   title ,   description ,   url  or   image  for a network automatically sets that network's   isOverwriteValuesEnabled  to   true . Unknown network names are rejected.   networkConfigs  is applied   after    networks , so you can enable a set of networks with the simple list and then refine individual ones.  Example:     {\n       \"type\"  :   \"Share\"  ,\n       \"networks\"  : [  \"facebook\"  ,   \"linkedin\"  ],\n       \"networkConfigs\"  : {\n           \"linkedin\"  : {\n               \"title\"  :   \"I scored 9/10 - can you beat me?\"  ,\n               \"url\"  :   \"https://www.your-website.com/quiz\"\n           }\n       }\n   }\n  Available social networks  The following social networks are available to share on   (make sure to use the same casing!) :   buffer  email  evernote  facebook  flipboard  instagram  instapaper  line  linkedin  messenger  odnoklassniki  pinterest  pocket  reddit  skype  sms  telegram  tumblr  twitter  viber  vk  weibo  whatsapp  xing  yammer  Add answered blocks  Displays a block that shows the user what they answered and how many votes each answer got (if enabled).  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   AnsweredBlocks     areTotalVotesVisible   boolean  If   true  the total number of votes will be displayed  false    isPercentageVisible   boolean  If   true  the percentage of votes will be displayed  true    isVotesNumberVisible   boolean  If   true  the number of votes will be displayed  false    areAnswerImagesHidden   boolean  If   true  the images of the answers will be hidden  false    areMainImagesHidden   boolean  If   true  the main images will be hidden  false    areTitlesHidden   boolean  If   true  the question titles will be hidden  false    areChoicesSortedByVote   boolean  If   true  the answer options are sorted by how many votes they got instead of their original order  false    isRightWrongMsgEnabled   boolean  Quiz: if   true  a \"correct\"/\"incorrect\" message is shown per question  false    isRightWrongVisualEnabled   boolean  Quiz: if   true  correct and incorrect answers are highlighted visually  false  Example     {\n       \"type\"  :   \"AnsweredBlocks\"  ,\n       \"areTotalVotesVisible\"  :   true\n   }\n  Add image  Displays an image, a video, or embedded social media content.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Media     media  ✓  string|object  The media to display. See   Use media     mediaFit   string  How the media fills the block:   Cover  (crop to fill) or   Contain  (fit entirely)  Cover    isBlurredBgEnabled   boolean  Whether a blurred copy of the media fills the empty space around it  true  Example     {\n       \"type\"  :   \"Media\"  ,\n       \"media\"  :   \"https://httpbin.io/image/jpeg\"  ,\n       \"mediaFit\"  :   \"Contain\"\n   }\n  Add leaderboard  Add a leaderboard to the result page.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Leaderboard     leaderboard  ✓  string  The UUID of the leaderboard you want to connect     isTitleVisible   boolean  Whether the leaderboard's title is shown above the entries  false    isShareButtonVisible   boolean  Whether visitors can share their leaderboard entry  false  Example     {\n       \"type\"  :   \"Leaderboard\"  ,\n       \"leaderboard\"  :   \"hQ3SYWur\"\n   }\n   Note:  The leaderboard has to satisfy two conditions, and both are checked while the build runs:   it must already be   published  - a leaderboard that only exists as a draft is rejected with   Leaderboard hQ3SYWur is not published , so publish it (or build it with   \"publish\": true ) before referencing it here, and  the Riddle you are building must be   connected  to it, otherwise the build is rejected with   Leaderboard hQ3SYWur is not connected to Riddle abcdef12 .  The connection is configured in   build.leaderboard.connections  of this Riddle, or from the leaderboard's side via   riddleConnections  - see   Create and connect to Leaderboard . Sending both the connection and this block in one build configuration works: the connection is established before the result page is built.  Add popular choices  Ranks the outcomes all respondents predicted, e.g. \"63% picked Team A\".   Only available for predictors.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   PopularChoices     topChoicesCountSingleQuestion   integer  How many choices to rank when the predictor has a single question; 1 or more  5    topChoicesCountPerQuestion   integer  How many choices to rank per question when the predictor has several questions; 1 or more  1    showOtherChoicesSummary   boolean  Whether the remaining choices are summarized below the ranking  true  Example     {\n       \"type\"  :   \"PopularChoices\"  ,\n       \"topChoicesCountSingleQuestion\"  :   3  ,\n       \"showOtherChoicesSummary\"  :   false\n   }\n  Add winning personality  Displays the user's winning personality. Only available for personality tests.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   WinningPersonality     showMedia   boolean  If   true  the media of the personality will be displayed  true    format   string  The format in which the personality will be displayed. Valid values:   PercentageTitle ,   TitlePercentage ,   PointsTitle ,   TitlePoints ,   Title  PercentageTitle    mediaOrientation   string  How that media is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings  Example     {\n       \"type\"  :   \"WinningPersonality\"  ,\n       \"showMedia\"  :   true  ,\n       \"format\"  :   \"Title\"\n   }\n  Add other personalities  Displays the other personalities. Only available for personality tests.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   OtherPersonalities     format   string  The format in which the personalities will be displayed. Valid values:   PercentageTitle ,   TitlePercentage ,   PointsTitle ,   TitlePoints ,   Title  TitlePercentage    count   integer  The number of personalities to display; 1 or more. Only applies when   isShowAllEnabled  is   false  2    isShowAllEnabled   boolean  If   true  all personalities are shown and   count  is ignored  true    layout   string  The layout in which the personalities will be displayed. Valid values:   FullWidth ,   TwoColumns  TwoColumns    includeWinningPersonality   boolean  If   true  the winning personality will also be displayed  false    mediaOrientation   string  How the personalities' media is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings  Example     {\n       \"type\"  :   \"OtherPersonalities\"  ,\n       \"format\"  :   \"Title\"  ,\n       \"count\"  :   3  ,\n       \"layout\"  :   \"FullWidth\"  ,\n       \"includeWinningPersonality\"  :   false\n   }\n  Add attributes  Displays a bar per Personality attribute with its score. Only available for personality tests.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   Attributes     areAllAttributesVisible   boolean  If   true  every attribute is shown and   count  is ignored  false    count   integer  How many top attributes to display; 1 or more. Only applies when   areAllAttributesVisible  is   false     format   string  The format in which each attribute is displayed. Valid values:   PercentageTitle ,   TitlePercentage ,   PointsTitle ,   TitlePoints ,   Title     layout   string  The layout in which the attributes are displayed. Valid values:   FullWidth ,   TwoColumns     mediaOrientation   string  How the attributes' media is cropped:   Settings ,   Wide ,   Square ,   Tall , or   Original  Settings  Example     {\n       \"type\"  :   \"Attributes\"  ,\n       \"format\"  :   \"Title\"  ,\n       \"count\"  :   3  ,\n       \"layout\"  :   \"FullWidth\"\n   }\n  Add recommended content  Displays other Riddles the visitor might want to check out next. You can either pick the Riddles yourself, or have them selected dynamically by type/tag.  Properties     Property  Required  Type  Description  Default     type  ✓  string  Set to   RecommendedContent     title   string  The block's own title     selectionMode   string   Manual  (you pick the Riddles yourself via   selectedRiddles ) or   Conditions  (Riddles are selected dynamically via   riddleTypes /  tags /  sortBy /  amount )     selectedRiddles   string    Manual  only: 1-10 UUIDs of published Riddles you own     riddleTypes   string    Conditions  only: limit to these Riddle types; omit or send an empty array for \"every type\"     tags   (integer|string)    Conditions  only: limit to Riddles carrying at least one of these tags, each given as a tag ID or a tag name     sortBy   string   Conditions  only: how the matching Riddles are sorted     amount   integer   Conditions  only: how many Riddles to show, 1-10     showMedia   boolean  Whether each Riddle's media is shown  true    showTitle   boolean  Whether each Riddle's title is shown  true    displayMode   string  How the Riddles are laid out    Note:    selectionMode  and its matching properties form two strictly separate sets -   Manual  only ever reads   selectedRiddles ,   Conditions  only ever reads   riddleTypes /  tags /  sortBy /  amount . This is enforced, not just gated for display:   As soon as you send any property from either set, you must also send   selectionMode  explicitly (set to   Manual  or   Conditions ) - it is never inferred from what else you sent.  Sending a property that belongs to the   other  mode than the one you selected is rejected outright.  In   Manual  mode,   selectedRiddles  must be a non-empty list - an empty selection would show nothing.  Each   selectedRiddles  UUID must belong to a Riddle you (or your team) own and that is currently published; an unpublished, missing, or foreign Riddle is rejected.  Each   tags  entry must be an existing tag of the same scope as the Riddle you are building - your team's tags for a team Riddle, your own otherwise. Send either the numeric tag ID or the tag name; a tag that does not exist, or belongs to someone else, is rejected (a build never creates a tag), and naming the same tag twice is rejected as well. Tags always read back as their numeric IDs, which - unlike a name two tags could share - are unambiguous. If a tag is deleted later, reading the Riddle back leaves it out and reports a warning; sending that build configuration back therefore also removes it from the stored filter.  Example: manual results     {\n       \"type\"  :   \"RecommendedContent\"  ,\n       \"title\"  :   \"You might also like\"  ,\n       \"selectionMode\"  :   \"Manual\"  ,\n       \"selectedRiddles\"  : [  \"hQ3SYWur\"  ,   \"aB1cDeFg\"  ]\n   }\n  Example: conditional results     {\n       \"type\"  :   \"RecommendedContent\"  ,\n       \"title\"  :   \"More quizzes\"  ,\n       \"selectionMode\"  :   \"Conditions\"  ,\n       \"riddleTypes\"  : [  \"Quiz\"  ],\n       \"tags\"  : [  \"Summer\"  ],\n       \"amount\"  :   3\n   }\n  Offset any block with margins  If you want to create a gap between two result page builder blocks, e.g. to emphasize a certain block, you can use margins to better position the blocks.   Note:  The margin does not work with pixel values! Instead we use the coordinate system just as in the Creator to position the blocks. This means that setting \"marginTop: 2\" will result in a block offset by two units. We recommend you play around and see what works best for your design.  Properties     Property  Required  Type  Description  Default     marginTop   integer  The margin at the top of the block; 0-10  0    marginBottom   integer  The margin at the bottom of the block; 0-10  0  Both are accepted on   every  result page block type.  Example     {\n       \"type\"  :   \"Text\"  ,\n       \"text\"  :   \"This is my result page text!\"  ,\n       \"marginTop\"  :   2  ,\n       \"marginBottom\"  :   2\n   }\n  Full example  A poll with an advanced result page built into it: a text, the answered blocks with their total votes, an image and a button back to your site.     {\n       \"type\"  :   \"Poll\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Pasta poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"title\"  :   \"Spaghetti or Fusilli?\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Spaghetti\"   },\n                       {   \"title\"  :   \"Fusilli\"   }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"blocks\"  : [\n                   {\n                       \"type\"  :   \"Text\"  ,\n                       \"text\"  :   \"Thanks for voting!\"\n                   },\n                   {\n                       \"type\"  :   \"AnsweredBlocks\"  ,\n                       \"areTotalVotesVisible\"  :   true\n                   },\n                   {\n                       \"type\"  :   \"Media\"  ,\n                       \"media\"  :   \"https://httpbin.io/image/png\"  ,\n                       \"mediaFit\"  :   \"Contain\"\n                   },\n                   {\n                       \"type\"  :   \"Button\"  ,\n                       \"label\"  :   \"Back to the blog\"  ,\n                       \"url\"  :   \"https://riddle.com\"\n                   }\n               ]\n           }\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":261,"path":262,"dir":263,"title":264,"description":265,"keywords":266,"body":279},"content:15.Api:4.Build Riddles:4.Settings configuration:1.Publish settings.md","/api/build-riddles/settings-configuration/publish-settings","settings-configuration","Publish settings - Build Riddles","Learn how to publish Riddles and set publish settings via API",[267,268,269,98,270,271,272,273,274,275,276,277,278,133],"Publishing the built Riddle after creation","Advanced settings","Properties","Integrations","DOI","Email OTP","SMS OTP","Showcase page and QR code","Email automation","Data Layer","Tracking","Embed settings","  Publish settings  Publishing the built Riddle after creation  The request body parameter   publish  can be sent with the API to publish the Riddle right after creation, making it easier to embed the generated content on the web page.  Example:     {\n       \"type\"  :   \"Poll\"  ,\n       \"publish\"  :   true  ,\n       \"build\"  : {\n           \"blocks\"  : [  ...  ]\n       }\n   }\n  Advanced settings  With these publish settings you can define any settings found in the Riddle Creator Publish screen.  Properties  You can specify the following   optional  properties:     Property  Required  Type  Description  Default     isShowcaseEnabled   boolean  Set to   false  if your Riddle should not be accessible via direct Riddle link (e.g. riddle.com/view/XXX)  true    showcaseConfig   object  Further configuration of that direct link and its QR code; more information below     isDoiEnabled   boolean  Set to   true  if you want to enable the Double-Opt-In Feature. For this to work you must add an email address form field first. Learn   here  how to add form fields  false    doiConfig   object  Further configuration for the Double-Opt-In Feature; more information below     isOtpEnabled   boolean  Set to   true  to verify leads with a one-time code sent by   email  instead of a confirmation link. Also requires an email form field  false    otpConfig   object  Further configuration for email OTP; more information below     isOtpSMSEnabled   boolean  Set to   true  to verify leads with a one-time code sent by   SMS . Requires a   Phone  form field  false    otpSMSConfig   object  Further configuration for SMS OTP; more information below     isEmailAutomationEnabled   boolean  Set to   true  if you want to enable the email automation feature. For this to work you must add an email address form field first. Learn   here  how to add form fields  false    emailAutomationConfig   object  Further configuration for the email automation feature; more information below     dataLayerItems   object  A key-value array to create data layer variables; more information below     isDataLayerSubmitEnabled   boolean  Whether the Riddle can be submitted via a   dataLayer.push(...)  from your own page  false    isDataLayerChangePaletteEnabled   boolean  Whether a data layer push may also switch the Riddle's palette  false    tracking   string[]  Simple tracking configuration - a list of networks to switch on; more information below     trackingNetworks   object  Advanced, per-network tracking configuration (credentials, events); more information below     integrations   object  Specify   existing  integrations to enable; more information below     embedSettings   object  How the published Riddle behaves once embedded (iframe sizing, lazy loading, ...); more information below    Note:  DOI, email OTP and SMS OTP are three alternative ways of verifying a lead and only   one  of them can be active. Enabling one automatically switches the other two off, exactly as the Riddle Creator does.  Example  The publish settings properties are sent in the   publish  property of the build object, here's how it looks:     {\n       \"blocks\"  : [  ...  ],\n       \"publish\"  : {\n           \"isDoiEnabled\"  :   true  ,\n           ...\n       }\n   }\n  Integrations  You can add existing Googlesheets & webhook integrations to your Riddle. To do this, you can specify   integrations  in your   publish  object.  Example:     {\n       \"blocks\"  : [  ...  ],\n       \"publish\"  : {\n           \"integrations\"  : {\n               \"googlesheets\"  :   \"test@riddle.com\"  ,\n               \"webhook\"  :   \"your-website.com/webhook\"\n           }\n       }\n   }\n  In this example we already connected the Googlesheets integration with the email   test@riddle.com  and the webhook integration with the URL   your-website.com/webhook . The name of the integration you send here must match with the name displayed on the integrations page in the Riddle Creator.  If the integration cannot be found, the Riddle build will fail and you will get a   RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_INVALID  error from the API.  DOI  To enable DOI, first set   isDoiEnabled  to   true :     {\n       \"isDoiEnabled\"  :   true\n   }\n  Enabling it will set the first email field in the Riddle as the DOI field.  If you want to customize the DOI email or confirmation page, you can send the following properties in   doiConfig :     Property  Required  Type  Description  Default     emailSubject   string  The DOI email subject     emailText   string  The DOI email text     emailConfirmationButtonLabel   string  The label of the confirmation button in the DOI email     confirmationPageHeadline   string  The headline of the confirmation page     confirmationPageBody   string  The text of the confirmation page     confirmationPageUrl   URL  The URL the user is redirected to after confirming the DOI     isCustomConfirmationPageEnabled   boolean  Explicitly switches the custom confirmation page on or off - send   false  together with the properties above to keep them stored but show the default page - see   feature toggles  derived from the three properties above    emailFieldIdentifier   string  Which email field the confirmation link is sent to - overrides the auto-picked first email field     isSaveUnconfirmedEnabled   boolean  Whether leads that never confirm are still stored, instead of being discarded  false    isSmtpEnabled   boolean  Whether the email is sent through your own configured SMTP server instead of Riddle's sender  false   Note:  If you send a   confirmationPageUrl  property, the other confirmation page properties are redundant as the user gets redirected to the URL immediately after confirming the DOI (user does not see extra confirmation page headline/text).   Note:  Sending any of   confirmationPageHeadline ,   confirmationPageBody  or   confirmationPageUrl  automatically switches the custom confirmation page on - you do not need a separate flag for it.   Note:    emailFieldIdentifier  must be the identifier of an   Email  field that actually exists in the built Riddle (e.g.   email1 ); anything else is rejected and the error lists the identifiers you can use. You only need it if your Riddle has more than one email field, e.g. an \"invite a friend\" form.   Tip:  Use   dynamic variables  for any of the DOI properties to personalize this flow to user input. Only variables that this particular Riddle can actually resolve are accepted - e.g.   %name  needs a   Name  form field. If you use one that does not exist, the error message lists every variable that   is  usable in your Riddle.  Example:     {\n       \"isDoiEnabled\"  :   true  ,\n       \"doiConfig\"  : {\n           \"emailSubject\"  :   \"Please confirm your email %name\"  ,\n           \"emailText\"  :   \"Hi %name, Please confirm your email by clicking the button below.\"  ,\n           \"emailConfirmationButtonLabel\"  :   \"Confirm email\"  ,\n           \"confirmationPageHeadline\"  :   \"Thank you for confirming your email\"  ,\n           \"confirmationPageBody\"  :   \"You can now access the content\"  ,\n           \"confirmationPageUrl\"  :   \"https://www.your-website.com\"\n       }\n   }\n  Email OTP  Instead of a confirmation link (DOI), you can have the visitor type back a one-time code that is emailed to them. Set   isOtpEnabled  to   true ; the first email field of the Riddle is picked automatically, and DOI/SMS OTP are switched off.   otpConfig  accepts:     Property  Required  Type  Description  Default     emailFieldIdentifier   string  Which email field the code is sent to - overrides the auto-picked first email field     isSaveUnconfirmedEnabled   boolean  Whether leads that never enter the code are still stored  false    isSmtpEnabled   boolean  Whether the email is sent through your own configured SMTP server  false  Example:     {\n       \"isOtpEnabled\"  :   true  ,\n       \"otpConfig\"  : {\n           \"isSaveUnconfirmedEnabled\"  :   true\n       }\n   }\n  SMS OTP  The same one-time-code flow, but over SMS. Set   isOtpSMSEnabled  to   true  - this requires a   Phone  form field in the Riddle (the first one is picked automatically) and switches DOI/email OTP off.   otpSMSConfig  accepts:     Property  Required  Type  Description  Default     phoneFieldIdentifier   string  Which phone field the SMS is sent to - overrides the auto-picked first phone field     isSaveUnconfirmedEnabled   boolean  Whether leads that never enter the code are still stored  false    vendor   string  The SMS vendor to send through:   LinkMobility  or   WebSMS  WebSMS    vendorApiKey   string  Your API key for that vendor    Note:    vendorApiKey  is write-only. It is never returned when you read a Riddle back as a build configuration, so a credential is not handed out to anyone who can read the Riddle's structure.  Example:     {\n       \"isOtpSMSEnabled\"  :   true  ,\n       \"otpSMSConfig\"  : {\n           \"vendor\"  :   \"LinkMobility\"  ,\n           \"vendorApiKey\"  :   \"my-api-key\"\n       }\n   }\n  Showcase page and QR code   isShowcaseEnabled  controls whether the Riddle is reachable through its direct link (riddle.com/view/XXX) at all - it is enabled by default.   showcaseConfig  fine-tunes that page and the QR code generated for it:     Property  Required  Type  Description  Default     isFullScreenEnabled   boolean  Whether the showcase page renders the Riddle full-screen  false    isQrCodeLogoEnabled   boolean  Whether your logo is placed in the middle of the QR code  true    isCustomQrCodeDestinationEnabled   boolean  Whether the QR code points somewhere else than the showcase page  false    customQrCodeDestination   URL  That custom destination URL   Example:     {\n       \"isShowcaseEnabled\"  :   true  ,\n       \"showcaseConfig\"  : {\n           \"isFullScreenEnabled\"  :   true  ,\n           \"isCustomQrCodeDestinationEnabled\"  :   true  ,\n           \"customQrCodeDestination\"  :   \"https://www.your-website.com/campaign\"\n       }\n   }\n  Email automation  To enable email automation, first set   isEmailAutomationEnabled  to   true :     {\n       \"isEmailAutomationEnabled\"  :   true\n   }\n  Enabling it will set the first email field in the Riddle as the email automation field.  Enabling it also prefills a default subject and text for you (e.g.   \"Thanks for taking our quiz!\" , including the score and result for quizzes) - you only need   emailAutomationConfig  if you want something else.  If you want to customize the email that is sent, you can send the following properties in   emailAutomationConfig :     Property  Required  Type  Description  Default     subject   string  The email subject     text   string  The email text     recipient   string  Which email field the email is sent to - overrides the auto-picked first email field     recipientCC   string[]  Literal email addresses to CC     recipientBCC   string[]  Literal email addresses to BCC     replyTo   string[]  Literal email addresses to use as reply-to     isAdvancedEnabled   boolean  Whether the advanced CC/BCC/reply-to panel is active in the Riddle Creator  false    isSmtpEnabled   boolean  Whether the email is sent through your own configured SMTP server  false   Note:    recipient  is a   form field identifier  (e.g.   email1 ) and must name an   Email  field in the built Riddle.   recipientCC ,   recipientBCC  and   replyTo  are the opposite: plain, literal email addresses, each of which must be a valid address.   Tip:  Use   dynamic variables  for any of the email automation properties to personalize this flow to user input.  Example:     {\n       \"isEmailAutomationEnabled\"  :   true  ,\n       \"emailAutomationConfig\"  : {\n           \"subject\"  :   \"Thank you for participating %name!\"  ,\n           \"text\"  :   \"Thank you for participating in our quiz %name. Here are your results: ...\"\n       }\n   }\n  Data Layer  The   Riddle Data Layer  can be setup with the   dataLayerItems  property which is a key-value array: The key is the key of the data layer variable (this is used to push to it, e.g. riddle.com/view/XXX?key=value or   dataLayer.push({ key: value }) ) and the value is the title of the variable which will be used in the export as the data layer column name.  Example: Adding three data layer variables:     {\n       \"dataLayerItems\"  : {\n           \"utm_source\"  :   \"Source\"  ,\n           \"utm_medium\"  :   \"Medium\"  ,\n           \"utm_campaign\"  :   \"Campaign\"\n       }\n   }\n  Two further data layer switches are available next to the variables themselves:     Property  Required  Type  Description  Default     isDataLayerSubmitEnabled   boolean  Whether the Riddle can be submitted from your own page via a data layer push  false    isDataLayerChangePaletteEnabled   boolean  Whether a data layer push may also change the Riddle's palette  false  Tracking  With the   tracking  property you can define which tracking should be enabled for your Riddle. By default no tracking is enabled.  The following tracking options are available (case-sensitive):   adobe  facebookPixel  googleAnalytics  googleAnalytics4  googleTagManager  matomoTag  Example: Activating Google Tag Manager and Matomo Tag:     {\n       \"tracking\"  : [  \"googleTagManager\"  ,   \"matomoTag\"  ]\n   }\n   Note:    tracking  is a switch and nothing more - it enables the networks you list and disables every one you leave out. It cannot configure   customTracking ; use   trackingNetworks  below for that.  Advanced tracking configuration   trackingNetworks  is the richer form of the same setting: an object keyed by network name, where each network can be configured in detail. It is applied   after    tracking , so you can use the simple list to switch networks on and this to fill in the details - or use   trackingNetworks  alone.     Property  Required  Type  Description  Default     isEnabled   boolean  The network's own master switch     trackingId   string  The network's credential/ID, e.g. your GTM container ID or Facebook pixel ID. Not available for   customTracking     eventFunction   string   customTracking    only : the JavaScript function that receives every Riddle event     eventConfig   object  Which events are forwarded to this network; see below   Next to the six networks listed above,   trackingNetworks  also accepts   customTracking .   Note:  Supplying a   trackingId  automatically enables that network's configuration - a credential you sent would otherwise never be used.   eventConfig  accepts these keys, all booleans:     Key  Description  Default     isEnabled  Whether custom event configuration is used at all for this network  false    CoreMetrics_View  Riddle was viewed  true    CoreMetrics_Start  Riddle was started  true    CoreMetrics_Finish  Riddle was finished  true    Block_View  A block was viewed  true    Block_Next  The visitor moved to the next block  true    Block_Skip  A block was skipped  true    Block_Submit  A block was submitted  true    Form_Submit  A form was submitted  true    Form_Skip  A form was skipped  true    LeadSettings  Lead settings events (e.g. DOI/OTP confirmation)  true    Social  Sharing events  true    Cta  A call-to-action/button was clicked  true    isIncludeDataLayerEnabled  Whether data layer variables are sent along with the events  true    isIncludeFormDataEnabled  Whether form answers are sent along with the events  false  An unknown network name, an unknown event key or a non-boolean event value is rejected, and the error message lists the keys you can use.  Example: switching on Google Tag Manager with its container ID, forwarding only the core metrics, plus a custom tracking function:     {\n       \"trackingNetworks\"  : {\n           \"googleTagManager\"  : {\n               \"isEnabled\"  :   true  ,\n               \"trackingId\"  :   \"GTM-XXXXXX\"  ,\n               \"eventConfig\"  : {\n                   \"isEnabled\"  :   true  ,\n                   \"Block_View\"  :   false  ,\n                   \"Block_Next\"  :   false  ,\n                   \"isIncludeFormDataEnabled\"  :   true\n               }\n           },\n           \"customTracking\"  : {\n               \"isEnabled\"  :   true  ,\n               \"eventFunction\"  :   \"(riddleEvent) => { console.log(riddleEvent); }\"\n           }\n       }\n   }\n  Embed settings   embedSettings  defines how the published Riddle behaves once it is embedded on your own page - the same options the   Embed  screen of the Riddle Creator offers. They are applied to the embed code you retrieve for the Riddle.     Property  Required  Type  Description  Default     iframeMaxWidth   string  A CSS width the Riddle is capped at, e.g.   640px  640px    isFixedHeightEnabled   boolean  Whether the Riddle uses a fixed height instead of resizing itself  false    iframeFixedHeight   string  That fixed height, e.g.   400px  - a number followed by   px ,   % ,   rem  or   em  400px    isFullscreenAllowed   boolean  Whether the embedded Riddle may go full-screen  false    isLazyLoadRiddleActive   boolean  Whether the Riddle itself is only loaded once it scrolls into view  false    isLazyLoadImagesActive   boolean  Whether images inside the Riddle are lazy-loaded  false    isSeoIncluded   boolean  Whether the Riddle's content is also rendered for search engines  false    isAutoScrollEnabled   boolean  Whether the page scrolls to the Riddle as the visitor advances through it  true    isAutoScrollOffsetEnabled   boolean  Whether that scroll stops a few pixels above the Riddle  false    autoScrollOffset   integer  How many pixels above the Riddle to stop; 0 or more  80    isJsEmbedDisabled   boolean  Whether the JavaScript loader is left out of the embed code, leaving a plain   \u003Ciframe>  false    isCssEmbedDisabled   boolean  Whether Riddle's embed CSS is left out  false    jsEmbedHeight   string  Placeholder height the JS embed reserves before the Riddle has resized itself, e.g.   110%  110%   Note:  Unlike everything else on this page, embed settings have no draft/live distinction - they take effect immediately, without publishing the Riddle again.  Example:     {\n       \"embedSettings\"  : {\n           \"iframeMaxWidth\"  :   \"800px\"  ,\n           \"isLazyLoadRiddleActive\"  :   true  ,\n           \"isAutoScrollOffsetEnabled\"  :   true  ,\n           \"autoScrollOffset\"  :   120\n       }\n   }\n  Full example     {\n       \"type\"  :   \"Poll\"  ,\n       \"publish\"  :   true  ,\n       \"build\"  : {\n           \"blocks\"  : [  ...  ],\n           \"publish\"  : {\n               \"isDoiEnabled\"  :   true  ,\n               \"doiConfig\"  : {\n                   \"emailSubject\"  :   \"Please confirm your email %name\"  ,\n                   \"emailText\"  :   \"Hi %name, Please confirm your email by clicking the button below.\"  ,\n                   \"emailConfirmationButtonLabel\"  :   \"Confirm email\"  ,\n                   \"confirmationPageHeadline\"  :   \"Thank you for confirming your email\"  ,\n                   \"confirmationPageBody\"  :   \"You can now access the content\"  ,\n                   \"confirmationPageUrl\"  :   \"https://www.your-website.com\"\n               },\n               \"isEmailAutomationEnabled\"  :   true  ,\n               \"emailAutomationConfig\"  : {\n                   \"subject\"  :   \"Thank you for participating %name!\"  ,\n                   \"text\"  :   \"Thank you for participating in our quiz %name. Here are your results: ...\"\n               },\n               \"dataLayerItems\"  : {\n                   \"utm_source\"  :   \"Source\"  ,\n                   \"utm_medium\"  :   \"Medium\"  ,\n                   \"utm_campaign\"  :   \"Campaign\"\n               },\n               \"isDataLayerSubmitEnabled\"  :   true  ,\n               \"tracking\"  : [  \"googleTagManager\"  ,   \"matomoTag\"  ],\n               \"trackingNetworks\"  : {\n                   \"googleTagManager\"  : {\n                       \"trackingId\"  :   \"GTM-XXXXXX\"\n                   }\n               },\n               \"embedSettings\"  : {\n                   \"iframeMaxWidth\"  :   \"800px\"  ,\n                   \"isLazyLoadRiddleActive\"  :   true\n               },\n               \"integrations\"  : {\n                   \"googlesheets\"  :   \"test@riddle.com\"  ,\n                   \"webhook\"  :   \"https://www.your-website.com/webhook\"\n               }\n           }\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":281,"path":282,"dir":263,"title":283,"description":284,"keywords":285,"body":312},"content:15.Api:4.Build Riddles:4.Settings configuration:2.Preset settings.md","/api/build-riddles/settings-configuration/preset-settings","Preset settings - Build Riddles","Learn how to set preset settings via API",[286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,133],"Default case","Specifying preset settings","All preset properties","Customizing individual palette values","Add remember user configuration","Changing Riddle language","Opening the Riddle at a set time","Closing the Riddle at a set time","Setting Riddle timer","Setting block timer","Timer warm-up","Pagination","Live score","Right/wrong answer feedback","Results on blocks","Stats before voting","Reveal results later","Single vote","IP limit","Clock","Open or close the Riddle right away","Personality result calculation","Custom strings","Footer","Riddle-level ads","External content privacy banner","  Preset settings  With the preset settings you can customize:   Which project preset and palette to use  The remember user configuration  The Riddle language  When the Riddle automatically opens and closes  The Riddle and block timer  Navigation: pagination, auto-advance, back navigation  What the visitor sees while answering: live score, right/wrong feedback, results and stats on blocks  Vote limits: single vote per device, IP limits, email blocklist  Button and message texts, the footer (logo + text) and Riddle-level ad slots  Default case  If no preset setting is specified and the Riddle is created in a project (!) the default preset and its selected palette will be used for the built Riddle.   Click here  to learn how to set a default preset for your project.  Specifying preset settings  The preset settings properties are sent in the   preset  property of the build object. If we now for example want to use a preset and palette from our project the request would look like this:     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"preset\"  :   805  ,\n           \"palette\"  :   \"Zymx\"\n       }\n   }\n  Retrieving preset and palette IDs  Retrieving your project's presets and associated palettes is possible through the   Builder API presets endpoint . An example response looks like this:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : [\n           {\n               \"id\"  :   805  ,\n               \"name\"  :   \"My project preset\"  ,\n               \"palettes\"  : [\n                   {\n                       \"id\"  :   \"Zymx\"  ,\n                       \"name\"  :   \"my palette\"\n                   }\n               ]\n           }\n       ]\n   }\n   palette  accepts either form: the palette's   id  (  \"Zymx\" ) or its   name  (  \"my palette\" ). If neither matches, the error message lists the palettes available in the Riddle's preset.  All preset properties  Every property is optional. Which ones are accepted depends on the Riddle type, see the \"Available for...\" column below.   Note:  In a plain   POST  create build, a property that does not exist for the type you are building is silently ignored by default - unless you turn on    strictProperties , in which case it is rejected with a   400  naming the property and listing what is supported for that type instead. That strict behaviour is not optional when   editing an existing Riddle  (  PUT ) - there an inapplicable property (e.g.   preset.revealResultsLater , Poll only, sent for a Quiz) is always rejected.     Property  Required  Type  Description  Available for...  Default     preset   integer  The project preset to connect the Riddle to  all     presetId   integer  Legacy alias of   preset  all     palette   string  The palette to use - either its ID or its display name  all     paletteValues   object  Individual palette values to override, keyed by field path; see below  all     language   string  The Riddle language; see below  all     rememberUser   object  Remember-user configuration; see below  all     autoOpenDate   string  When the Riddle opens; see below  all     isAutoOpenEnabled   boolean  Explicitly switches auto-open on or off; see below  all     autoClose   object  When the Riddle closes; see below  all     customStrings   object  Overrides for button and feedback texts; see below  all     isRiddleFooterVisible   boolean  Whether the Riddle's footer is shown at all (default   true )  all     footerText   object  A free text note in the footer; see below  all     footerBranding   object  Your own logo in the footer; see below  all     ads   object  Riddle-level ad slots above/below the Riddle; see below  all     isOneVotePerIdentifierEnabled   boolean  Whether each visitor may only vote once, identified by their generated ID (default   false )  all     mediaOrientation   string  The aspect ratio every media element of the Riddle is cropped to:   Wide ,   Square ,   Tall  or   Original  all     isRiddleOpen   boolean  The master open/closed switch; see below  Poll, Quiz, Personality, Form, Predictor, Minigame, Story     riddleTimer   object  A time limit for the whole Riddle; see below  Poll, Quiz, Personality, Form, Minigame     blockTimer   object  A time limit per block; see below  Poll, Quiz, Personality, Form, Minigame     displayLiveScore   object  A running score while answering; see below  Quiz     quizRightWrongDisplay   object  Right/wrong answer feedback; see below  Quiz     pagination   object  Pager/progress bar navigation; see below  Poll, Quiz, Personality, Form, Story     resultsOnBlocks   object  Showing a block's own results after answering; see below  Poll, Quiz, Personality, Form     statsBeforeVoting   object  Showing view/completion counts before answering; see below  Poll, Quiz, Personality, Form     revealResultsLater   object  Hiding the results until a set date; see below  Poll     riddleSingleVote   object  One vote per device; see below  Poll, Quiz, Personality, Form, Predictor     riddleIpLimit   object  Vote limit per IP address; see below  Poll, Quiz, Personality, Form, Predictor     clockRiddle   object  An always-visible running clock; see below  Minigame     personalitySettings   object  How the winning result is calculated; see below  Personality     isAutoAdvance   boolean  Whether the Riddle advances to the next block automatically after answering (default   true )  Poll, Quiz, Personality, Predictor     isChooseButtonVisible   boolean  Whether an explicit \"choose\" button is shown instead of answering by clicking (default   false )  Poll, Quiz, Personality     isTimerWarmupEnabled   boolean  Whether a short countdown runs before a timer starts (default   false )  Poll, Quiz, Personality, Form, Minigame     timerWarmupTime   integer  That countdown's length in seconds; 0 or more (default   3 )  Poll, Quiz, Personality, Form, Minigame     isEmailBlocklistEnabled   boolean  Whether your email blocklist is applied to submissions (default   false )  all except Leaderboard     isExternalContentBannerEnabled   boolean  Whether a privacy banner is shown before external content (YouTube, X, Vimeo) is loaded (default   false )  Poll, Quiz, Personality, Form, Story     privacyTextYoutube   string  Custom banner text for YouTube embeds  Poll, Quiz, Personality, Form     privacyTextTwitter   string  Custom banner text for X/Twitter embeds  Poll, Quiz, Personality, Form, Story     privacyTextVimeo   string  Custom banner text for Vimeo embeds  Poll, Quiz, Personality, Form, Story     privacyTextButton   string  Label of the \"load content anyway\" button  Poll, Quiz, Personality, Form, Story     scoreSeparator   string  How the two predicted scores are separated:   Versus ,   Colon ,   At ,   Dash ,   Slash  or   X  (default   Versus )  Predictor     hasEmphasizeWinnerEnabled   boolean  Whether the winning side is emphasized (default   true )  Predictor     hasGrayOutEnabled   boolean  Whether the losing side is grayed out (default   true )  Predictor     areShareablesOnBlockEnabled   boolean  Whether each prediction can be shared right on the block (default   false )  Predictor     quizTimeMultiplier   integer  0-100; how strongly answering time influences the ranking (default   0 )  Leaderboard     isCompactView   boolean  Whether entries use the compact, single-line view (default   false )  Leaderboard     isShareButtonVisible   boolean  Whether the leaderboard offers a share button (default   true )  Leaderboard     entriesAbove   integer  How many entries are shown above the visitor's own (default   1 )  Leaderboard     entriesBelow   integer  How many entries are shown below the visitor's own (default   3 )  Leaderboard     isTotalEntriesEnabled   boolean  Whether the total number of entries is displayed (default   false )  Leaderboard     isBadwordFilterEnabled   boolean  Whether nicknames run through the bad-word filter (default   false )  Leaderboard     badwordFilterCustomList   string  Additional comma-separated words to filter  Leaderboard     isEmailVerificationEnabled   boolean  Whether participants have to confirm their email address before their score is ranked (default   false )  Leaderboard     color1st   string  CSS color of the first-place row on the podium (default   #D38807 )  Leaderboard     color2nd   string  CSS color of the second-place row on the podium (default   #A9A9A9 )  Leaderboard     color3rd   string  CSS color of the third-place row on the podium (default   #C2691C )  Leaderboard    Note:  Sending   preset  re-applies that project preset to the Riddle from scratch. Any other preset property you send in the same build config is applied   on top  of it, so   {\"preset\": 805, \"language\": \"de_formal\"}  gives you the project preset with German as its language.  Customizing individual palette values   paletteValues  overrides individual design values (colors, fonts, layout options) of the palette the Riddle ends up on, without switching to a different palette. It is an object of   path => value  pairs, e.g.:     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"paletteValues\"  : {\n               \"bgColor\"  :   \"#ffffff\"  ,\n               \"font.name\"  :   \"Roboto\"\n           }\n       }\n   }\n  If   palette  is sent in the same build config, the values are applied on top of that palette. A built-in palette is forked into a Riddle-owned copy first, since a built-in palette itself cannot be changed. An unknown path or a value that does not match the path (e.g. a non-color string for a color field) is rejected, naming the path and the reason.  Reading a Riddle back only reports the values that differ from the palette's own defaults, not the palette's full content.  Add remember user configuration  'Remember user' means writing the user's answers to the local storage, meaning that the user doesn't have to input their name or email again when revisiting the Riddle / website.  Properties     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether the remember user feature is enabled or not  false    isAutoSubmitEnabled   boolean  If true, the form will be submitted automatically when the user returns to the Riddle  true    isDsgvoAccepted   boolean  Whether the user has accepted the DSGVO  false    isUserPermissionRequired   boolean  Whether the user has to give permission to store their data in local storage  true    isPIDOnly   boolean  Whether only the generated participant ID is remembered instead of the answers themselves. The Creator only offers this once   isEnabled  and   isDsgvoAccepted  are both on  false  Example     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"rememberUser\"  : {\n               \"isEnabled\"  :   true  ,\n               \"isAutoSubmitEnabled\"  :   false  ,\n               \"isDsgvoAccepted\"  :   true  ,\n               \"isUserPermissionRequired\"  :   false\n           }\n       }\n   }\n  Changing Riddle language  The language of the Riddle can be changed by setting the   language  property in the preset settings. The default is   en .  Most languages are their plain ISO code (  en ,   it ,   es ), some carry a region (  en-GB ,   pt-br ,   zh-tw ), and some exist only as a formal and a casual tone variant, written as   \u003Clanguage>:formal  /   \u003Clanguage>:casual :   de:formal ,   de:casual ,   fr:formal ,   fr:casual ,   cs:formal ,   pt:formal ,   zh-hans:formal ,   zh-hans:casual . The older underscore spelling (  de_formal ) is still accepted and normalized to the colon form.  Sending a variant language's bare code (  de ,   fr ) resolves to its formal variant where it has one. A variant language with no formal variant rejects the bare code and lists the variants you can send explicitly instead. An unknown language is rejected with the full list of available codes.  Example     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"language\"  :   \"de:formal\"\n       }\n   }\n  Opening the Riddle at a set time  Opening the Riddle at a set time can be done by setting the   autoOpenDate  property in the preset settings. The value must be a date in the format 'YYYY-mm-dd HH:ii:ss', e.g. '2023-10-01 00:00:00'. The date must be in the timezone   Europe/Berlin (German local time) .  Example     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"autoOpenDate\"  :   \"2099-10-01 00:00:00\"\n       }\n   }\n  Closing the Riddle at a set time  Closing the Riddle at a set time can be done by setting the   autoClose  property in the preset settings. The property is an object with the following properties:     Property  Required  Type  Description  Default     date  ✓  string  The date when the Riddle should close. The value must be a date in the format 'YYYY-mm-dd HH:ii:ss', e.g. '2023-10-01 00:00:00'. The date must be in the timezone   Europe/Berlin (German local time)     resultId   integer  The ID of the result that should be shown when the Riddle is closed. Use   1  for the first result,   2  for the second result, ...; by default the first result is shown  1    isResultEnabled   boolean  Explicitly switches showing that result on or off - see   feature toggles  derived from   resultId    isEnabled   boolean  Explicitly switches the automatic closing on or off - see   feature toggles   true  (sending the object closes the Riddle at that date)  Example     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"autoClose\"  : {\n               \"date\"  :   \"2099-10-01 00:00:00\"  ,\n               \"resultId\"  :   1\n           }\n       }\n   }\n  As with   autoOpenDate , sending   date  switches the automatic closing on, and sending   resultId  switches on showing that result once the Riddle is closed.  Setting Riddle timer  The Riddle timer is a limit on how long the user has to complete the Riddle.   Note:  The Riddle timer is available for polls, quizzes, personality tests, forms and minigames. For all other Riddle types,   riddleTimer  is silently ignored in a plain create build, but rejected as an unsupported property (see the note under   All preset properties ) when strict validation applies - editing an existing Riddle, or   strictProperties: true .  Properties     Property  Required  Type  Description  Default     timeLimit  ✓  integer  The time limit in seconds     isEnabled   boolean  Explicitly switches the Riddle timer on or off - see   feature toggles   true  (sending the object enables the timer)    pauseOnNonQuestionBlocks   boolean  Whether the timer should pause on non-question blocks, such as Form blocks  true    warningAt   integer  The time in seconds when the warning should be shown. The warning is a message that tells the user how much time they have left  10    format   string  The format of the timer. Allowed values:   s  (Seconds as number),   m_s  (Minutes:Seconds),   x_m_x_s  (X minutes Y seconds)  s    shape   string  The shape of the timer. Allowed values:   circleTimer ,   barTimer  barTimer  Example     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"riddleTimer\"  : {\n               \"timeLimit\"  :   60  ,\n               \"pauseOnNonQuestionBlocks\"  :   true  ,\n               \"warningAt\"  :   10  ,\n               \"format\"  :   \"s\"  ,\n               \"shape\"  :   \"circleTimer\"\n           }\n       }\n   }\n  Setting block timer  The block timer is a limit on how long the user has to complete a block. The time limit can be set either per block or globally for all blocks.   Note:  The block timer is available for polls, quizzes, personality tests, forms and minigames. For all other Riddle types,   blockTimer  is silently ignored in a plain create build, but rejected as an unsupported property (see the note under   All preset properties ) when strict validation applies - editing an existing Riddle, or   strictProperties: true .  Properties     Property  Required  Type  Description  Default     timeLimit  ✓  integer  The time limit in seconds; not required when   individualBlockTimes  is set     pauseOnNonQuestionBlocks   boolean  Whether the timer should pause on non-question blocks, such as Form blocks  true    warningAt   integer  The time in seconds when the warning should be shown. The warning is a message that tells the user how much time they have left  10    format   string  The format of the timer. Allowed values:   s  (Seconds as number),   m_s  (Minutes:Seconds),   x_m_x_s  (X minutes Y seconds)  s    shape   string  The shape of the timer. Allowed values:   circleTimer ,   barTimer  barTimer    individualBlockTimes   int   An array of integers that specify the time limit for each block. The order of the blocks is the same as in the   blocks  property of the build object. The length of the array must be equal to the number of blocks in the Riddle     areIndividualTimesEnabled   boolean  Whether those per-block times are actually used instead of the single shared   timeLimit . Sending   individualBlockTimes  switches it on; send   false  to store the times but keep the shared limit in effect  derived from   individualBlockTimes    isEnabled   boolean  Explicitly switches the block timer on or off - see   feature toggles   true  (sending the object enables the timer)  Example  Setting a global block time limit:     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"blockTimer\"  : {\n               \"timeLimit\"  :   60  ,\n               \"pauseOnNonQuestionBlocks\"  :   true  ,\n               \"warningAt\"  :   10  ,\n               \"format\"  :   \"s\"  ,\n               \"shape\"  :   \"circleTimer\"\n           }\n       }\n   }\n  Setting a block time limit for each block:     {\n       \"blocks\"  : [\n           {\n               \"title\"  :   \"Solve this Riddle: What is the capital of France?\"  ,\n               \"type\"  :   \"SingleChoice\"  ,\n               \"items\"  : [\n                   {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   true   },\n                   {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   false   }\n               ]\n           },\n           {\n               \"title\"  :   \"Solve this Riddle: What is the capital of Germany?\"  ,\n               \"type\"  :   \"SingleChoice\"  ,\n               \"items\"  : [\n                   {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n                   {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   false   }\n               ]\n           }\n       ],\n       \"preset\"  : {\n           \"blockTimer\"  : {\n               \"individualBlockTimes\"  : [  60  ,   30  ]\n           }\n       }\n   }\n  Timer warm-up  Available for polls, quizzes, personality tests, forms and minigames: a short countdown before the timer actually starts running.     Property  Required  Type  Description  Default     isTimerWarmupEnabled   boolean  Whether the warm-up countdown runs  false    timerWarmupTime   integer  Its length in seconds; 0 or more  3  Pagination  Available for polls, quizzes, personality tests, forms and stories. Pagination is the pager and progress bar the visitor navigates the Riddle with; it is   on  by default.     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether pagination is used at all  true    pagerIsEnabled   boolean  Whether the pager (\"3 / 10\") is shown  true    progressBarIsEnabled   boolean  Whether the progress bar is shown  true    isOnlyOnQuestionBlocksEnabled   boolean  Whether it only appears on question blocks  false    isBackNavigationEnabled   boolean  Whether the visitor may navigate back  false    paginationStyle   string   Unsegmented  (one continuous bar) or   Segmented  (one segment per block)  Unsegmented   Note:  Pagination and   custom logic  are mutually exclusive - a logic tree already controls how the Riddle moves from block to block. This is not just about   isEnabled : sending   logic  in the same build config together with   any  of   pagination 's toggles set to   true  -   isEnabled ,   pagerIsEnabled ,   progressBarIsEnabled ,   isOnlyOnQuestionBlocksEnabled  or   isBackNavigationEnabled  (  paginationStyle  is pure styling and is exempt) - is rejected, naming which toggle(s) conflict. Only sending   logic  with   pagination.isEnabled: false    and  every other toggle left   false  or omitted is accepted - that combination is what lets a Riddle with custom logic be re-saved with its preset object at all.  Example:     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"pagination\"  : {\n               \"isEnabled\"  :   true  ,\n               \"paginationStyle\"  :   \"Segmented\"  ,\n               \"isBackNavigationEnabled\"  :   true\n           }\n       }\n   }\n  Live score  Quiz only: a running score displayed while the visitor answers.     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether the live score is displayed  false    type   string   RawTotal  (e.g. \"3 / 10\") or   Percentage  RawTotal    isOnResultPageEnabled   boolean  Whether it is also shown on the result page  true    isOnlyOnQuestionBlocksEnabled   boolean  Whether it only appears on question blocks  true  Right/wrong answer feedback  Quiz only: what the visitor sees right after answering a question.     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether right/wrong feedback is given at all  true    isVisualEnabled   boolean  Whether the answer is marked visually (green/red)  true    isVisualBrieflyEnabled   boolean  Whether that marking only flashes briefly instead of staying  true    isMsgEnabled   boolean  Whether a \"Correct!\"/\"Wrong!\" message is shown  true    isConfettiEnabled   boolean  Whether a correct answer triggers confetti  false  The message texts themselves can be overridden with   customStrings.correctAnswerText  and   customStrings.wrongAnswerText .  Results on blocks  Available for polls, quizzes, personality tests and forms: showing how everyone else answered, right on the block.     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether a block's own results are shown after answering  true (Poll, Quiz, Form), false (Personality)    isPercentageVisible   boolean  Whether each choice's percentage is shown  true    isVotesNumberVisible   boolean  Whether each choice's number of votes is shown  false    areTotalVotesVisible   boolean  Whether the total number of votes is shown  false  Stats before voting  Available for polls, quizzes, personality tests and forms: showing how popular the Riddle is   before  the visitor answers.     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether these stats are shown  false    areViewsVisible   boolean  Whether the number of views is shown  false    areCompletionsVisible   boolean  Whether the number of completions is shown  false  Reveal results later  Poll only: keep the results hidden until a set date, e.g. while a vote is still running.     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether the results are withheld  false    revealDate   string  The date the results become visible, in the format   YYYY-mm-dd HH:ii:ss  (timezone   Europe/Berlin )     revealLaterText   string  The message shown instead of the results until then   Single vote  Available for polls, quizzes, personality tests, forms and predictors: limit each visitor's device to one submission.     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether a device may only submit once  false    isVoteAgainEnabled   boolean  Whether the visitor may deliberately vote again anyway  depends on the Riddle type - see below   Note:    isVoteAgainEnabled  has no single default. A newly created   Quiz  starts with   true  (retaking is allowed), a newly created   Poll  with   false  (retaking is blocked), and every other type with whatever its own default preset data carries. This only applies to a Riddle created without a parent preset - one built with a   presetId  inherits the setting from that preset instead. Send the key explicitly whenever the distinction matters to you rather than relying on the type default.  IP limit  Available for the same Riddle types as single vote: a coarser limit per IP address.     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether the IP limit applies  false    countLimit   integer  How many submissions one IP may make; 1 or more  1    timePeriod   string  The window that limit applies to:   OneMinute ,   OneHour  or   OneDay  OneDay  Clock  Minigame only: an always-visible clock counting   up  (as opposed to a countdown timer).     Property  Required  Type  Description  Default     isEnabled  ✓  boolean  Whether the clock is displayed  false    format   string   s  (seconds),   m_s  (Minutes:Seconds) or   x_m_x_s  (X minutes Y seconds)  m_s    isAutoPauseEnabled   boolean  Whether the clock pauses automatically, e.g. when the tab loses focus  true    isPauseOnNonRiddleBlocksEnabled   boolean  Whether it pauses on blocks that are not part of the game  true  Open or close the Riddle right away   isRiddleOpen  is the master switch for whether the Riddle accepts submissions at all - independent of   autoOpenDate  and   autoClose , which schedule that state for a date.     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"isRiddleOpen\"  :   false\n       }\n   }\n  Scheduling an opening date closes the Riddle as a side effect, so this is also how you open one back up, or close one without inventing a date for it. Sending both in the same build config is fine:   isRiddleOpen  is applied after   autoOpenDate  and wins.  Personality result calculation  Personality tests only. Both properties pick between the same two scoring modes; they apply to the two independent ways such a test can be scored.     Property  Required  Type  Description  Default     calculationType   string  How results scored by   result points  are ranked:   TotalPointsAchieved  or   MaxAchievablePoints     calculationTypeAttributes   string  The same choice for results scored by   attributes    TotalPointsAchieved  ranks results by the raw points a participant collected for each of them.   MaxAchievablePoints  ranks them by the share of the points that were achievable for that result, which keeps results with fewer scoring answers competitive.     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"personalitySettings\"  : {\n               \"calculationType\"  :   \"MaxAchievablePoints\"\n           }\n       }\n   }\n  Custom strings   customStrings  overrides the Riddle's button and feedback texts. Sending at least one of them switches the custom-strings feature on.     Property  Required  Type  Description  Available for...  Default     isEnabled   boolean  Explicitly switches the custom strings on or off. Sending   false  keeps them stored but unused - see   feature toggles  all     startBtn   string  \"Start\" button  all     nextBtn   string  \"Next\" button  all     skipBtn   string  \"Skip\" button  all     startOverBtn   string  \"Start over\" button  all     chooseBtn   string  \"Choose\" button  all     formSubmitBtn   string  Form submit button  all     formSkipBtn   string  Form skip button  all     correctAnswerText   string  Message for a correct answer  all     wrongAnswerText   string  Message for a wrong answer  all     chooseAgainBtn   string  \"Choose again\" button  Quiz     giveUpBtn   string  \"Give up\" button  Quiz     drawBtn   string  \"Draw\" button (both sides tie)  Predictor     saveScoreBtn   string  \"Save score\" button  Predictor   Example:     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"customStrings\"  : {\n               \"startBtn\"  :   \"Let's go!\"  ,\n               \"nextBtn\"  :   \"Continue\"  ,\n               \"correctAnswerText\"  :   \"Spot on!\"\n           }\n       }\n   }\n  Footer   isRiddleFooterVisible  (default   true ) controls whether the Riddle has a footer at all. Inside it you can place your own text and logo.  Footer text     Property  Required  Type  Description  Default     text   string  The footer text; supports rich text. Sending it switches the footer text on     isEnabled   boolean  Explicitly switches the footer text on or off. Sending   false  keeps the text stored but hidden - see   feature toggles  derived from   text    isOnAllBlocksEnabled   boolean  Whether the text appears on every block instead of only the first  false  Footer branding     Property  Required  Type  Description  Default     type  ✓  string   CustomLogo  to show your own logo,   NoFooter  to remove Riddle's branding without adding one  NoFooter    logo   string|object  The logo to display. See   Use media     mediaOrientation   string  How the logo is cropped:   Wide ,   Square ,   Tall  or   Original  Original    maxWidth   integer  Maximum logo width in pixels; 1 or more  200    logoPosition   string   Left ,   Center  or   Right  Center    link   string  Where clicking the logo takes the visitor   Example:     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"isRiddleFooterVisible\"  :   true  ,\n           \"footerText\"  : {\n               \"text\"  :   \"Sponsored by Example Inc.\"  ,\n               \"isOnAllBlocksEnabled\"  :   true\n           },\n           \"footerBranding\"  : {\n               \"type\"  :   \"CustomLogo\"  ,\n               \"logo\"  :   \"https://httpbin.io/image/jpeg\"  ,\n               \"logoPosition\"  :   \"Left\"  ,\n               \"maxWidth\"  :   120  ,\n               \"link\"  :   \"https://www.your-website.com\"\n           }\n       }\n   }\n  Riddle-level ads  Unlike the    Ad  block  (which is a block of its own in the Riddle),   ads  places a fixed ad slot above and/or below the whole Riddle. Supplying either slot switches ads on.     Property  Required  Type  Description  Default     adTop   object  The slot above the Riddle     adBottom   object  The slot below the Riddle     isEnabled   boolean  Explicitly switches Riddle-level ads on or off. Sending   false  keeps both slots configured but unused - see   feature toggles   Each slot is configured with   either  a project ad slot or a custom iframe - setting one clears the other:     Property  Required  Type  Description  Default     projectSlot   object   slotId  (integer, required) and optional   variables  (key-value overrides) of one of your   project ad slots     iframe   object   url  (required) and optional   height  in pixels (1 or more)     isEnabled   boolean  Explicitly switches this single slot on or off, independently of   ads.isEnabled    Note:    projectSlot  requires the Riddle to belong to a team, since the slot IDs are the team's own.  Example:     {\n       \"blocks\"  : [  ...  ],\n       \"preset\"  : {\n           \"ads\"  : {\n               \"adTop\"  : {\n                   \"projectSlot\"  : {\n                       \"slotId\"  :   123456  ,\n                       \"variables\"  : {\n                           \"ad-variable-key1\"  :   \"override-value1\"\n                       }\n                   }\n               },\n               \"adBottom\"  : {\n                   \"iframe\"  : {\n                       \"url\"  :   \"https://ads.your-website.com/ad.html\"  ,\n                       \"height\"  :   250\n                   }\n               }\n           }\n       }\n   }\n  External content privacy banner  Available for polls, quizzes, personality tests, forms and stories: before an embedded YouTube/X/Vimeo item is loaded, the visitor is asked for consent.     Property  Required  Type  Description  Default     isExternalContentBannerEnabled   boolean  Whether the banner is shown  false    privacyTextYoutube   string  Custom text for YouTube embeds (not available for stories)     privacyTextTwitter   string  Custom text for X/Twitter embeds     privacyTextVimeo   string  Custom text for Vimeo embeds     privacyTextButton   string  Label of the button that loads the content anyway   Full example  A poll with a preset object built into it: German as its formal variant, a segmented pager the visitor can navigate back through, an opening date, and returning visitors remembered.     {\n       \"type\"  :   \"Poll\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Pasta poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"title\"  :   \"Spaghetti or Fusilli?\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Spaghetti\"   },\n                       {   \"title\"  :   \"Fusilli\"   }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"title\"  :   \"Thanks for voting!\"\n           },\n           \"preset\"  : {\n               \"language\"  :   \"de:formal\"  ,\n               \"autoOpenDate\"  :   \"2026-09-01 00:00:00\"  ,\n               \"pagination\"  : {\n                   \"isEnabled\"  :   true  ,\n                   \"paginationStyle\"  :   \"Segmented\"  ,\n                   \"isBackNavigationEnabled\"  :   true\n               },\n               \"rememberUser\"  : {\n                   \"isEnabled\"  :   true  ,\n                   \"isDsgvoAccepted\"  :   true\n               }\n           }\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":314,"path":315,"dir":263,"title":316,"description":317,"keywords":318,"body":328},"content:15.Api:4.Build Riddles:4.Settings configuration:3.Logic settings.md","/api/build-riddles/settings-configuration/logic-settings","Logic settings - Build Riddles","Learn how to build custom logic flows for your Riddles via API",[319,320,321,322,323,324,325,326,327,133],"Limits and constraints","Default logic","Prerequisites","Logic settings structure / properties","Pitfalls","Reading the logic back","Changing the logic of an existing Riddle","Troubleshooting / Error codes","Answer branching step by step","  Logic settings   Just like in the Riddle creator , you can set up custom logic flows for your Riddles using the Builder API.  Custom logic flows are available for the following Riddle types via API:    Quiz   Poll   Form   Story  Personality tests, predictors, minigames and leaderboards do   not  support custom logic - sending a   logic  property for one of them is rejected with   Logic configuration is not allowed for Riddle type \"\u003Ctype>\" .  You can branch by answers (typically on SingleChoice, MultipleChoice, and standalone Form   Dropdown  fields), by a condition on a block's answer or a form field's value, or by block/total score. The following will be added soon:   Branching by a data layer variable  Any other suggestions? Please get in touch via support chat or send an email to   hello@riddle.com .  Limits and constraints    Block count:  custom logic is only accepted for Riddles with up to   250 blocks  (building a logic tree is recursive, so the cost grows super-linearly). Riddles above that limit have to use the default linear logic. The overall build limit of   500 blocks  still applies on top of that.   Pagination:  custom logic and   pagination  are mutually exclusive. Sending   logic  together with   preset.pagination.isEnabled: true  is rejected - a paginated Riddle shows all blocks on one page, which has no meaningful branching.   Flashcards:  a Quiz that contains a   Flashcard  block only accepts   linear  logic (see   RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_LINEAR_ONLY_ALLOWED  below).   Story:  a Story Riddle only accepts   linear  logic - there is nothing to branch on (no answers, scores, or form fields), so   answer ,   condition , and   score  branching are all rejected.   Every block has to be used:  every block in the   blocks  array must be reachable somewhere in the tree, otherwise the build is rejected (see   RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_UNUSED_BLOCKS ).  Default logic  When you create a Riddle via the Builder API without specifying any logic settings, the Riddle will have a default linear logic flow. This means that the blocks will be shown in the exact order they are defined in the   blocks  array of the build configuration.  Prerequisites  To be able to work with the logic settings efficiently, it is advised to read about   assigning custom IDs  to blocks and answer items first. This makes it easier to reference the blocks and answer items in the following logic settings.  Logic settings structure / properties  The logic settings are defined in the   logic  property in the   build  configuration, next to the   blocks  and   result /  results  properties:     {\n       \"type\"  :   \"Quiz\"  ,\n       \"build\"  : {\n           \"title\"  :   \"My quiz with logic\"  ,\n           \"blocks\"  : [\n               \"...\"  ,\n               \"...\"  ,\n               \"...\"\n           ],\n           \"results\"  : [\n               \"...\"\n           ],\n           \"logic\"  : {\n               \"...logic tree structure...\"\n           }\n       }\n   }\n  The logic settings structure can be compared to a \"tree\" where the root of the tree is the start block, and each branch represents a possible path through the Riddle based on user interactions. This means it can nest indefinitely, as long as there are available blocks in the build configuration.  You can use four types of branching:  Linear 'branching'     Property  Required  Type  Description  Default     blockId  ✓  integer  The ID of the block where this logic layer starts. Can reference any block, for example even   Content     branchingType   string  The type of branching to use. For linear branching it is set to   linear , but can also be omitted due to being the default value  linear    next   object  An object defining the next block to show after the block defined in   blockId  has been completed. Send   null  (or leave it out) to mark this layer as the end of its path  null   blockId  must be a   positive integer  that exists in the   blocks  array;   branchingType  is matched case-insensitively (  Answer  works just as well as   answer ).   Example: Sequence of 4 linear blocks     {\n       \"blockId\"  :   1  ,\n       \"next\"  : {\n           \"blockId\"  :   2  ,\n           \"next\"  : {\n               \"blockId\"  :   3  ,\n               \"next\"  : {\n                   \"blockId\"  :   4\n               }\n           }\n       }\n   }\n  In spoken form: Show block ID 1, then block ID 2, then block ID 3, then block ID 4 - and end the Riddle there.  Answer branching     Property  Required  Type  Description  Default     blockId  ✓  integer  The ID of the block where this logic layer starts. Can only reference blocks which offer selectable answers to branch on; see below     branchingType  ✓  string  The type of branching to use. For answer branching, it is set to   answer  linear    rules  ✓  object   An array of at least one rule object defining the branching logic. To see the structure of each rule, see below   Which blocks can be branched on  The block referenced by   blockId  has to expose selectable answer items - the API validates your   answers  against exactly those items:    Question blocks  with answer items work, e.g.   SingleChoice  and   MultipleChoice .   Form fields:  only a   standalone   Dropdown  field  can be branched on. Any other form field - including a whole   FormBuilder  block - is rejected with   Answer logic branching is currently only allowed with standalone Dropdown form fields (Found \u003Ctype>).  Blocks that carry no answer items at all (e.g. a   Content  block) are rejected with   Answer logic block must refer to a question block with choices/answers, found \"\u003Ctype>\" block.  Such blocks can still be used in   linear  layers.  Defining rules   Note:  Each rule itself is also either a linear or answer branching, meaning it can contain a   next  OR   rules  property to define what happens after the block defined in   blockId  has been completed.  Properties exclusive to the rule object:     Property  Required  Type  Description  Default     answers  ✓  string  |int   A non-empty array of answers that trigger this rule. You can use either the answer text or the given answer ID to identify the answer   Rules for   answers :   Answer texts are matched   exactly  (no case-insensitive or trimmed matching) - if the value matches neither a title nor an ID, the error lists all valid choices of that block.  Every answer may only be used   once per logic layer : repeating the same answer in another rule of the same layer, or twice within the same rule, is rejected as a non-unique rule.  Not every answer of a block needs its own rule, but every rule needs at least one answer.   Example: Answer branching with linear next     {\n       \"answers\"  : [  \"Answer 1\"  ,   \"Answer 2\"  ],\n       \"blockId\"  :   2  ,\n       \"next\"  : {\n           \"blockId\"  :   3\n       }\n   }\n  In spoken form: If the user selects \"Answer 1\" or \"Answer 2\" show block with ID 2, then after completing that block, show block with ID 3.   Example: Answer branching, followed by answer branching / rules     {\n       \"answers\"  : [  \"Answer 1\"  ,   \"Answer 2\"  ],\n       \"blockId\"  :   2  ,\n       \"branchingType\"  :   \"answer\"  ,\n       \"rules\"  : [\n          \"...\"\n       ]\n   }\n  In spoken form: If the user selects \"Answer 1\" or \"Answer 2\" show block with ID 2, then after completing that block, follow the rules defined in the   rules  array (and so on).   Example: First linear branching, then answer branching, then linear branching     {\n       \"blockId\"  :   1  ,\n       \"next\"  : {\n           \"blockId\"  :   2  ,\n           \"branchingType\"  :   \"answer\"  ,\n           \"rules\"  : [\n               {\n                   \"answers\"  : [  \"Answer 1\"  ],\n                   \"blockId\"  :   3  ,\n                   \"next\"  : {\n                       \"blockId\"  :   4\n                   }\n               },\n               {\n                   \"answers\"  : [  \"Answer 2\"  ],\n                   \"blockId\"  :   5\n               }\n           ]\n       }\n   }\n  In spoken form: Start with block ID 1, then show block ID 2. If the user selects \"Answer 1\", show block ID 3, then block ID 4. If the user selects \"Answer 2\", show block ID 5.  Condition branching     Property  Required  Type  Description  Default     blockId  ✓  integer  The ID of the block this condition evaluates. Can reference a question block's answer, or a form field's value (including a field nested inside a   FormBuilder  block)     branchingType  ✓  string  The type of branching to use. For condition branching, it is set to   condition  linear    condition  ✓  object  An object with   field  (the answer/value to compare, e.g. an answer's title or ID, or use   \"score\"  to compare a question block's own score),   operator  (see below), and, unless the operator is a standalone check like   isAnswered ,   value  (the value to compare against)     ifTrue   object  The next logic layer to follow if the condition evaluates to true. Same rules as   next /  rules  - it can itself be linear, answer, condition, or score branching  null    ifFalse   object  The next logic layer to follow if the condition evaluates to false  null  Operators  The allowed   operator  values depend on the kind of field   blockId  points at:     Field kind  Allowed operators    Question block answer   equals ,   notEquals ,   isAnswered ,   isNotAnswered   Question block score (  field: \"score\" )   equals ,   notEquals ,   greaterThan ,   greaterThanOrEqual ,   lessThan ,   lessThanOrEqual   Form text field   equals ,   notEquals ,   contains ,   notContains ,   isAnswered ,   isNotAnswered   Form number field   equals ,   notEquals ,   greaterThan ,   greaterThanOrEqual ,   lessThan ,   lessThanOrEqual ,   isAnswered ,   isNotAnswered   Form select/dropdown/radio field   equals ,   notEquals ,   isAnswered ,   isNotAnswered   Form checkbox field   isChecked ,   isNotChecked   Example: Condition branching on a SingleChoice answer     {\n       \"blockId\"  :   1  ,\n       \"branchingType\"  :   \"condition\"  ,\n       \"condition\"  : {\n           \"field\"  :   \"Berlin\"  ,\n           \"operator\"  :   \"equals\"  ,\n           \"value\"  :   true\n       },\n       \"ifTrue\"  : {\n           \"blockId\"  :   2\n       },\n       \"ifFalse\"  : {\n           \"blockId\"  :   3\n       }\n   }\n  In spoken form: Show block ID 1. If the user picked \"Berlin\" there, continue with block ID 2, otherwise continue with block ID 3.   Referencing a form field nested inside a   FormBuilder  block:  use   \"\u003CblockId>_\u003CfieldId>\"  as the condition's   blockId  is still the   FormBuilder  block itself, while the field being evaluated is identified this way in the underlying   field /  value  targeting - see   custom IDs  for how field IDs are assigned.  Score branching     Property  Required  Type  Description  Default     blockId  ✓  integer  The ID of the block this score is evaluated for. For   scoreType: \"block\"  this is the block whose own score is checked; for   scoreType: \"total\"  it can be any block, since the running total is riddle-wide     branchingType  ✓  string  The type of branching to use. For score branching, it is set to   score  linear    scoreType  ✓  string   total  branches on the cumulative score across every block answered so far (Quiz only);   block  branches on the score of this node's own block only     ranges  ✓  object   An array of at least one range object mapping a   [min, max]  score interval to a next block. Ranges must not overlap and each range's   min  must be less than or equal to its   max   Each range object has   min  (integer),   max  (integer),   blockId  (the block to show for this range) and, like an answer rule, an optional   next /  rules /  ifTrue +  ifFalse /  ranges  describing what comes after.   Example: Score branching on the running total (Quiz only)     {\n       \"blockId\"  :   1  ,\n       \"branchingType\"  :   \"score\"  ,\n       \"scoreType\"  :   \"total\"  ,\n       \"ranges\"  : [\n           {\n               \"min\"  :   0  ,\n               \"max\"  :   50  ,\n               \"blockId\"  :   2\n           },\n           {\n               \"min\"  :   51  ,\n               \"max\"  :   100  ,\n               \"blockId\"  :   3\n           }\n       ]\n   }\n  In spoken form: Show block ID 1. If the total score so far is 0-50 points, continue with block ID 2; if it is 51-100 points, continue with block ID 3.   scoreType: \"total\"  is only available on a Quiz - Poll and Form have no running score to branch on.  Pitfalls  Building the logic settings can be tricky. Here are some tips to avoid common pitfalls:   Result blocks are   not  part of the logic tree in the API. Instead, they will always be shown at the end of the Riddle logic tree, regardless of the path taken. An end of the logic tree can be defined by adding a logic layer with no   next  property or with the   next  property set to   null .  In a   Poll  or   Form , every end of a path automatically leads to the first result page. In a   Quiz , the result is picked by the   minPercentage /  maxPercentage  ranges of your result pages instead, no matter which path the visitor took.  The   same block may be referenced from several different branches  - that is how two rules can converge on the same follow-up question (see the full example below, where both rules end on block 3). What is not allowed is referencing a block again   below itself  on the same path, which would create an infinite loop.  Make sure to use   custom IDs  for blocks and answers to make it easier to reference them in the logic settings.  Reading the logic back  When you read a Riddle back as a build configuration, the   logic  property behaves as follows:   A Riddle with the   default linear logic  does not return a   logic  property at all - leaving it out rebuilds exactly the same default.   Custom logic  built through the API is returned in the same shape you sent (linear, answer, condition, or score - and any nested combination of them), and can be sent back unchanged.   answers  are always returned as   answer IDs , never as answer texts.  Logic that was configured in the Creator but has no equivalent in a builder config - a condition builder rule targeting a data layer variable or magic variable, or logic referencing question bank / embedded form select blocks - cannot be expressed. In that case the whole   logic  property is reported as unsupported instead of being returned partially, because a partial tree could not be rebuilt into the same Riddle.  Changing the logic of an existing Riddle  When   editing a Riddle ,   logic  is replaced as a whole if you send it and kept as it is if you omit it - there is no per-node merge. Two edit-only rules apply:    Resetting:    \"logic\": {\"$reset\": true}  discards the custom logic and falls back to the default linear flow, regenerated from the current block order. It is exclusive - combining   $reset  with any other key inside   logic  is rejected, and it is only accepted when editing (never in a   POST /riddle-builder  request).   Deleting a referenced block:  deleting a block that the custom logic still points at is rejected unless the same request either supplies a replacement tree or resets the logic. See    RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_DELETED_BLOCK_STILL_REFERENCED  below.  A Riddle whose logic was reset returns no   logic  property when read back, exactly like any other Riddle on the default flow.  Troubleshooting / Error codes  The logic settings throws unique error codes which can only occur in this context.  Not sure how exception handling works?   Check out the basic API exception handling .  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_CIRCULAR_REFERENCE  A circular reference was detected in the logic settings. This means that a block is referenced again going 'up' the logic tree, which would create an infinite loop.   Example faulty logic settings:     {\n       \"blockId\"  :   1  ,\n       \"next\"  : {\n           \"blockId\"  :   2  ,\n           \"next\"  : {\n               \"blockId\"  :   1\n           }\n       }\n   }\n  In spoken form: Show block ID 1, then block ID 2, then block ID 1 again - which sends the visitor around the same two blocks forever.  The error message names the offending node and spells out the loop, so you do not have to walk your own configuration to find it:     Circular reference detected: logic (block ID 1) points back at block ID 1, which already appears earlier on this branch (1 -> 2 -> 1). Point it at another block, or end the branch instead.\n  The node is named the same way every other logic error names it -   logic (block ID 1) , plus its   branchingType  when the node states one, e.g.   logic (block ID 1, branchingType: \"answer\") . The path in brackets reads in the direction you wrote it, from the block that first appears on the branch to the reference that closes the loop.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_INVALID_RULE  The   answers  provided in an answer branching rule object is either empty or references answers that do not exist in the corresponding block's   items  array.   Example faulty logic settings:     {\n       \"blockId\"  :   1  ,\n       \"branchingType\"  :   \"answer\"  ,\n       \"rules\"  : [\n           {\n               \"answers\"  : [],   // empty answers array\n               \"blockId\"  :   2\n           },\n           {\n               \"answers\"  : [  \"Non-existing answer\"  ],   // answer does not exist in block's items\n               \"blockId\"  :   3\n           }\n       ]\n   }\n  In spoken form: the first rule says \"if the user selects nothing in particular\", and the second one branches on an answer block ID 1 does not offer - neither can ever trigger.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_NON_UNIQUE_RULES  The   answers  provided in an answer branching rule object are not unique. This means that the same answer is referenced in multiple rules of the same logic layer.   Example faulty logic settings:     {\n       \"blockId\"  :   1  ,\n       \"branchingType\"  :   \"answer\"  ,\n       \"rules\"  : [\n           {\n               \"answers\"  : [  \"Answer 1\"  ,   \"Answer 2\"  ],\n               \"blockId\"  :   2\n           },\n           {\n               \"answers\"  : [  \"Answer 2\"  ,   \"Answer 3\"  ],   // \"Answer 2\" is referenced twice\n               \"blockId\"  :   3\n           }\n       ]\n   }\n  In spoken form: \"Answer 2\" would send the visitor to block ID 2 and to block ID 3 at the same time.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_NON_EXISTING_BLOCK  A   blockId  in the logic settings references a block that does not exist in the   blocks  array of the build configuration.   Example faulty logic settings:     {\n       \"blockId\"  :   999  ,   // block with ID 999 does not exist in blocks array\n       \"next\"  : {\n           \"blockId\"  :   2\n       }\n   }\n  In spoken form: Start with a block that the Riddle does not contain, then show block ID 2.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_UNUSED_BLOCKS  Some blocks defined in the   blocks  array of the build configuration are not referenced in the logic settings. This means that there is no possible way for a user to reach these blocks when taking the Riddle. In the Riddle Creator this is indicated by a warning icon in the publish step, in the Builder API this results in an error to avoid building Riddles with unnecessary/unused blocks. The message lists the block IDs concerned:   \"The built logic tree does not use all Riddle blocks. Unused block IDs: 4, 5\" .  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_LINEAR_ONLY_ALLOWED  This can happen in two scenarios: you are trying to use non-linear (answer/condition/score) branching in a Quiz that contains Flashcard blocks - disallowed because Flashcards have complex logic themselves which does not work with non-linear logic - or you are trying to use non-linear branching on a Story Riddle, which has nothing to branch on.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_DEAD_ENDS  The built logic tree contains a dead end: a path that neither ends the flow nor leads anywhere. The message names the block it stops at, so you can go straight to that node:     The built logic tree contains a dead end at block ID 3: it neither ends the flow nor leads anywhere. Please check your logic configuration for that block.\n  Give that node a   next  - or, on a branching node, a target for every branch it can take.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_INVALID_NODE  A logic node is invalid. This can happen if the node is missing a   blockId , if the   blockId  is not a positive integer, or if the   branchingType  is not a recognized value.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_CONDITION_INVALID_MAPPABLE  A condition branching node's   condition.field  does not refer to a usable value - for example it references a form field that doesn't exist on the   blockId  block, or a question block that carries no answer items/score to condition on.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_CONDITION_OPERATOR_NOT_ALLOWED  A condition branching node's   condition.operator  is not one of the operators allowed for the kind of field   condition.field  refers to. See the operator table under   Condition branching  above.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_SCORE_RANGE_OVERLAP  A score branching node's   ranges  contains two ranges that overlap, or a range whose   min  is greater than its   max .   Example faulty logic settings:     {\n       \"blockId\"  :   1  ,\n       \"branchingType\"  :   \"score\"  ,\n       \"scoreType\"  :   \"total\"  ,\n       \"ranges\"  : [\n           {   \"min\"  :   0  ,   \"max\"  :   50  ,   \"blockId\"  :   2   },\n           {   \"min\"  :   40  ,   \"max\"  :   100  ,   \"blockId\"  :   3   }\n       ]\n   }\n  In spoken form: a score of 45 points would match both ranges at once, so there is no telling whether block ID 2 or block ID 3 comes next.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_DELETED_BLOCK_STILL_REFERENCED  Only occurs when   editing a Riddle : the request deletes a block (  \"$delete\": true ) that the Riddle's   custom  logic still references, and does not resolve that in the same request. The error names which deleted block is still referenced by which logic node.  Fix it by sending, in the same request, either a full replacement   logic  tree that no longer references the block, or   \"logic\": {\"$reset\": true} . This never happens while the Riddle still uses the default linear logic - that logic is regenerated from the current block order on every build.  RIDDLE_BUILDER_BLOCK_PROPERTY_LOGIC_RESET_CONFLICT   \"logic\": {\"$reset\": true}  was combined with other logic configuration in the same object. Either reset the logic or supply a full replacement tree, not both.  Answer branching step by step   Riddle build configuration (without logic settings in first step):     {\n       \"type\"  :   \"Quiz\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Logic example (Builder API)\"  ,\n           \"blocks\"  : [\n               {\n                   \"id\"  :   1  ,\n                   \"title\"  :   \"What's the capital of Germany?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Leipzig\"  ,   \"isCorrect\"  :   false   }\n                   ]\n               },\n               {\n                   \"id\"  :   2  ,\n                   \"title\"  :   \"What are valid colors in German?\"  ,\n                   \"type\"  :   \"MultipleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"rot\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"schwarz\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"nero\"  ,   \"isCorrect\"  :   false   }\n                   ]\n               },\n               {\n                   \"id\"  :   3  ,\n                   \"title\"  :   \"Order the following colors from lightest to darkest.\"  ,\n                   \"type\"  :   \"Order\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"red\"   },\n                       {   \"title\"  :   \"blue\"   },\n                       {   \"title\"  :   \"green\"   }\n                   ]\n               }\n           ],\n           \"results\"  : [\n               {\n                   \"title\"  :   \"Thanks for taking the quiz!\"  ,\n                   \"minPercentage\"  :   0  ,\n                   \"maxPercentage\"  :   100\n               }\n           ]\n       }\n   }\n  The quiz above consists of three question blocks and one result block. For this example we want to branch based on the \"What's the capital of Germany?\" question. If the user answers \"Berlin\", we want to show the second question (\"What are valid colors in German?\"). If the user answers \"Lissabon\" or \"Leipzig\", we want to skip the second question and go directly to the third question (\"Order the following colors from lightest to darkest.\").  The logic tree / settings then look like this:     {\n       \"blockId\"  :   1  ,\n       \"branchingType\"  :   \"answer\"  ,\n       \"rules\"  : [\n           {\n               \"answers\"  : [  \"Berlin\"  ],\n               \"blockId\"  :   2  ,\n               \"next\"  : {\n                   \"blockId\"  :   3\n               }\n           },\n           {\n               \"answers\"  : [  \"Lissabon\"  ,   \"Leipzig\"  ],\n               \"blockId\"  :   3\n           }\n       ]\n   }\n  In spoken form: Show block ID 1 (\"What's the capital of Germany?\"). If the user answers \"Berlin\", show block ID 2 and then block ID 3. If the user answers \"Lissabon\" or \"Leipzig\", skip straight to block ID 3 and end there.   Note:  Result blocks are   not  part of the logic tree in the API. Instead, they will always be shown at the end of the Riddle logic tree, regardless of the path taken. An end of the logic tree can be defined by adding a logic layer with no   next  property or with the   next  property set to   null .  Optional: Referencing answers by ID  As with the   blocks , the answer items can also be referenced by their ID instead of the answer text which makes it less confusing and more deterministic when creating logic rules for complex build configurations.   Learn more   Step by step guide to convert from answer text to answer IDs:   Add explicit IDs to the answers in the   items  property of the SingleChoice question block:     {\n       \"id\"  :   1  ,\n       \"title\"  :   \"What's the capital of Germany?\"  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"items\"  : [\n           {   \"id\"  :   11  ,   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n           {   \"id\"  :   22  ,   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n           {   \"id\"  :   33  ,   \"title\"  :   \"Leipzig\"  ,   \"isCorrect\"  :   false   }\n       ]\n   }\n   Use the answer IDs (i.e. 11, 22, 33) in the logic settings instead of the answer text:     {\n       \"blockId\"  :   1  ,\n       \"branchingType\"  :   \"answer\"  ,\n       \"rules\"  : [\n           {\n               \"answers\"  : [  11  ],\n               \"blockId\"  :   2  ,\n               \"next\"  : {\n                   \"blockId\"  :   3\n               }\n           },\n           {\n               \"answers\"  : [  22  ,   33  ],\n               \"blockId\"  :   3\n           }\n       ]\n   }\n  In spoken form: exactly the same flow as above - if the user picks answer 11 (\"Berlin\"), show block ID 2 and then block ID 3; if they pick answer 22 or 33, go straight to block ID 3.  Full example  Two complete request bodies that build the logic described above.   A quiz that branches on the answer to its first question. Whoever answers \"Berlin\" also gets the colors question before the ordering question, whoever answers \"Lissabon\" or \"Leipzig\" goes straight to the ordering question, and both paths end on the same result page.     {\n       \"type\"  :   \"Quiz\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Logic example (Builder API)\"  ,\n           \"blocks\"  : [\n               {\n                   \"id\"  :   1  ,\n                   \"title\"  :   \"What's the capital of Germany?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Leipzig\"  ,   \"isCorrect\"  :   false   }\n                   ]\n               },\n               {\n                   \"id\"  :   2  ,\n                   \"title\"  :   \"What are valid colors in German?\"  ,\n                   \"type\"  :   \"MultipleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"rot\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"schwarz\"  ,   \"isCorrect\"  :   true   },\n                       {   \"title\"  :   \"nero\"  ,   \"isCorrect\"  :   false   }\n                   ],\n                   \"explanation\"  : {\n                       \"title\"  :   \"Correct!\"  ,\n                       \"description\"  :   \"Only 'rot' and 'schwarz' are valid colors in German\"\n                   }\n               },\n               {\n                   \"id\"  :   3  ,\n                   \"title\"  :   \"Order the following colors from lightest to darkest.\"  ,\n                   \"type\"  :   \"Order\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"red\"   },\n                       {   \"title\"  :   \"blue\"   },\n                       {   \"title\"  :   \"green\"   }\n                   ],\n                   \"itemsShuffled\"  :   true  ,\n                   \"guesses\"  :   3\n               }\n           ],\n           \"logic\"  : {\n               \"blockId\"  :   1  ,\n               \"branchingType\"  :   \"answer\"  ,\n               \"rules\"  : [\n                   {\n                       \"answers\"  : [  \"Berlin\"  ],\n                       \"blockId\"  :   2  ,\n                       \"next\"  : {\n                           \"blockId\"  :   3\n                       }\n                   },\n                   {\n                       \"answers\"  : [  \"Lissabon\"  ,   \"Leipzig\"  ],\n                       \"blockId\"  :   3\n                   }\n               ]\n           },\n           \"results\"  : [\n               {\n                   \"title\"  :   \"Thanks for taking the quiz!\"  ,\n                   \"minPercentage\"  :   0  ,\n                   \"maxPercentage\"  :   100\n               }\n           ]\n       }\n   }\n   A poll that branches on a standalone form dropdown field. The visitor picks their favourite programming language and sees only the follow-up question for that language, Python leading to block ID 2, JavaScript to block ID 3 and Java to block ID 4, before the Riddle ends.     {\n       \"type\"  :   \"Poll\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Programming Language Quiz\"  ,\n           \"blocks\"  : [\n               {\n                   \"id\"  :   1  ,\n                   \"title\"  :   \"Select your favorite programming language:\"  ,\n                   \"type\"  :   \"FormField\"  ,\n                   \"fieldType\"  :   \"Dropdown\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Python\"   },\n                       {   \"title\"  :   \"JavaScript\"   },\n                       {   \"title\"  :   \"Java\"   }\n                   ]\n               },\n               {\n                   \"id\"  :   2  ,\n                   \"title\"  :   \"Why do you like Python?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Easy to learn\"   },\n                       {   \"title\"  :   \"Great libraries\"   },\n                       {   \"title\"  :   \"Versatile\"   }\n                   ]\n               },\n               {\n                   \"id\"  :   3  ,\n                   \"title\"  :   \"Why do you like JavaScript?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Web development\"   },\n                       {   \"title\"  :   \"Versatile\"   },\n                       {   \"title\"  :   \"Large community\"   }\n                   ]\n               },\n               {\n                   \"id\"  :   4  ,\n                   \"title\"  :   \"Why do you like Java?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Platform independence\"   },\n                       {   \"title\"  :   \"Strong typing\"   },\n                       {   \"title\"  :   \"Enterprise use\"   }\n                   ]\n               }\n           ],\n           \"logic\"  : {\n               \"blockId\"  :   1  ,\n               \"branchingType\"  :   \"answer\"  ,\n               \"rules\"  : [\n                   {\n                       \"answers\"  : [  \"Python\"  ],\n                       \"blockId\"  :   2\n                   },\n                   {\n                       \"answers\"  : [  \"JavaScript\"  ],\n                       \"blockId\"  :   3\n                   },\n                   {\n                       \"answers\"  : [  \"Java\"  ],\n                       \"blockId\"  :   4\n                   }\n               ]\n           },\n           \"result\"  : {\n               \"title\"  :   \"Thanks for sharing your preferences!\"\n           }\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":330,"path":331,"dir":332,"title":333,"description":334,"keywords":335,"body":340},"content:15.Api:4.Build Riddles:5.Advanced features:1.Use media.md","/api/build-riddles/advanced-features/use-media","advanced-features","Use media - Build Riddles","Learn how to use media in your Riddle via API",[336,337,338,339],"Adding images / videos / audio","Adding social media content","Checking media without uploading it","Reading media back","  Use media  You can add media, such as images, videos, audio, and social media content, to any block and result in your riddle.  Every   media  property accepts either   a   plain URL string  - the shortcut for an image, e.g.   \"media\": \"https://httpbin.io/image/jpeg\" , or  a   media object  with a   type  and the properties of that type, e.g.   \"media\": {\"type\": \"Image\", \"url\": \"...\"} .  These are the accepted   type  values:      type  What it is     Image  An uploaded image    Video  An uploaded video (a GIF is uploaded as a video, too)    Audio  An uploaded audio file    YouTube  An embedded YouTube video    Vimeo  An embedded Vimeo video    X  An embedded X (  formerly Twitter ) post   type  is matched   case-insensitively , so   Image ,   image  and   IMAGE  are all accepted. An unknown value is rejected with   Invalid media type: \u003Cvalue> , a media object without a   type  with   Missing property type in Media object .   Note:  A media object has   no   id  you can set. A media file's id is assigned by our CDN when the file is uploaded, so it can neither be chosen nor overridden - sending one is rejected with   Property \"id\" cannot be set on a Media object: a media id is assigned by the Riddle Upload API when the file is uploaded and can neither be chosen nor overridden. Reference the media by its \"url\" instead. . Media is always referenced by its   url , which is also the only thing a Riddle read back as a build configuration gives you.   Note:  The plain-URL shortcut always means an   image . Pointing it at a video or audio file is rejected with   For simple media (only supplying an URL for the \"media\" property), only images are allowed.  - use the object form with the matching   type  instead.  Adding images / videos / audio  Any media you add to the API payload is downloaded, re-hosted on the Riddle CDN, and transcoded: images are converted to WebP. This ensures your media is optimized for the web.  The following media types are supported:   Images (JPG, PNG, GIF)  Videos (MP4)  Audio (MP3)  Other image/video formats may work, but are not officially supported. If you want to use other media types, please contact us at   hello@riddle.com .  Requirements for media URLs  Before anything is downloaded, every media URL of type   Image ,   Video  or   Audio  is probed once. A URL is only accepted if:   it is a valid,   publicly reachable    http(s)  URL. URLs pointing at a private/internal address are always rejected.  the request finishes within the probe timeouts (5 seconds to connect, 10 seconds in total).  the final response status is a success status and its   content type  is an   image/* ,   video/*  or   audio/*  type.  it redirects   at most once . A longer redirect chain is treated as unreachable - use the final URL directly.  A URL that fails any of these checks is rejected with   Given media URL leads to a non-reachable source (\u003Curl>) , naming the property it belongs to.  On top of that, the content type has to match the   type  you declared: pointing an   Image  at an MP4 fails with   Media URL of property \"url\" must point to a file of type \"image\". Received: video .   Example SingleChoice object:     {\n       \"type\"  :   \"SingleChoice\"  ,\n       \"title\"  :   \"What is the capital of France?\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Madrid\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   true   }\n       ],\n       \"media\"  :   \"https://httpbin.io/image/png\"\n   }\n  Upload limit  Uploading media slows down the building process and our servers. To ensure a smooth experience, we have set a limit of 15 media per Riddle. If you need more media, please contact us at   hello@riddle.com .  The limit counts   distinct URLs , not media properties: using the same URL on several blocks costs one upload, and the file is downloaded and stored only once. Exceeding it fails the build with   Maximum of 15 media per build reached.  Embedded social media (  YouTube ,   Vimeo ,   X ) is not uploaded at all and therefore does not count towards the limit.  Advanced properties  You can further customize how your media is displayed by:   setting alt tags for accessibility and SEO  setting attribution metadata to credit the source  setting the background or overlay color (Image only)  To do this, convert the   media  property to an object and add the following properties:     Property  Required  Type  Description  Default     type  ✓  string  Set to   Image ,   Video , or   Audio     url  ✓  string  The URL of the media you want to add     altTag   string  The alt tag of the media (for accessibility and SEO)  \"\"    attributionText   string  The attribution text of the media (e.g. photographer name)  \"\"    attributionUrl   string  A link to the source of the media (e.g. photographer website or profile)  \"\"    backgroundColor   string   Image only.  A CSS color code (e.g.   #000000  or   rgba(0,0,0,0.5) ) to use as background color for the media  rgba(255,255,255,0)    overlayColor   string   Image only.  A CSS color code (e.g.   #000000  or   rgba(0,0,0,0.5) ) to use as overlay color for the media  rgba(255,255,255,0)   altTag ,   attributionText  and   attributionUrl  are available for   Image ,   Video  and   Audio  alike; the two colors only apply to images.   Example object:     {\n       \"type\"  :   \"SingleChoice\"  ,\n       \"title\"  :   \"What is the capital of France?\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Madrid\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   true   }\n       ],\n       \"media\"  : {\n           \"type\"  :   \"Image\"  ,\n           \"url\"  :   \"https://httpbin.io/image/jpeg\"  ,\n           \"altTag\"  :   \"An image showing the Eiffel Tower in Paris\"  ,\n           \"attributionText\"  :   \"Photo by John Doe\"  ,\n           \"attributionUrl\"  :   \"https://johndoe.com\"  ,\n           \"backgroundColor\"  :   \"#000000\"  ,\n           \"overlayColor\"  :   \"rgba(0,0,0,0.5)\"\n       }\n   }\n  Video-specific properties  Media of   type    Video  supports the following additional properties:     Property  Required  Type  Description  Default     previewImageUrl   string  The URL of an image to show before the video is played     autoplay   boolean  Set to   true  to enable autoplay, or   false  to disable it  false    loop   boolean  Set to   true  to enable looping, or   false  to disable it  true    controls   boolean  Set to   true  to show video controls, or   false  to hide them  true   Example object:     {\n       \"type\"  :   \"SingleChoice\"  ,\n       \"title\"  :   \"What is the capital of France?\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Madrid\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   true   }\n       ],\n       \"media\"  : {\n           \"type\"  :   \"Video\"  ,\n           \"url\"  :   \"https://www.w3schools.com/html/mov_bbb.mp4\"  ,\n           \"previewImageUrl\"  :   \"https://httpbin.io/image/webp\"  ,\n           \"autoplay\"  :   false  ,\n           \"loop\"  :   true  ,\n           \"controls\"  :   true\n       }\n   }\n  Audio  Media of   type    Audio  supports the following properties:     Property  Required  Type  Description  Default     url  ✓  string  The URL of the audio file you want to add     previewImage   string|object  An image to show alongside the audio player - either a plain URL or a full   Image  media object (with   altTag ,   attributionText , ...). It must point to an image     autoplay   boolean  Set to   true  to enable autoplay, or   false  to disable it  false    loop   boolean  Set to   true  to enable looping, or   false  to disable it  true   Example object:     {\n       \"type\"  :   \"SingleChoice\"  ,\n       \"title\"  :   \"What is the capital of France?\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Madrid\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   true   }\n       ],\n       \"media\"  : {\n           \"type\"  :   \"Audio\"  ,\n           \"url\"  :   \"https://www.w3schools.com/html/horse.mp3\"  ,\n           \"previewImage\"  :   \"https://httpbin.io/image/svg\"  ,\n           \"autoplay\"  :   false  ,\n           \"loop\"  :   true\n       }\n   }\n  Adding social media content  The following social media content types are supported:   YouTube videos  Vimeo videos  X (  formerly Twitter ) posts  Add a YouTube video     Property  Required  Type  Description  Default     type  ✓  string  Set to   YouTube     videoId  ✓  string  The YouTube video ID (the part after   v=  in the URL)     autoplay   boolean  Set to   true  to enable autoplay, or   false  to disable it  false    loop   boolean  Set to   true  to enable looping, or   false  to disable it  true    controls   boolean  Set to   true  to show video controls, or   false  to hide them  false   Example object:     {\n       \"type\"  :   \"Content\"  ,\n       \"title\"  :   \"Welcome to the quiz\"  ,\n       \"description\"  :   \"This quiz will test your knowledge about France\"  ,\n       \"media\"  : {\n           \"type\"  :   \"YouTube\"  ,\n           \"videoId\"  :   \"dQw4w9WgXcQ\"  ,\n           \"autoplay\"  :   false  ,\n           \"loop\"  :   true  ,\n           \"controls\"  :   false\n       }\n   }\n  Add a Vimeo video     Property  Required  Type  Description  Default     type  ✓  string  Set to   Vimeo     videoId  ✓  string  The Vimeo video ID (the part after the last   /  in the URL)     autoplay   boolean  Set to   true  to enable autoplay, or   false  to disable it  false    loop   boolean  Set to   true  to enable looping, or   false  to disable it  true    controls   boolean  Set to   true  to show video controls, or   false  to hide them  false   Example object:     {\n       \"type\"  :   \"Content\"  ,\n       \"title\"  :   \"Welcome to the quiz\"  ,\n       \"description\"  :   \"This quiz will test your knowledge about France\"  ,\n       \"media\"  : {\n           \"type\"  :   \"Vimeo\"  ,\n           \"videoId\"  :   \"76979871\"  ,\n           \"autoplay\"  :   false  ,\n           \"loop\"  :   true  ,\n           \"controls\"  :   false\n       }\n   }\n  Add an X post     Property  Required  Type  Description  Default     type  ✓  string  Set to   X     url  ✓  string  The full URL of the X post, e.g.   https://x.com/username/status/1234567890    Example object:     {\n       \"type\"  :   \"Content\"  ,\n       \"title\"  :   \"Welcome to the quiz\"  ,\n       \"description\"  :   \"This quiz will test your knowledge about France\"  ,\n       \"media\"  : {\n           \"type\"  :   \"X\"  ,\n           \"url\"  :   \"https://x.com/username/status/1234567890\"\n       }\n   }\n  Checking media without uploading it   POST /riddle-builder/validate  dry-runs a build configuration, media included - but it only   checks  a media URL against the requirements above (reachable, right content type, redirect limit); it never downloads or uploads the file, so no copy of it is ever created on our end.  Because nothing is uploaded, the   build  a validated item echoes back reports the   URL you supplied , not a CDN URL. A real   POST /  PUT  request downloads and re-encodes the file, so the same media ends up with a different, re-encoded Riddle CDN URL once it is actually built (an uploaded   .jpg , for example, comes back as a   .webp  file on our CDN). Do not compare the two literally; validating a config successfully only tells you the media URL was reachable and of an acceptable type, not what URL the file will have once it is really built.  Reading media back  When you read a Riddle back as a build configuration, its media is returned as the same builder config you send - so a configuration you fetched can be rebuilt unchanged:    Uploaded media  (  Image ,   Video ,   Audio ) is returned as   {\"type\": ..., \"url\": ...} . The URL is the re-hosted Riddle CDN URL of the file, not the URL you originally sent: the source URL is fetched once at build time and is not stored anywhere, so it cannot be recovered from a later read-back.   Embedded videos  are returned as   {\"type\": \"YouTube\"|\"Vimeo\", \"videoId\": ...}  - a string for YouTube, an integer for Vimeo.   X posts  are returned as   {\"type\": \"X\", \"url\": ...} .  Only settings that actually differ from their default are included, so a plain image usually comes back as nothing but   type  and   url . A video or embedded video also returns   autoplay ,   loop  and   controls  when they were changed, an image its   altTag , attribution and colors, and audio its   autoplay /  loop .  A video's   previewImageUrl  and an audio file's   previewImage  are not returned - the preview image generated during the upload stays in place when you rebuild.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":342,"path":343,"dir":332,"title":344,"description":345,"keywords":346,"body":351},"content:15.Api:4.Build Riddles:5.Advanced features:2.Dynamic variables.md","/api/build-riddles/advanced-features/dynamic-variables","Dynamic variables - Build Riddles","Learn how to use dynamic variables in Riddles via API",[347,348,349,350],"Syntax","Dynamic Riddle variables","Dynamic form variables","Reading variables back","  Dynamic variables   In the Riddle Creator you can use dynamic variables  to personalize / dynamically display any Riddle / form data.  You can do the same when building a Riddle via the API - all   title  and   description  properties can be personalized with dynamic variables.  Syntax  The following syntax is used to embed dynamic variables into a property:     %riddleVariable\n  Example:     Welcome back, %name!\n   riddleVariable  then needs to be replaced with the variable you want to use. Keep reading to learn which variables you can use.  Rules for the syntax:   A variable name consists of letters, digits and dots, and is matched   case-insensitively  (  %Name  works just as well as   %name ). A dot at the very end is not part of the variable, so   Welcome back, %name.  works as expected.  A variable is only accepted if it exists   for this Riddle  - see the two sections below. An unknown variable that stands on its own (i.e. is preceded by whitespace) fails the build with   Invalid variable found in rich text: %\u003Cname> (original text: ...) .  A   %something  that is   not  preceded by whitespace is treated as literal text and left untouched, so texts like   50%off  do not break the build.  Dynamic Riddle variables  Available variables     Riddle type  Variable  Description    All  riddle.id  The unique ID of the Riddle   All  riddle.title  The title of the Riddle   All  riddle.image  The image of the Riddle - this will be automatically translated to an image in the email automation / DOI   Quiz, Poll  result.title  The title of the user result   Quiz, Poll  result.description  The description of the user result   Quiz  score.number  The score of the user as a number   Quiz  score.percentage  The score of the user as a percentage   Quiz  score.max  The maximum achievable score the user could have achieved   Personality  personality.title  The title of the visitor's main personality   Personality  personality.label  The label of that personality   Personality  personality.desc  The description of that personality   Personality  personality.score  The score the visitor reached for that personality   Personality  personality.percentage  That score as a percentage   Personality  personality.2.title   (… up to personality.5.…)  The same five variables for the 2nd to 5th ranked personality, e.g.   %personality.2.score   Personality  attribute.title, attribute.label, attribute.desc, attribute.score, attribute.percentage  The same set for the visitor's main attribute   Personality  attribute.2.title   (… up to attribute.5.…)  The same for the 2nd to 5th ranked attribute  Variables that do not exist for the Riddle type you are building are rejected - e.g.   %score.number  in a Poll.  Example  You could personalize the result page by using the variables   result.title ,   score.number , and   score.max :     {\n       \"result\"  : {\n           \"title\"  :   \"Your result: %result.title\"  ,\n           \"description\"  :   \"You scored %score.number out of %score.max\"\n       }\n   }\n  Dynamic form variables  Added form fields can be used in any following blocks as dynamic variables.  A form field's variable is its   field type in lowercase , followed by the position of that field among all fields of the same type:   %name1 ,   %name2 ,   %email1 ,   %phone1 ,   %dropdown1 , and so on. The first field of a type is additionally available without the number.  For example, adding a   FormBuilder  with two   Name  fields and one   Email  field makes the following variables available:   %name (this will always be the first   Name  field)  %name1  %name2  %email (this will always be the first   Email  field)  %email1  Here's how you could integrate the variables into a   SingleChoice  quiz question:     {\n       \"title\"  :   \"What's the capital of Germany, %name1 %name2?\"  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   true   },\n           {   \"title\"  :   \"Lissabon\"  ,   \"isCorrect\"  :   false   },\n           {   \"title\"  :   \"Leipzig\"  ,   \"isCorrect\"  :   false   }\n       ]\n   }\n  Reading variables back  When you read a Riddle back as a build configuration, variables are turned back into the very   %shortcode  you would send, so the text can be rebuilt unchanged. For the first field of a type the short form is preferred, i.e.   %email  rather than   %email1 .  Two cases cannot be expressed as a shortcode and are therefore returned as the raw variable markup, with a warning for that property:   a variable that was given a   fallback value  in the Creator (the API's   %shortcode  syntax has no way to express a fallback), and  a variable whose source no longer exists, e.g. because its form field was deleted.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":353,"path":354,"dir":332,"title":355,"description":356,"keywords":357,"body":363},"content:15.Api:4.Build Riddles:5.Advanced features:3.Custom IDs.md","/api/build-riddles/advanced-features/custom-ids","Custom IDs - Build Riddles","Learn how to assign custom IDs to blocks, items and results via API",[358,359,360,361,362,133],"How IDs are assigned","IDs when editing a Riddle","Custom block IDs","Custom item IDs","Custom result IDs","  Assigning custom IDs  By default any entries in   blocks ,   results , and   items  are assigned an auto incremented ID. This behaviour can be changed and the IDs can be set explicitly which makes it easier to later work with the Riddle's stats or webhook data.  Additionally it makes it easier to   configure custom logic settings  based on the IDs you have assigned.  How IDs are assigned   Every ID has to be a   positive integer  (1 or greater). Sending   0  or a negative number is rejected with   Block ID must be a positive integer, \u003Cid> given.  Auto-generated IDs also start at 1 and count up. The Riddle remembers which IDs it has handed out, so you can mix explicit IDs and auto-generated ones freely - an auto-generated ID never re-uses an ID you assigned yourself.   blocks  and   result /  results  share   one  ID namespace, so a result cannot re-use a block's ID (in a personality test, personalities and attributes share that namespace as well).  Item IDs only have to be unique   within their own block .  Re-using an ID inside one namespace fails the build with   ... with ID \u003Cid> already exists.  /   Item with ID \u003Cid> already exists. Make sure to not provide overlapping IDs.  IDs when editing a Riddle   Editing an existing Riddle  addresses blocks by the IDs they are already stored with, so two more things matter there:   The ID counter   only ever grows  and is shared across blocks, results, personalities and attributes. An ID freed by a deletion is never handed out again, and no ID visible in the build configuration tells you which one is free - the highest block ID plus one is usually already taken by a result.  Read the free ID from   nextBlockId , which    GET /riddle-builder/{UUID}  returns. Claiming a taken ID is rejected with an error naming the next free one.  Riddles built in the Creator can number their content from   0  upwards. An edit accepts such IDs so a configuration read from the API can be sent back unchanged; a newly added block (  \"$create\": true ) still needs a positive ID.  Custom block IDs  You can assign a custom ID to any block by adding the   id  property to the block object. The ID must be a positive integer (1 or greater) and unique (not used in   blocks  +   result /  results ).   Example object:     {\n       \"id\"  :   101  ,\n       \"title\"  :   \"The best noodles?\"  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"items\"  : [\n           {   \"title\"  :   \"Spaghetti\"   },\n           {   \"title\"  :   \"Fusilli\"   }\n       ]\n   }\n  Custom item IDs  You can assign a custom ID to any item by adding the   id  property to the item object. The ID must be a positive integer (1 or greater) and unique (only within the same block). Every collection is an array of objects (see   item formats ), so   id  simply joins the other keys of the entry:     {\n       \"items\"  : [\n           {\n               \"id\"  :   201  ,\n               \"title\"  :   \"Spaghetti\"\n           },\n           {\n               \"id\"  :   202  ,\n               \"title\"  :   \"Fusilli\"\n           }\n       ]\n   }\n  Custom result IDs  You can assign a custom ID to any result by adding the   id  property to the result object. The ID must be a positive integer (1 or greater) and unique (not used in   blocks  +   result /  results ).   Example simple result:     {\n       \"id\"  :   301  ,\n       \"title\"  :   \"Thank you\"  ,\n       \"description\"  :   \"Thanks for your vote.\"\n   }\n   Example advanced result page with blocks:     {\n       \"id\"  :   302  ,\n       \"blocks\"  : [\n           {\n               \"type\"  :   \"Text\"  ,\n               \"text\"  :   \"\u003Ch1>Thank you!\u003C/h1>\u003Cp>Thanks for your vote.\u003C/p>\"\n           }\n       ]\n   }\n  Full example     {\n       \"type\"  :   \"Poll\"  ,\n       \"build\"  : {\n           \"title\"  :   \"Favorite color poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"id\"  :   101  ,\n                   \"title\"  :   \"What's your favorite color?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {\n                           \"id\"  :   201  ,\n                           \"title\"  :   \"green\"\n                       },\n                       {\n                           \"id\"  :   202  ,\n                           \"title\"  :   \"red\"\n                       }\n                   ]\n               }\n           ],\n           \"result\"  : {\n               \"id\"  :   301  ,\n               \"title\"  :   \"Thank you\"  ,\n               \"description\"  :   \"Thanks for your vote.\"\n           }\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":365,"path":366,"dir":332,"title":367,"description":368,"keywords":369,"body":373},"content:15.Api:4.Build Riddles:5.Advanced features:4.Batch&Async processing.md","/api/build-riddles/advanced-features/batchandasync-processing","Batch & asynchronous processing - Build Riddles","Learn how to build and process Riddles in batches/asynchronously via API",[370,371,372],"Building in batches","Building single Riddles asynchronously","Checking the result of an asynchronous build","  Batch and asynchronous processing  In some cases where lots of Riddles are needed, it may be more efficient to build them in batches. This drastically reduces the overhead of each HTTP request and allows for faster processing.  Additionally, single Riddles can also be built asynchronously - this makes migrating to an asynchronous flow much easier with your existing code and processes.  Building in batches   A batch  is a   collection of Riddle builds , sent in one payload to the builder API.  Example  For example if I want to create a quiz and poll with one request, only one request to the   builder batch API endpoint  is needed with the   batch  property set to an array of build configurations:     {\n       \"batch\"  : [\n           {\n               \"type\"  :   \"Quiz\"  ,\n               \"build\"  : {\n                   \"title\"  :   \"My new quiz\"  ,\n                   \"blocks\"  : [\n                       {\n                           \"title\"  :   \"What is the capital of France?\"  ,\n                           \"type\"  :   \"SingleChoice\"  ,\n                           \"items\"  : [\n                               {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   false   },\n                               {   \"title\"  :   \"Madrid\"  ,   \"isCorrect\"  :   false   },\n                               {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   true   }\n                           ]\n                       }\n                   ]\n               }\n           },\n           {\n               \"type\"  :   \"Poll\"  ,\n               \"build\"  : {\n                   \"title\"  :   \"My new poll\"  ,\n                   \"blocks\"  : [\n                       {\n                           \"title\"  :   \"What is your favorite color?\"  ,\n                           \"type\"  :   \"SingleChoice\"  ,\n                           \"items\"  : [\n                               {   \"title\"  :   \"Red\"   },\n                               {   \"title\"  :   \"Green\"   },\n                               {   \"title\"  :   \"Blue\"   }\n                           ]\n                       }\n                   ]\n               }\n           }\n       ]\n   }\n  Every item of   batch  needs the same two properties the single build endpoint takes:     Property  Required  Type  Description  Default     type  ✓  string  The Riddle type to build, e.g.   Quiz  or   Poll     build  ✓  object  The build configuration for that Riddle     strictProperties   boolean  Reject a build configuration property that no Riddle type or block knows instead of silently ignoring it - only for this item. Falls back to the batch-wide   strictProperties  when omitted   On top of the array itself, the following properties are read   once per request  and applied to every Riddle of the batch:     Property  Required  Type  Description  Default     batch  ✓  array  Between 1 and 100 build configurations     publish   boolean  Publish every Riddle of the batch after it was built  false    project   integer  The project (team) ID all Riddles should be created in. Requires the   create Riddle  permission in that project. If omitted, a team access token builds in its own project, a personal token in your personal project  null    strictProperties   boolean  The default for every item of the batch, overridable per item  false   Note:    publish  and   project  are   batch-wide  - they are read from the top level of the payload, not from the individual items. Setting   publish  inside a single batch item has no effect.   strictProperties  is the one property that works on   both  levels: the batch-wide value is the default, and an item that carries its own   strictProperties  uses that instead.   Note:  A batch is built in the background, so a property rejected because of   strictProperties  cannot be answered with a   400  - the affected Riddle stays empty instead (see   Checking the result of an asynchronous build ). Send one build synchronously with   strictProperties: true  while you develop the configuration: there the offending key is named in the response.   Note:    projectId  is still accepted as a legacy alias for   project .  Important factors to consider when using batches   The batch size is limited to   100  Riddles per request; an empty   batch  array is rejected.  Building in batches requires a   Business or Enterprise  plan, just like the single build endpoint.  The Riddles are created asynchronously and the response will contain a list of Riddles which are only initialized, i.e. not visible yet in the Creator.  The response contains one entry per batch item, in the same order as it was sent:     {\n       \"success\"  :   true  ,\n       \"data\"  : {\n           \"count\"  :   2  ,\n           \"items\"  : [\n               {\n                   \"UUID\"  :   \"abcdef12\"  ,\n                   \"title\"  :   \"My new quiz\"  ,\n                   \"type\"  :   \"Quiz\"\n               },\n               {\n                   \"UUID\"  :   \"34567890\"  ,\n                   \"title\"  :   \"My new poll\"  ,\n                   \"type\"  :   \"Poll\"\n               }\n           ]\n       }\n   }\n  The   title  is taken from the   title  of the build configuration, so the entries can be matched to what you sent even before the builds have finished.  Building single Riddles asynchronously   Building asynchronously  means that a   single Riddle build  is processed in the background and the response will contain a UUID for the Riddle which is only initialized, i.e. not visible yet in the Creator.  Example  To mark the build as asynchronous, the   queue  property must be set to   true  in the request. The request would look like this:     {\n       \"type\"  :   \"Quiz\"  ,\n       \"queue\"  :   true  ,\n       \"build\"  : {\n           \"title\"  :   \"My new quiz\"  ,\n           \"blocks\"  : [\n               {\n                   \"title\"  :   \"What is the capital of France?\"  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"Berlin\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Madrid\"  ,   \"isCorrect\"  :   false   },\n                       {   \"title\"  :   \"Paris\"  ,   \"isCorrect\"  :   true   }\n                   ]\n               }\n           ]\n       }\n   }\n  The response is a regular Riddle response, but for the   initialized  Riddle: it already has its   UUID , its type and - if you sent one - its   title , while its   data  is still empty. Everything else in   build  is applied a moment later, in the background.   publish ,   project  and   strictProperties  work exactly as they do for a synchronous build;   publish: true  publishes the Riddle once the background build has finished.   strictProperties: true  is still enforced - but in the background, so the rejected key cannot be reported back to you and the Riddle stays empty instead.  Checking the result of an asynchronous build  Queued builds - both   queue: true  and every item of a batch - are processed after the response was sent, so   build errors cannot be returned to you . There is no status field to poll either. Instead:   Fetch the Riddle by its UUID once, e.g. via the   Riddle endpoint . A Riddle that is still empty either has not been processed yet or its build configuration was rejected.  Because of that, we recommend building   one  Riddle synchronously (without   queue ) while you develop your build configuration: a synchronous build validates the whole configuration and answers with a precise error message. Once the payload is known to be valid, switch to   queue: true  or the batch endpoint for the bulk work.  Or check the payload up front:    POST /riddle-builder/validate  dry-runs up to 20 build configurations - the batch items themselves - and reports per item whether it would be accepted and why not, without creating a single Riddle.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":375,"path":376,"dir":332,"title":377,"description":378,"keywords":379,"body":383},"content:15.Api:4.Build Riddles:5.Advanced features:5.Deleting built Riddles.md","/api/build-riddles/advanced-features/deleting-built-riddles","Deleting built Riddles - Build Riddles","Learn how to delete built Riddles via API",[380,381,382],"Which Riddles can be deleted","The same rule gates editing and restyling","Response","  Deleting built Riddles  In contrast to Riddles which were created through our web interface, Riddles built via the Builder API can be deleted through the API.  To delete a Riddle, use the   Riddle delete endpoint . The   UUID  of the Riddle can be found in the response of the   Riddle build endpoint .  Please be aware that deleting a Riddle is irreversible and will remove all data associated with the Riddle. This includes the Riddle itself, its results, and all data collected from participants.  Which Riddles can be deleted  Only   programmatically created  Riddles can be deleted with an API key:   Riddles built via the   Riddle Builder API , including queued and batch builds,  Riddles created from a template with the   MCP  tool   riddleTemplate_use , and  Riddles generated by the   Riddle AI  via an API key.  Everything else - most importantly Riddles created in the Creator - is rejected with:     Only Riddles created via the Builder API or generated by the Riddle AI can be deleted with an API key.\n  This makes the endpoint safe to use for cleaning up Riddles that were created for testing purposes: it can never delete the work of your team.  Deleting also requires the   delete Riddle  permission for the project the Riddle lives in.  The same rule gates editing and restyling  Deleting is not the only thing this rule decides. Exactly the same condition - reported as   origin.apiManageable  when you read a Riddle back - gates every write an API key or MCP client may perform on a whole Riddle:   deleting it,   editing it  with a build configuration (  PUT /riddle-builder/{UUID}  /   riddle_builder_update ), and  restyling it (  palette_customize ).  Reading is never restricted:   any  Riddle can be read back as a build configuration, whoever created it.  Because a Riddle created with   riddleTemplate_use  counts as programmatically created, it can be edited, restyled and deleted afterwards just like one you built yourself - and it records where it came from: reading it back reports the template's Riddle under   context.duplicated .  Response  On success the endpoint answers with the UUID it deleted:     {\n       \"success\"  :   true  ,\n       \"data\"  : {\n           \"deletedUUID\"  :   \"abcdef12\"\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":385,"path":386,"dir":332,"title":387,"description":388,"keywords":389,"body":393},"content:15.Api:4.Build Riddles:5.Advanced features:6.Feature toggles.md","/api/build-riddles/advanced-features/feature-toggles","Feature toggles - Build Riddles","Learn how features are switched on and off in a builder config",[390,391,392,16],"The rule","Round trips","Where they are","  Feature toggles  Many Riddle features consist of two things: the content of the feature, and a flag saying whether it is used. In a builder config you normally only send the content -   supplying a feature's content switches the feature on . Sending an   explanation  enables the explanation, sending a   footerText  enables the footer text, sending an   adTop  slot enables ads.  For every such feature the flag is also available as a property of its own, so you can state it explicitly.  The rule   Send only the content → the feature is switched   on .  Send the flag as   true  → same thing, explicit.  Send the content   and  the flag as   false  → the content stays stored, the feature is   off .  Send neither → nothing changes.  An explicit flag is always applied   after  the content it belongs to, so it always wins - the order inside your JSON object does not matter.  Case 3 is what makes a feature switchable again when   editing an existing Riddle : without it, resending a configuration would silently switch every configured feature back on.     {\n       \"blocks\"  : [\n           {\n               \"id\"  :   1  ,\n               \"explanation\"  :   \"Paris has been the capital since 508.\"  ,\n               \"isExplanationEnabled\"  :   false\n           }\n       ]\n   }\n  The explanation stays exactly as it is, but is no longer shown. Dropping   isExplanationEnabled  from the same request would switch it back on.  Round trips   Reading a Riddle back  always returns the flag next to the feature it belongs to, so \"is this on?\" is answered by the configuration itself and an off state survives being sent back unchanged. A feature nobody ever configured is left out entirely, flag included.  Where they are     Flag  Where  Switched on by     isEnabled   preset.riddleTimer ,   preset.blockTimer ,   preset.autoClose  Sending the object    isEnabled   preset.customStrings  Sending at least one string    isEnabled   preset.footerText  A non-empty   text    isEnabled   preset.ads , and each of its   adTop  /   adBottom  slots  Sending a slot / the slot's   projectSlot  or   iframe    isAutoOpenEnabled   preset   autoOpenDate    isResultEnabled   preset.autoClose   resultId    areIndividualTimesEnabled   preset.blockTimer   individualBlockTimes    isCustomConfirmationPageEnabled   publish.doi  Any of the confirmation page properties    isExplanationEnabled  A Quiz question / answer   explanation    isRankFormatEnabled  An \"order it\" block   rankFormat    isDescriptionVisible  A choice block  Any item   description    areOtherResultsEnabled ,   isIncludeCTAButtonEnabled  A personality result  The other results / CTA button properties    isDescriptionEnabled ,   isPrefilledTextEnabled ,   isAdvancedValidationEnabled  A form field   description  /   prefilledText  /   regex    isShowNextButtonAfterDelayEnabled  An   Ad  block  A   showNextButtonDelay  greater than   0    isSuccessMessageEnabled  A Sudoku block  A non-empty   successMessage    isDelayEnabled  A result redirect  A   delay  greater than   0  Flags that are not derived from anything -   isRequired  on a form field,   preset.riddleSingleVote.isEnabled ,   preset.pagination.isEnabled  and the like - are ordinary properties and behave exactly as they read.  Next steps    Edit an existing Riddle   Configure the preset settings   Configure the publish settings  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":395,"path":396,"dir":332,"title":397,"description":398,"keywords":399,"body":403},"content:15.Api:4.Build Riddles:5.Advanced features:7.Validating build configurations.md","/api/build-riddles/advanced-features/validating-build-configurations","Validating build configurations - Build Riddles","Learn how to dry-run build configurations before creating or editing Riddles via API",[400,382,401,402,16],"Request","What it can catch","Two things worth knowing","  Validating build configurations   POST /riddle-builder/validate    dry-runs  build configurations: every item is validated exactly as the real call would validate it, against a scratch Riddle that is discarded before the response. Nothing is created, changed, published or queued, and no Riddle appears in your library.  Use it to check a configuration you are still writing, to find out   why  one would be rejected without spending a real create or edit on it, and to pre-flight a whole set of similar Riddles in a single request.   Needed subscription plan:  Business or Enterprise.  Request     Property  Required  Type  Description  Default     builds  ✓  array  The configurations to check,   1 to 20  entries. See below     projectId   integer  The project a creating item would be created in. Defaults to your personal project, and is checked for the same permission a real create needs. Ignored by editing items, which are checked against their own Riddle     strictProperties   boolean  Request-wide default for   strict properties ; can be overridden per item, exactly as on the batch endpoint   Each entry of   builds  is either    {\"type\": ..., \"build\": {...}}  - a would-be   creation , the shape of   POST /riddle-builder  and of a   batch  item, or   {\"UUID\": ..., \"build\": {...}}  - a would-be   edit , the shape of   PUT /riddle-builder/{UUID}  (see   Editing Riddles ).  Exactly one of   type /  UUID  per item; creations and edits can be mixed in one call. An item may carry its own   strictProperties , and a per-item   publish  is accepted and ignored - nothing is built here.  To check a   single  configuration, send a one-item   builds  array and read   items[0] .     {\n       \"builds\"  : [\n           {\n               \"type\"  :   \"Poll\"  ,\n               \"build\"  : {\n                   \"title\"  :   \"My new poll\"  ,\n                   \"blocks\"  : [\n                       {\n                           \"type\"  :   \"SingleChoice\"  ,\n                           \"title\"  :   \"Which city do you like most?\"  ,\n                           \"items\"  : [\n                               {   \"title\"  :   \"Berlin\"   },\n                               {   \"title\"  :   \"Madrid\"   },\n                               {   \"title\"  :   \"Paris\"   }\n                           ]\n                       }\n                   ]\n               }\n           },\n           {\n               \"UUID\"  :   \"abcdef12\"  ,\n               \"build\"  : {\n                   \"title\"  :   \"A new title for an existing Riddle\"\n               }\n           }\n       ]\n   }\n  Response     Property  Type  Description  Default     valid  boolean  Whether   every  item would be accepted as-is     summary  object  Counts over all items:   {total, valid, invalid}     items  array  One entry per item of   builds , in the order you sent them   Every item entry carries its   index , the   type  it names (or the type of the Riddle an editing item addressed), the   UUID  for editing items, and   valid . Beyond that:     Property  When  Description  Default     build   valid: true  The build configuration the Riddle would end up with, read back the way    GET /riddle-builder/{UUID}  reports one     errors   valid: false  Why the item would be rejected, as a   {message, code}  list - the same codes   exception handling  documents. An entry that came from property validation additionally names its   property     wouldBeRejectedByRequest  only when   true  The item is malformed at   request  level (neither or both of   type /  UUID , no   build , or an undeclared property under   strictProperties ) rather than at build-configuration level: a real call would reject the whole request over it, not just this item     internalError  only when   true  Checking this item ran into an error on our side rather than into a rejection: its outcome is unknown (and has been reported to us), the other items are unaffected. A real call with that configuration would answer a   500    Every item is answered on its own.  One item being rejected - or hitting an   internalError  - never changes what the others report, and the response is a   200  either way: read   valid , not the status code.     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"valid\"  :   false  ,\n       \"summary\"  : {   \"total\"  :   2  ,   \"valid\"  :   1  ,   \"invalid\"  :   1   },\n       \"items\"  : [\n           {\n               \"index\"  :   0  ,\n               \"type\"  :   \"Poll\"  ,\n               \"valid\"  :   true  ,\n               \"build\"  : {   \"title\"  :   \"My new poll\"  ,   \"blocks\"  : [   ...   ] }\n           },\n           {\n               \"index\"  :   1  ,\n               \"type\"  :   \"Quiz\"  ,\n               \"UUID\"  :   \"abcdef12\"  ,\n               \"valid\"  :   false  ,\n               \"errors\"  : [\n                   {\n                       \"message\"  :   \"QuizSingleChoiceBlock: Property   \\\"  items  \\\"   is required but not set\"  ,\n                       \"code\"  :   \"REQUIRED\"\n                   }\n               ]\n           }\n       ]\n   }\n  What it can catch    Permissions are enforced as they would be for a real call : the project permission a create needs (resolved only if the request contains a creating item, so an edit-only call does not need create permission), and per editing item the edit permission plus the same origin rule   PUT /riddle-builder/{UUID}  applies - only Riddles   built via the API or generated by the Riddle AI  can be edited.   Media URLs are checked.  A media URL in the configuration is verified with a live request for reachability, content type and redirect limit, exactly as a real call would - so an unreachable URL is rejected here too. The file itself is never downloaded or stored; see   Use media .  Two things worth knowing    errors  is not necessarily the complete list.  Validation reports the first class of problem it runs into for an item: a rejection that aborts the build - overlapping result percentages, an unusable logic tree, a reference that cannot be resolved - is reported on its own, and the block-level property errors of the very same configuration are only reported once that rejection is gone. So an item that comes back with one error can still come back with further ones after you fixed it. Re-validate after every fix until   valid  is   true ; that final   true  is conclusive.   Send   projectId  whenever the configuration references another Riddle.  A creating item is validated in the project you name, and in your personal project if you name none - exactly where a real create would put it. References to other Riddles (a   Placeholder  condition, a leaderboard UUID, a   FormSelect  target) are authorization-checked against that location, so validating a configuration without   projectId  while the Riddle it points at lives in a team project is rejected with   You are not authorized to access \u003CType> \u003CUUID>  - not because the configuration is wrong, but because it was checked in the wrong place. Name the project you actually intend to build in. Editing items are unaffected: they are always checked against their own Riddle's project.  This is also the only way to check the items of   POST /riddle-builder/batch  beforehand: a batch only enqueues its builds and therefore answers   200  long before any of them is validated - see   Batch & asynchronous processing .  Next steps    Handle the errors it reports   Build the configuration for real   Edit an existing Riddle   Build many Riddles at once  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":405,"path":406,"dir":81,"title":407,"description":408,"keywords":409,"body":415},"content:15.Api:4.Build Riddles:6.Item formats.md","/api/build-riddles/item-formats","Item formats - Build Riddles","Learn the one item format every collection property of a build configuration uses: an array of objects",[410,411,412,413,414,16],"One format: an array of objects","Giving an entry its own id","Editing a collection","The one collection with keys: a Matrix scale","Older configurations: the bare-value shorthand","  Item formats  Most blocks hold a collection of smaller entries: a question's   items , a form's   fields , a TierList's   tiers , a personality test's   personalities . All of these use the same format, so you only have to learn it once - the pages of the individual Riddle types and blocks then only tell you what is specific to that collection.  One format: an array of objects  A collection is an   array of objects , and every entry carries its own properties as keys. The entry's text is its   title :     \"items\"  : [\n       {   \"title\"  :   \"Spaghetti\"   },\n       {   \"title\"  :   \"Fusilli\"   }\n   ]\n  That is the whole rule. Beyond   title  and   its own   id , an entry only accepts the properties of the collection it sits in - there is no set of keys that every entry shares. A Quiz answer has an   isCorrect  flag, a form field a   type , a personality answer its   scores :     \"items\"  : [\n       {   \"title\"  :   \"Rome\"  ,   \"isCorrect\"  :   true   },\n       {   \"title\"  :   \"Madrid\"  ,   \"isCorrect\"  :   false   }\n   ]\n     \"fields\"  : [\n       {   \"title\"  :   \"Your email\"  ,   \"type\"  :   \"Email\"   },\n       {   \"title\"  :   \"Your name\"  ,   \"type\"  :   \"Name\"   }\n   ]\n     \"items\"  : [\n       {   \"title\"  :   \"I plan every detail\"  ,   \"scores\"  : [  3  ,   0  ] },\n       {   \"title\"  :   \"I improvise\"  ,   \"scores\"  : [  0  ,   3  ] }\n   ]\n  Which properties those are is listed on the page of the Riddle type or block that owns the collection. A property that is not on that list is rejected, and the error names what the collection does accept:   Matrix scale[0]: \"description\" is not a supported property of this block. Supported here: title.\n  A   description  and a   media  of its own, for example, exist only on the answers of a choice question and on the entries of a few Poll blocks - not on a Matrix rating, a TierList tier or a Predictor team.  Giving an entry its own   id  Every entry of a collection gets an   id  - auto-generated and counting up from 1 if you do not send one:     \"items\"  : [\n       {   \"id\"  :   201  ,   \"title\"  :   \"Spaghetti\"   },\n       {   \"id\"  :   202  ,   \"title\"  :   \"Fusilli\"   }\n   ]\n  An item ID has to be a positive integer and only has to be unique   within its own block . Assigning them yourself pays off in three places:   logic settings  can reference an answer by ID instead of by its exact text, stats and webhook data become stable when a wording changes, and an edit can address the entry. See   custom IDs  for the full rules.  Editing a collection  When you   edit an existing Riddle , the entries of these collections are merged by their   id : an entry you do not mention stays as it is, and an entry you send by   id  is updated with the properties you send.     {\n       \"id\"  :   3  ,\n       \"items\"  : [\n           {   \"id\"  :   2  ,   \"title\"  :   \"Bonn\"   }\n       ]\n   }\n  An entry without an   id  is not addressing anything, so an edit rejects it - add   \"$create\": true  to send it as a new entry instead:     {\n       \"id\"  :   3  ,\n       \"items\"  : [\n           {   \"$create\"  :   true  ,   \"title\"  :   \"Cologne\"   }\n       ]\n   }\n  The one collection with keys: a Matrix   scale  A   Likert/matrix question  stores the value a rating stands for, and that value is the key of the entry:     \"scale\"  : {\n       \"0\"  : {   \"title\"  :   \"Bad\"   },\n       \"2\"  : {   \"title\"  :   \"Medium\"   },\n       \"4\"  : {   \"title\"  :   \"Good\"   }\n   }\n  The entries themselves are objects like everywhere else. Send   scale  as a plain array to get the default values - the index of the entry, counting from 0.  Older configurations: the bare-value shorthand  The object entry above is the only item format the Builder API documentation describes. Older configurations, written when a collection also accepted a   bare value  in place of an object, may still look different, and what such a value meant depended on the collection it was in:     What an old configuration may hold  What it means  The same thing as an object     \"items\": [\"Spaghetti\", \"Fusilli\"]  Each value is one entry's title   \"items\": [{ \"title\": \"Spaghetti\" }, { \"title\": \"Fusilli\" }]    \"items\": {\"Rome\": true}  The key is the title, the value the   isCorrect  flag   \"items\": [{ \"title\": \"Rome\", \"isCorrect\": true }]    \"fields\": {\"Your email\": \"Email\"}  The key is the field label, the value the field   type   \"fields\": [{ \"title\": \"Your email\", \"type\": \"Email\" }]  Those configurations keep working on   POST /riddle-builder  for backwards compatibility, but the shorthand is no longer documented, and it is   rejected  wherever strict property validation applies: when you   edit a Riddle , when you build through the   MCP server , and on a create build sent with    strictProperties :   SingleChoice: Invalid item at key \"Madrid\": expected an object with the item's properties as keys, e.g. {\"title\":\"Madrid\",\"isCorrect\":false}. A bare bool is not accepted here - only an object can carry an \"id\", which is what addressing a single item takes.\n  There is nothing a bare value can express that an object cannot, so move any configuration that still sends one over to the object entry: the text goes into   title , every other value into a key of its own.  Next steps    Build a Riddle from scratch   Edit an existing Riddle and learn about build markers   Assign your own IDs to blocks, items and results   Add media to an entry  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":417,"path":418,"dir":81,"title":419,"description":420,"keywords":421,"body":424},"content:15.Api:4.Build Riddles:7.Reading Riddles back.md","/api/build-riddles/reading-riddles-back","Reading Riddles back - Build Riddles","Learn how to read an existing Riddle back as a build configuration via API",[382,422,423,16],"Content the build configuration cannot express","Properties left out because they are still at their default","  Reading a Riddle back   GET /riddle-builder/{UUID}  returns any Riddle - also ones that were never built via the API - as the same build configuration a build request accepts as   build . Three things it is for:   preparing an   edit , which addresses blocks by the   id  they are stored with  checking what a Riddle currently holds, including which features are switched on  learning the defaults of a block type  Response     Property  Type  Description  Default     uuid  string  The UUID of the Riddle     type  string  The Riddle type     modifiedAt  string  When the Riddle was last modified, e.g.   2024-01-01 12:00:00     build  object  The Riddle as a build configuration; every block, item and result carries the   id  it is stored with     nextBlockId  integer  The ID a newly added block may claim, and the only reliable source for one - see   block IDs     warnings  array  Everything that could   not  be expressed in   build , each with a   path  (e.g.   blocks[7].items ), a   reason  (  UNKNOWN_BLOCK_TYPE ,   PROPERTY_NOT_SERIALIZABLE ,   RIDDLE_DATA_NOT_EXPRESSIBLE ) and a   message   Example     {\n       \"uuid\"  :   \"abcdef12\"  ,\n       \"type\"  :   \"Poll\"  ,\n       \"modifiedAt\"  :   \"2026-01-01 12:00:00\"  ,\n       \"nextBlockId\"  :   9  ,\n       \"build\"  : {\n           \"title\"  :   \"Favorite color poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"id\"  :   1  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"title\"  :   \"What's your favorite color?\"  ,\n                   \"items\"  : [   ...   ]\n               },\n               {\n                   \"id\"  :   3  ,\n                   \"type\"  :   \"NPS\"  ,\n                   \"title\"  :   \"How likely are you to recommend us?\"\n               }\n           ],\n           \"result\"  : {   \"id\"  :   2  ,   \"title\"  :   \"Thank you\"   }\n       },\n       \"warnings\"  : []\n   }\n  Content the build configuration cannot express  The endpoint never fails on content it does not understand. Unsupported blocks are returned as   {\"id\": ..., \"type\": ..., \"isSupported\": false, \"rawContent\": {...}}  - for reference only, never send them back. Everything else that could not be expressed comes with an entry in   warnings .  Properties left out because they are still at their default  A property that still holds its block type's own default value is   not  written into   build . The omission is never silent, though: every block carries an   omittedDefaults  object naming each of those properties   together with the value it is at .     {\n       \"id\"  :   1  ,\n       \"type\"  :   \"SingleChoice\"  ,\n       \"title\"  :   \"Capital of France?\"  ,\n       \"items\"  : [\n           {\n               \"id\"  :   1  ,\n               \"title\"  :   \"Paris\"  ,\n               \"isCorrect\"  :   true  ,\n               \"omittedDefaults\"  : {   \"description\"  :   \"\"  ,   \"media\"  :   null  ,   \"score\"  :   1   }\n           }\n       ],\n       \"omittedDefaults\"  : {\n           \"description\"  :   \"\"  ,\n           \"media\"  :   null  ,\n           \"mediaOrientation\"  :   \"Settings\"  ,\n           \"score\"  :   1  ,\n           \"itemsShuffled\"  :   false  ,\n           \"isRequired\"  :   true  ,\n           \"layoutType\"  :   \"Rows\"\n       }\n   }\n  Items, form fields and result pages carry their own   omittedDefaults  the same way their block does - the map always belongs to the object it sits in. (The block map above is shortened; a real one covers every default that block type has.)  Read it as   \"these properties are still X\" , not as   \"these properties can be set to X here\" :   Do not send a value from   omittedDefaults  back.  It is informational. A good number of builder properties switch a feature   on by being present at all , whatever value they carry - the preset timer, double opt-in and email automation, the scoring level. Copying a pair out of this map into the block is therefore not a no-op; leave the property out, exactly as the read-back did.     id  and   type  are never omitted.  They are written on every block, always - as is every   required  property of that block type, even when it happens to equal the default.   A property this block cannot accept at all is not listed either.  Where a property is only valid for a certain configuration - the   showInfo -only properties of an interactive-graphic hotspot, the area-only properties of a   dot  hotspot - it is rejected rather than defaulted, so it is deliberately not advertised as an omitted default.   The key is absent  from a block that omitted nothing.   A property in neither   build  nor   omittedDefaults  is either one of those conditionally invalid ones, or genuinely could not be expressed - and the second kind comes with an entry in   warnings .  This is also why diffing a fetched config against the config you originally sent shows fewer properties than you sent: compare against a fresh minimal build of the same block type instead.  Need the defaults of a block type you have not built yet? Build a minimal block of that type and read it back - its   omittedDefaults  is the complete list. The same catalogue is also published per Riddle type and block type as a reference document for   MCP clients .  Next steps    Edit an existing Riddle with the same build configuration   See which flags switch a feature on and off   Assign your own IDs to blocks, items and results  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":426,"path":427,"dir":81,"title":428,"description":429,"keywords":430,"body":438},"content:15.Api:4.Build Riddles:8.Editing Riddles.md","/api/build-riddles/editing-riddles","Editing Riddles - Build Riddles","Learn how to edit an existing Riddle via API with a builder config",[431,85,432,433,434,435,436,437,382,133,16],"The one rule","Step 1: read the Riddle","Editing a block","Adding a block: $create","Removing a block: $delete","Reordering: $blocksOrder and friends","Rules and errors","  Editing an existing Riddle   PUT /riddle-builder/{UUID}  edits a Riddle that already exists, using the   same builder config  that   POST /riddle-builder  accepts as   build  and that    GET /riddle-builder/{UUID}  returns.  It works on Riddles of   every type , but only on Riddles this API can see in full: ones   built via the Builder API, created from a template with the MCP tool   riddleTemplate_use , or generated by the Riddle AI  - see   which Riddles the API may manage . A Riddle assembled by hand in the Creator can hold content a builder config cannot express - that is what the read endpoint's   warnings  report - so editing it from here would mean editing around content the API never saw. Such a Riddle is rejected with a message saying so, and has to be edited in the Creator. Reading it keeps working.  The one rule   An edit only states what changes.  Anything the build configuration does not mention keeps whatever is stored.  That is the single difference to a build: no property is required as long as the Riddle already stores a value for it, and nothing is reset. Blocks are addressed by their   id  and are   merged into , not replaced.  Request format     {\n       \"build\"  : {\n           \"title\"  :   \"Favorite color poll (2026)\"\n       },\n       \"publish\"  :   true\n   }\n     Property  Required  Type  Description  Default     build  ✓  object  The build specifications to apply - only what should change     publish   boolean  Publish the Riddle after the edit  false  The root of an edit takes nothing else: the Riddle already has a   type  and lives in a   project , and an edit is always processed synchronously (there is no   queue ).  Step 1: read the Riddle  An edit addresses blocks by the   id  they are stored with, so start with   GET /riddle-builder/{UUID} . Besides   build  it returns   nextBlockId , the ID a newly created block may claim. See   reading Riddles back  for the full response and for why a read-back holds fewer properties than you sent.     {\n       \"uuid\"  :   \"abcdef12\"  ,\n       \"type\"  :   \"Poll\"  ,\n       \"modifiedAt\"  :   \"2026-01-01 12:00:00\"  ,\n       \"nextBlockId\"  :   9  ,\n       \"build\"  : {\n           \"title\"  :   \"Favorite color poll\"  ,\n           \"blocks\"  : [\n               {\n                   \"id\"  :   1  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"title\"  :   \"What's your favorite color?\"  ,\n                   \"items\"  : [   ...   ]\n               },\n               {\n                   \"id\"  :   3  ,\n                   \"type\"  :   \"NPS\"  ,\n                   \"title\"  :   \"How likely are you to recommend us?\"\n               }\n           ],\n           \"result\"  : {   \"id\"  :   2  ,   \"title\"  :   \"Thank you\"   }\n       },\n       \"warnings\"  : []\n   }\n  Editing a block  Send the block's   id  plus only the properties that change. Every other property of that block, and every block you do not list, stays as it is:     {\n       \"build\"  : {\n           \"blocks\"  : [\n               {   \"id\"  :   1  ,   \"title\"  :   \"What is your favorite color, really?\"   }\n           ]\n       }\n   }\n  The   NPS  block with ID   3  above is not mentioned, so it is untouched - as are the answer items of block   1 , its media, its layout settings and the Riddle's result page.  A block   cannot change its type : a   type  contradicting the stored one is rejected - delete the block and add a new one instead. Repeating the correct   type  is a no-op and always allowed, which is what a round-tripped configuration does. The same holds for the   fieldType  of a standalone   FormField  block.  What merges and what is replaced  The merge goes all the way down: blocks by their   id , and the collections inside them entry by entry. What is rewritten as a whole says so below. The   $create  and   $delete  markers the table mentions are described further down:     What you send  What happens     title  Replaced. Omit it to keep the current title.    blocks   Merged by   id .  Blocks you do not list are untouched.   A collection   inside  a block (  items ,   fields ,   answers , ...)   Merged by   id , entry by entry, exactly as   blocks  are: an entry you do not list stays as it is, an entry you send by   id  is updated with the properties you send,   \"$create\": true  adds one and   \"$delete\": true  removes one. See   item formats .    result  Replaced as a whole if sent, kept if omitted.    results  (Quiz)  Replaced as a whole if sent, kept if omitted. Resend every result page you want to keep, not just the one you are changing: there is no   id -addressing and no   $resultsOrder  for this collection.    personalities  (Personality Test)   Merged by   id , exactly like   blocks : an entry you do not list stays as it is,   \"$create\": true  adds one,   \"$delete\": true  removes one. Their   order is not editable  - there is no   $personalitiesOrder . See   Editing the personalities  below.    scale  (Matrix)  Replaced as a whole, not merged entry by entry - the ratings are the columns of the whole question. Resend every rating you want to keep.    logic  Replaced as a whole if sent, kept if omitted.    preset ,   publish  (settings object),   scoring  (Predictor)  Merged   per key  into the stored settings - sending   {\"correct\": 50}  leaves the other scoring rules exactly as they were.    leaderboard  Only applied when you actually send it; it adds a connection. Omit it to leave the Riddle's connections alone.    riddleConnections  (Leaderboard)  Replaces the connected set as a whole - resend every UUID you want to keep.    conditions  (Placeholder)  Replaces the routing rules as a whole - resend every condition you want to keep.   \"riddleId\": null  clears the fallback target, but an edit whose result would have   neither  a fallback nor a single condition is rejected: the Placeholder could no longer display anything. See   Placeholder .   Note:  In a collection which is rewritten as a whole, an entry you re-supply   under its original   id  is re-created under that same ID, so references into it (a   blockId_fieldId  reference, logic rules, personality scores by ID) keep resolving. An entry you omit - or that you send without an   id  - loses its old identity. In a merged collection there is nothing to re-supply: the entries your IDs address   are  the stored ones.  Editing the personalities  Sending   personalities  on a Personality Test merges by   id , exactly like   blocks : an entry you do not list stays\nas it is, an entry you send by   id  is updated with the properties you send,   \"$create\": true  adds one, and\n  \"$delete\": true  removes one.  Their   order cannot be changed  here. Unlike   blocks , this collection has no   $personalitiesOrder  marker - sending\none is rejected - and since the entries are matched by   id , the order you send them in has no meaning either. A\npersonality added with   \"$create\": true  is appended at the end, every other one keeps the place it has, and the\npersonalities are reordered in the Creator.  A Personality Test needs at least 2 personalities, and that minimum is checked against the count the merge would\nleave, not against the entries you send: an edit that deletes down to one personality is rejected, and editing an\nexisting personality without touching the count is unaffected either way.  The scores already stored on every answer item follow their personality   by identity , not by position:   a personality you keep keeps its scores;  a personality you   add  starts at a score of   0  on every existing answer;  a personality you   delete  takes its scores with it, and no other personality inherits them.  So renaming, restyling or shortening the personality list never needs the questions resent - the scoring stays valid\non its own. Since the order never moves, a   scores  array read back is always aligned with the personalities in the\norder   riddle_get  reports them.  Adding a personality leaves it scoring 0 everywhere until you say otherwise. Set the real scores by resending the\naffected blocks'   items  with their full   scores  arrays   in the same call  - blocks are built after the\npersonalities, so what you send simply wins.     {\n       \"personalities\"  : [\n           {   \"id\"  :   1  ,   \"title\"  :   \"The Explorer\"   },\n           {   \"$create\"  :   true  ,   \"id\"  :   3  ,   \"title\"  :   \"The Improviser\"   }\n       ],\n       \"blocks\"  : [\n           {\n               \"id\"  :   3  ,\n               \"items\"  : [\n                   {   \"id\"  :   1  ,   \"scores\"  : [  2  ,   0  ,   1  ] },\n                   {   \"id\"  :   2  ,   \"scores\"  : [  0  ,   2  ,   1  ] }\n               ]\n           }\n       ]\n   }\n  Adding a block:   $create   \"$create\": true  adds a new block instead of editing an existing one. Such an entry needs no   id  - though it may carry one to   control the ID  it gets - and it is built with full create semantics - so everything a   POST /riddle-builder  request requires for that block type is required here too:     {\n       \"build\"  : {\n           \"blocks\"  : [\n               {\n                   \"$create\"  :   true  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"title\"  :   \"Which color do you like least?\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"green\"   },\n                       {   \"title\"  :   \"red\"   }\n                   ]\n               }\n           ]\n       }\n   }\n  New blocks are appended after the Riddle's existing blocks. To put one somewhere else, send the Riddle's block order along with it in   $blocksOrder , the order marker described under   reordering : it takes the complete list of block IDs in the order you want, so the new block has to carry an   id  the list can name.  Choosing the new block's ID  A   $create  entry needs no   id  - it gets the next free one assigned. You   may  send one, though, and then the new block is created under exactly that ID, which is what lets   $blocksOrder  put it in front of the existing blocks   1  and   4  here:     {\n       \"build\"  : {\n           \"blocks\"  : [\n               {\n                   \"$create\"  :   true  ,\n                   \"id\"  :   9  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"title\"  :   \"Which color do you like least?\"  ,\n                   \"items\"  : [\n                       {   \"id\"  :   1  ,   \"title\"  :   \"green\"   },\n                       {   \"id\"  :   2  ,   \"title\"  :   \"red\"   }\n                   ]\n               }\n           ],\n           \"$blocksOrder\"  : [  9  ,   1  ,   4  ]\n       }\n   }\n  Take the ID from   nextBlockId  and count up from there if you add several blocks at once; claiming an ID that is already taken is rejected with an error naming the next free one, never silently renumbered. Do it whenever   the same request has to   reference  the new block -   $blocksOrder  is the usual case, and a   logic  tree sent along with it is another;  you want the ID to be   predictable  for your own stats, webhook or logic handling instead of learning it from the response.  The same applies inside the new block: its items, fields, results and other entries take their own   id , exactly as in a   POST /riddle-builder  build. See   custom IDs  and   item formats .  Block IDs  IDs are handed out by a counter that   only ever grows  and that is   shared  between the Riddle's blocks, results, personalities and attributes. Two consequences:   an ID freed by a deletion never comes back, and  no ID visible in   build  tells you which one is free - the highest block ID plus one is usually already taken by a result.  So take the ID for a   $create  entry from   nextBlockId  and count up from there if you add several blocks at once. Claiming a taken ID is rejected with an error naming the next free one, never silently renumbered. A   $create  without an   id  gets one assigned; sending one yourself creates the block under exactly that ID - see   choosing the new block's ID .   Note:  The IDs an edit can address are the ones the Riddle had   before  the request. A block created in the same request cannot also be edited by it - send its final state in the   $create  entry instead.   Note:  All of the above is about   block  IDs. The IDs   inside  a block - an answer item's   id , a form field's   id , a result page block's   id  - are counted   per collection  and start at   1  in every single one of them, so the same   id  legitimately appears in every block of the Riddle. Never take one of those from   nextBlockId : read the collection back and use the IDs it reports (or omit   id  in a   $create  entry and let one be assigned).   nextBlockId  only ever answers the question \"which top-level block ID is free\".  Removing a block:   $delete     {\n       \"build\"  : {\n           \"blocks\"  : [\n               {   \"id\"  :   3  ,   \"$delete\"  :   true   }\n           ]\n       }\n   }\n  Nothing else about such an entry is built - you can send back a block object read from   GET  untouched and just add the marker, without stripping its properties first.  Two things are rejected rather than applied:   an edit that would leave the Riddle   without any blocks  (a Riddle needs at least one, otherwise it is neither usable in the Creator nor publishable);  deleting a block that the Riddle's   custom logic  still references - see   below .  Deleting a block that the logic references  If the Riddle has   custom    logic  that still references a block you are deleting, the request is rejected with an error naming exactly which deleted block is still referenced by which logic node. Resolve it in the same request, either by   sending a full replacement   logic  tree that no longer references the deleted block(s), or  discarding the custom logic with   \"logic\": {\"$reset\": true} , which falls back to the default linear flow.     {\n       \"build\"  : {\n           \"blocks\"  : [\n               {   \"id\"  :   3  ,   \"$delete\"  :   true   }\n           ],\n           \"logic\"  : {   \"$reset\"  :   true   }\n       }\n   }\n   $reset  is exclusive: combining it with any other key inside   logic  is rejected, and its value has to be   true  or   false .  This guard never fires when the Riddle's logic is still the automatically generated default one - that logic is regenerated from the current block order on every build, so deleting a block always works there.  Reordering:   $blocksOrder  and friends  Order is a marker of its own, sitting next to the collection it orders and named after it:   $blocksOrder  for the Riddle's blocks,   $itemsOrder  inside a block entry for that block's items,   $fieldsOrder  for a FormBuilder's fields, and so on.     {\n       \"build\"  : {\n           \"blocks\"  : [\n               {   \"id\"  :   1  ,   \"$itemsOrder\"  : [  2  ,   1  ,   3  ] }\n           ],\n           \"$blocksOrder\"  : [  3  ,   1  ]\n       }\n   }\n  The value is always the   complete  list of that collection's IDs, every ID exactly once. A partial list is rejected: where the IDs you left out belong is exactly what it does not say.  An order marker is applied   last , after everything else in the same request, so it describes the collection as that request leaves it:   a block you delete in this request must   not  be listed;  a block you create in this request   must  be listed - which is why a   $create  entry needs an explicit   id  to be orderable.  An order on its own is a valid edit.  Which collections can be ordered  Only collections whose entries are stored with an ID of their own, and only at the Riddle level or on a top-level block entry - a block nested inside another block has no addressable entry to put a marker in yet.  Everything else is simply   sent in the order you want it in , and says so in the error if you try to order it:     Kind  Examples    Plain lists of values   recipientCC  /   recipientBCC  /   replyTo , a Recommended Content block's   selectedRiddles  /   riddleTypes  /   tags , a TypeRush item's   answers ,   reactionScale , a Slot Machine's   customSymbols , a Leaderboard's   riddleConnections   Maps keyed by something else   tracking  /   trackingNetworks ,   networks  /   networkConfigs ,   variables   Lists whose position is their meaning   individualBlockTimes  (one per block), a personality answer's   scores  (one per personality)   Collections an edit rewrites as a whole   results , a Placeholder's   conditions   Merged by   id , but with a fixed order   personalities  (Personality Test)  A Personality Test's   personalities  is the one collection which merges by   id  and still cannot be reordered: there is no   $personalitiesOrder , and sending one is rejected. Because the entries are matched by   id , the order you send them in has no meaning either - a   \"$create\"  is appended at the end, everything else keeps the place it has, and reordering the personalities is done in the Creator. See   Editing the personalities  above.  Rules and errors     Situation  Result    A block entry with neither an   id  nor   $create  Rejected - an edit addresses an existing block by its ID   An   id  that does not exist in this Riddle  Rejected, with the list of IDs that do exist   The same   id  addressed twice in one request  Rejected    $create  and   $delete  on the same entry  Rejected   A marker whose value is not   true  /   false  Rejected (a truthy string would otherwise delete a block)   An unknown marker, e.g.   $itemOrder  Rejected, with the list of markers supported there   Any marker in a   POST /riddle-builder  request  Rejected - markers only mean something relative to stored content; in a create build the order of the payload   is  the order   An order marker on a collection that cannot be ordered  Rejected, naming the reason - send the collection in the order you want instead   An order marker that is incomplete, has an unknown ID, a duplicate ID, or is not a list of integers  Rejected   A property that the Riddle type or block does not know, e.g.   titel  Rejected, with the list of properties supported there - see below   The Riddle is still being built by a queued   POST  request  Rejected - try again once it is done  Unknown properties are always rejected here. In a   POST /riddle-builder  build they are ignored unless you ask for them to be rejected with   strictProperties: true ; an edit has no such option, because there a dropped property is indistinguishable from \"the Riddle already looked like that\" - you would read back exactly what you sent and never learn that nothing happened.  Every edit is   one transaction : if any part of it is rejected, the Riddle stays exactly as it was. The error format is the same as for a build - see   exception handling .  Response   PUT /riddle-builder/{UUID}  answers with the same Riddle response that   POST /riddle-builder  returns, including the Riddle data. To get the edited Riddle back as a builder config again, read it with   GET /riddle-builder/{UUID} .  Changes land in the   draft . An embedded Riddle only changes once it is published again - either with   \"publish\": true  in the same request, or via the   publish endpoint .  Full example  Rename the Riddle, rewrite one question's title, edit the answers of another, add a new question, remove the NPS block and put the blocks in a new order - in one request:     {\n       \"build\"  : {\n           \"title\"  :   \"Favorite color poll (2026)\"  ,\n           \"blocks\"  : [\n               {   \"id\"  :   1  ,   \"title\"  :   \"What is your favorite color, really?\"   },\n               {\n                   \"id\"  :   4  ,\n                   \"items\"  : [\n                       {   \"id\"  :   1  ,   \"title\"  :   \"emerald green\"   },\n                       {   \"id\"  :   2  ,   \"$delete\"  :   true   },\n                       {   \"$create\"  :   true  ,   \"title\"  :   \"blue\"   }\n                   ]\n               },\n               {\n                   \"$create\"  :   true  ,\n                   \"id\"  :   9  ,\n                   \"type\"  :   \"SingleChoice\"  ,\n                   \"title\"  :   \"Which color do you like least?\"  ,\n                   \"items\"  : [\n                       {   \"title\"  :   \"green\"   },\n                       {   \"title\"  :   \"red\"   }\n                   ]\n               },\n               {   \"id\"  :   3  ,   \"$delete\"  :   true   }\n           ],\n           \"$blocksOrder\"  : [  9  ,   1  ,   4  ]\n       },\n       \"publish\"  :   true\n   }\n   block   1  keeps its answers, media and settings - only the title changes  block   4  renames the answer with ID   1 , removes the one with ID   2  and gains a new answer; every answer it does not list stays as it is  block   9  is new, with the ID taken from   nextBlockId , so   $blocksOrder  can name it  block   3  is removed, so it must not appear in   $blocksOrder   $blocksOrder  lists every block the Riddle has afterwards, exactly once  Next steps    Read a Riddle back as a build configuration   Item formats: how a collection merges by   id , and how to add an entry to it   Switch a configured feature back off   Assign your own IDs to blocks, items and results   Define the logic settings / flow of your Riddle   Re-route a Placeholder by editing its conditions   Handle exceptions  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":440,"path":441,"dir":442,"title":443,"description":444,"keywords":445,"body":450},"content:15.Api:5.Generate Riddles with AI:0.Getting started.md","/api/generate-riddles-with-ai/getting-started","generate-riddles-with-ai","Getting started - Generate Riddles with AI","Learn how to generate Riddles with AI via API",[446,447,448,449,16],"Providing context","Asynchronous generation","Knowing when the Riddle is ready","API limits and usage","  Getting started  You can use the   Riddle Generative AI API  to generate Riddles, populated with content from generative AI models.  Not familiar with the API yet? Read the   Getting started  guide first to learn about authentication and the response format.  Providing context  Generally there are two approaches you can take for providing context / content:    Topic : Supply a topic or theme for the Riddle, e.g. 'Soccer', 'Harry Potter'   URL : Provide a URL to a website, blog or article that contains the content you want to use for the Riddle. You can also provide   multiple URLs  in a single request – the AI combines the content of all pages into one Riddle (currently available for quizzes via the   /riddle-ai/url/quiz/bulk  endpoint).  Asynchronous generation  The Riddle AI generation happens asynchronously, meaning the Riddle will be generated in the background and the Riddle will not be visible in the Creator / on the landing page yet.  The API only returns a UUID and the requested Riddle type:     {\n       \"UUID\"  :   \"as12Dcs\"  ,\n       \"type\"  :   \"Quiz\"\n   }\n   Tip:  You can save this UUID to your database, for example to later call the API to analyse the Riddle's stats or leads.  Knowing when the Riddle is ready  As the Riddle is generated in the background, you need a way to find out when it is actually finished. There are two ways to do that – pick the one that fits your integration:     Approach  How it works  Use it when     Status endpoint  You ask the API for the state of the generation and check again until it is finished  Your code runs as a long-running process (a script, a job, a CLI command) that can keep checking before it continues    Callback URL  You pass a   callbackUrl  and we send a webhook with the finished Riddle to your server  Your code cannot wait – e.g. a web request that has to return immediately – and you can receive incoming HTTP requests  Status endpoint  Call   /riddle-ai/status/{UUID}  with the UUID you received from the creation endpoint:   GET https://www.riddle.com/creator/api/v3/riddle-ai/status/as12Dcs\n  The response tells you where the generation stands:     {\n       \"UUID\"  :   \"as12Dcs\"  ,\n       \"type\"  :   \"Quiz\"  ,\n       \"title\"  :   \"Formula 1\"  ,\n       \"status\"  :   \"completed\"  ,\n       \"isFinished\"  :   true  ,\n       \"error\"  :   null  ,\n       \"retryAfterSeconds\"  :   null\n   }\n     Property  Type  Description     UUID  string  The UUID of the generated Riddle    type  string  The Riddle type, e.g.   Quiz    title  string|null  The title of the Riddle. While the generation is still   pending  this is an internal placeholder – only rely on it once the status is   completed    status  string   pending ,   completed  or   failed ; see below    isFinished  boolean   false  while the generation is still running,   true  once it either completed or failed    error  string|null  Why the generation failed;   null  unless   status  is   failed    retryAfterSeconds  integer|null  How many seconds to wait before asking for the status again;   null  once the generation is finished  The three states are:     pending : the Riddle is still being generated. It exists, but it has no content yet – do not fetch, update or publish it.    completed : everything is done. The content was generated, the   build configuration  was applied and the Riddle was published, if you asked for it. Only now the Riddle is ready to be used and embedded.    failed : the generation did not succeed and   error  tells you why.  How often to check  The endpoint always answers immediately, so you have to ask again while the generation is still running. Every   pending  response tells you how long to wait before doing so via   retryAfterSeconds :     {\n       \"UUID\"  :   \"as12Dcs\"  ,\n       \"type\"  :   \"Quiz\"  ,\n       \"title\"  :   \"Riddle Builder\"  ,\n       \"status\"  :   \"pending\"  ,\n       \"isFinished\"  :   false  ,\n       \"error\"  :   null  ,\n       \"retryAfterSeconds\"  :   5\n   }\n  A generation usually takes   20 – 60 seconds ; generations based on one or more URLs take longer, as the given pages have to be scraped first. So expect to check several times:     # check the status until the generation is finished\n   while true; do\n       STATUS=$(curl --silent --location \\\n           --request GET 'https://www.riddle.com/creator/api/v3/riddle-ai/status/as12Dcs' \\\n           --header 'Authorization: Bearer [your API key]')\n   \n       echo \"$STATUS\" | grep -q '\"isFinished\":true' && break\n   \n       sleep 5 # the seconds returned in retryAfterSeconds\n   done\n   Important:  Always respect   retryAfterSeconds  and do not poll in a tight loop. If you cannot check periodically at all, use a   callbackUrl  instead of hammering this endpoint.  Errors  The status endpoint returns a   400  error if the Riddle exists but was   not  created by the Riddle AI, as there is no generation to report on:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"BAD_REQUEST\"  ,\n       \"message\"  :   \"Riddle as12Dcs was not created by the Riddle AI.\"\n   }\n  A UUID that does not exist – or that your API key cannot access – results in the usual   404  /   403  errors.  API limits and usage  The generative AI API has strict limits per month, differentiated for each plan:    Pro : 15 calls/month   Business : 30 calls/month   Enterprise : 50 calls/month  Fetch current usage  You can check your current usage dynamically by calling the   AI usage endpoint . This will return a JSON object with the current usage and limits:     {\n       \"current\"  :   5  ,\n       \"max\"  :   50\n   }\n   Note:  The returned usage may be multiplied by 12 if your subscription is billed annually. For example, if you are on the   Pro  plan, the usage will be 15 * 12 = 180.  Next steps    Create a Quiz, Poll, or Personality Test based on a topic   Create a Quiz or Poll based on one or more URLs   Generate Riddles in your projects   Enrich generated Riddles with a build configuration  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":452,"path":453,"dir":442,"title":454,"description":455,"keywords":456,"body":459},"content:15.Api:5.Generate Riddles with AI:1.Topic.md","/api/generate-riddles-with-ai/topic","AI Riddle via topic - Generate Riddles with AI","Learn how to generate Riddles with AI based on a topic via API",[457,458],"Generating different Riddle types","Optional parameters","  Generating AI Riddle via topic  A topic or theme can be provided to the generative AI API to get a Riddle surrounding a rather general subject; opposing to specific content, e.g. attributed to an URL.  Generating different Riddle types  Generate a Quiz  To generate a quiz about 'Soccer', use the   /riddle-ai/topic/quiz  API endpoint. Here is an example payload:     {\n       \"topic\"  :   \"Soccer\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"  ,\n       \"difficulty\"  :   \"easy\"\n   }\n  Generate a Poll  To generate a poll about 'Harry Potter', use the   /riddle-ai/topic/poll  API endpoint. Here is an example payload:     {\n       \"topic\"  :   \"Harry Potter\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"\n   }\n  Generate a Personality test  To generate a personality quiz about 'Harry Potter', use the   /riddle-ai/topic/personality  API endpoint.  Example payload:     {\n       \"topic\"  :   \"Harry Potter\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"  ,\n       \"numAttributes\"  :   0  ,\n       \"numPersonalities\"  :   3\n   }\n  Optional parameters  There are several optional parameters   you can use with every Riddle type  to further customize the generated Riddle and control its flow:     Property  Type  Description  Default     project  integer|null  The project the generated Riddle will be assigned to; pass   NULL  if it should be added to the personal project     publish  boolean  Whether to publish the Riddle immediately after generation; pass   false  to only generate a draft  false    callbackUrl  string  A URL to which the generated Riddle will be sent; useful as the generation happens asynchronously     build  object  A   Riddle Builder API  configuration applied on top of the generated content (result pages, preset, publish settings, ...);   learn more     strictProperties  boolean  Reject a   build  property that no Riddle type or block knows with a   400  - answered immediately and without consuming any AI usage - instead of silently ignoring it  false   Tip:  Using the   callbackUrl  parameter is a good way to avoid having to poll the API for the Riddle ID. You can use this URL to trigger a webhook to your server and be notified when the Riddle is ready to use and for embedding. If your integration cannot receive a webhook but can check periodically, use the   status endpoint  instead.  Example Poll object     {\n       \"topic\"  :   \"Harry Potter\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"  ,\n       \"project\"  :   123  ,\n       \"publish\"  :   true  ,\n       \"callbackUrl\"  :   \"https://your-website.com/callback\"  ,\n       \"build\"  : {\n           \"result\"  : {\n               \"title\"  :   \"Thanks for voting!\"  ,\n               \"description\"  :   \"Check back tomorrow for a new poll.\"\n           }\n       }\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":461,"path":462,"dir":442,"title":463,"description":464,"keywords":465,"body":466},"content:15.Api:5.Generate Riddles with AI:2.URL.md","/api/generate-riddles-with-ai/url","AI Riddle via URL - Generate Riddles with AI","Learn how to generate Riddles with AI based on a URL via API",[457,458],"  Generating AI Riddle via URL  A URL can be provided to the AI API to get a Riddle surrounding a rather specific context, as opposed to general content, e.g., topics or trivia quizzes.  Generating different Riddle types  Generate a Quiz  To generate a quiz about any URL, use the   /riddle-ai/url/quiz  API endpoint. Here is an example payload which generates a quiz about Riddle's pricing:     {\n       \"url\"  :   \"https://www.riddle.com/pricing\"  ,\n       \"language\"  :   \"en\"  ,\n       \"numQuestions\"  :   5  ,\n       \"difficulty\"  :   \"easy\"\n   }\n  Generate a Quiz from multiple URLs  You can also generate a single quiz from   multiple URLs  at once. Use the   /riddle-ai/url/quiz/bulk  API endpoint and pass the URLs as an array via the   urls  parameter – the AI combines the content of all pages into one quiz:     {\n       \"urls\"  : [\n           \"https://www.riddle.com/pricing\"  ,\n           \"https://www.riddle.com/quiz-maker\"\n       ],\n       \"language\"  :   \"en\"  ,\n       \"numQuestions\"  :   5  ,\n       \"difficulty\"  :   \"easy\"\n   }\n  Generate a Poll  To generate a poll about any URL, use the   /riddle-ai/url/poll  API endpoint. Here is an example payload which generates a poll about Riddle's pricing (not particularly interesting/engaging, but you get the idea):     {\n       \"url\"  :   \"https://www.riddle.com/pricing\"  ,\n       \"language\"  :   \"en\"  ,\n       \"numQuestions\"  :   5\n   }\n  Optional parameters  There are several optional parameters   you can use with every Riddle type  to further customize the generated Riddle and control its flow:     Property  Type  Description  Default     project  integer|null  The project the generated Riddle will be assigned to; pass   NULL  if it should be added to the personal project     publish  boolean  Whether to publish the Riddle immediately after generation; pass   false  to only generate a draft  false    callbackUrl  string  A URL to which the generated Riddle will be sent; useful as the generation happens asynchronously     build  object  A   Riddle Builder API  configuration applied on top of the generated content (result pages, preset, publish settings, ...);   learn more     strictProperties  boolean  Reject a   build  property that no Riddle type or block knows with a   400  - answered immediately and without consuming any AI usage - instead of silently ignoring it  false   Tip:  Using the   callbackUrl  parameter is a good way to avoid having to poll the API for the Riddle ID. You can use this URL to trigger a webhook to your server and be notified when the Riddle is ready to use and for embedding. If your integration cannot receive a webhook but can check periodically, use the   status endpoint  instead.  Example Poll object     {\n       \"url\"  :   \"https://www.riddle.com/pricing\"  ,\n       \"language\"  :   \"en\"  ,\n       \"numQuestions\"  :   5  ,\n       \"project\"  :   123  ,\n       \"publish\"  :   true  ,\n       \"callbackUrl\"  :   \"https://your-website.com/callback\"  ,\n       \"build\"  : {\n           \"result\"  : {\n               \"title\"  :   \"Thanks for voting!\"  ,\n               \"description\"  :   \"Check back tomorrow for a new poll.\"\n           },\n           \"preset\"  : {\n               \"preset\"  :   805  ,\n               \"palette\"  :   \"Zymx\"\n           }\n       }\n   }\n  The   build  object here replaces the generated result page and applies your own preset and palette. As this is a Poll, the result page is set with   result  – for a Quiz you would send an array of   results  instead.   Click here  to see everything you can configure per Riddle type.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":468,"path":469,"dir":442,"title":470,"description":471,"keywords":472,"body":473},"content:15.Api:5.Generate Riddles with AI:3.Project.md","/api/generate-riddles-with-ai/project","Generate Riddles in your projects - Generate Riddles with AI","Learn how to generate Riddles in your projects via API",[98],"  Generate Riddles in your projects  By default the project of the accessing API key will be used - this means that if you use an API key created in your personal project the newly generated AI Riddle will always be added to your personal space.  To change this you can specify the   project  in the root to create the Riddle in a specific project.  Example  The following example generates a Riddle about soccer in the project with the ID   12345 :     {\n       \"topic\"  :   \"Soccer\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"  ,\n       \"difficulty\"  :   \"easy\"  ,\n       \"project\"  :   12345\n   }\n  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":475,"path":476,"dir":442,"title":477,"description":478,"keywords":479,"body":484},"content:15.Api:5.Generate Riddles with AI:4.Build configuration.md","/api/generate-riddles-with-ai/build-configuration","Build configuration - Generate Riddles with AI","Learn how to enrich AI generated Riddles with a Riddle Builder API configuration",[480,481,482,149,483,16],"How it works","What you can configure","What you cannot configure","Error handling","  Enriching AI Riddles with a build configuration  By default the generative AI API decides everything about the Riddle it creates – not only the questions and answers, but also the result pages, the design and the publish settings. With the optional   build  parameter you can take that control back: it accepts a   Riddle Builder API  configuration which is applied   on top of  the generated content.  Typical use cases:   always applying your own project preset and palette, so every generated Riddle is on brand  replacing the generated result pages with your own copy, calls to action or images  enabling publish settings (showcase, double opt-in, tracking, data layer variables) right away  connecting generated quizzes to a leaderboard  How it works  The   build  parameter is available on   all AI creation endpoints  (topic and URL based, for every supported Riddle type). Every property it accepts has exactly the same format as in the   Riddle Builder API , so you can reuse everything you already know from the Build Riddles section – except for the content itself.  Add it next to the regular AI parameters:     {\n       \"topic\"  :   \"Formula 1\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"  ,\n       \"difficulty\"  :   \"easy\"  ,\n       \"build\"  : {\n           \"preset\"  : {\n               \"preset\"  :   805  ,\n               \"palette\"  :   \"Zymx\"\n           },\n           \"publish\"  : {\n               \"isShowcaseEnabled\"  :   true\n           }\n       }\n   }\n  Internally the steps happen in this order:   The AI generates the content (questions, answers, personalities, ...)  The default content around it (result pages, ...) is created and translated into the requested   language   Your build configuration is applied on top of the generated Riddle  The Riddle is published, if   publish  was set to   true  Because your configuration is applied   after  the translation, any text you send in the   build  object is used   exactly as you sent it  – it is never translated or rewritten by the AI.  All of this happens in the background, so your configuration is not applied yet when the creation endpoint responds. The   status endpoint  only reports   completed  once the build configuration was applied as well.  What you can configure  Only the configuration   around  the content can be set – the content itself is generated by the AI. Which properties are available depends on the Riddle type you are generating:     Property  Quiz  Poll  Personality  Description     title  ✓  ✓  ✓  Overrides the title generated by the AI; omit it to keep the generated one    results  ✓    The   result pages  with their score ranges    result   ✓  ✓  The single   result page  / result template    logic  ✓  ✓   Custom   block logic    preset  ✓  ✓  ✓   Preset settings : project preset, palette, language, timers, ...    publish  ✓  ✓  ✓   Publish settings : showcase, double opt-in, email automation, tracking, ...    leaderboard  ✓     Leaderboard  connections; needs extra configuration, see   below   Note:  The   publish  property inside the build object holds the publish   settings  – it is not the same as the   publish  boolean in the root of the request, which controls whether the Riddle goes live immediately. You can use both together.  What you cannot configure  The content properties are rejected, as this is exactly what the AI generates for you:     Property  Riddle type     blocks  all types    personalities  Personality  Sending one of them fails the request   immediately  with a validation error – you do not have to wait for the asynchronous generation to find out:     {\n       \"success\"  :   false  ,\n       \"code\"  :   400  ,\n       \"error\"  :   \"RIDDLE_BUILDER_BLOCK_PROPERTY_VALUE_VALIDATION\"  ,\n       \"message\"  :   \"QuizBuilder: Property   \\\"  blocks  \\\"   is not supported here - the content itself is generated and cannot be specified in the build configuration.\"\n   }\n  If you want to define the questions and answers yourself, use the   Riddle Builder API  instead – it builds a Riddle entirely from your configuration, without any AI involved.  Result pages  Result pages are the most common reason to use a build configuration, so it is worth knowing how they behave:    Omit    result /  results  and the result pages generated by the AI are kept as they are.   Send    result /  results  and the generated result pages are   completely replaced  by yours. This is a replacement, not a merge – so send all result pages you want the Riddle to have.  Example: Quiz with custom result pages  For a   Quiz  the result pages are wired into the Riddle logic via their score ranges. When you send your own   results , that logic is rebuilt from your score ranges, so make sure the ranges you send cover 0 – 100% without gaps.     {\n       \"topic\"  :   \"Formula 1\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"  ,\n       \"difficulty\"  :   \"easy\"  ,\n       \"publish\"  :   true  ,\n       \"build\"  : {\n           \"results\"  : [\n               {\n                   \"minPercentage\"  :   0  ,\n                   \"maxPercentage\"  :   49  ,\n                   \"title\"  :   \"Rookie\"  ,\n                   \"description\"  :   \"Time to brush up on the basics!\"\n               },\n               {\n                   \"minPercentage\"  :   50  ,\n                   \"maxPercentage\"  :   100  ,\n                   \"title\"  :   \"Champion\"  ,\n                   \"description\"  :   \"You know your stuff!\"\n               }\n           ],\n           \"preset\"  : {\n               \"preset\"  :   805  ,\n               \"palette\"  :   \"Zymx\"\n           },\n           \"publish\"  : {\n               \"isShowcaseEnabled\"  :   true\n           }\n       }\n   }\n  Example: Poll with a single result page  A Poll (and a Personality test) only has one result page, so the property is called   result  instead of   results :     {\n       \"topic\"  :   \"Harry Potter\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"  ,\n       \"build\"  : {\n           \"title\"  :   \"What the community thinks\"  ,\n           \"result\"  : {\n               \"title\"  :   \"Thanks for voting!\"  ,\n               \"description\"  :   \"Check back tomorrow for a new poll.\"\n           }\n       }\n   }\n  Example: Quiz connected to a leaderboard  Leaderboard connections are set in   build.leaderboard.connections , exactly as described in   Create and connect to Leaderboard .   Important:  A leaderboard needs a nickname (and usually an identifier) to rank participants. For built Riddles these are detected automatically from the   Name  and   Email  form fields – but an AI generated Riddle contains   no form blocks , and you cannot add them via the build configuration because blocks are content. You therefore have to point   nickname  – and   identifier , if the leaderboard requires email verification – to   data layer  variables instead:     {\n       \"url\"  :   \"https://www.your-website.com/article\"  ,\n       \"numQuestions\"  :   5  ,\n       \"language\"  :   \"en\"  ,\n       \"difficulty\"  :   \"medium\"  ,\n       \"publish\"  :   true  ,\n       \"build\"  : {\n           \"publish\"  : {\n               \"dataLayerItems\"  : {\n                   \"nickname\"  :   \"Nickname\"  ,\n                   \"email\"  :   \"Email\"\n               }\n           },\n           \"leaderboard\"  : {\n               \"nickname\"  :   \"dataLayer:nickname\"  ,\n               \"identifier\"  :   \"dataLayer:email\"  ,\n               \"connections\"  : [  \"Fw5uSygx\"  ]\n           }\n       }\n   }\n  The data layer values are then passed in when the Riddle is embedded or opened, e.g.   riddle.com/view/XXX?nickname=Ada&email=ada@your-website.com .  Error handling  There are two moments at which a build configuration can fail:    When you send the request.  Content properties (  blocks ,   personalities ) are validated right away, so you get a   400  response immediately and no AI usage is consumed. The same is true for properties no Riddle type or block knows at all – but only if you ask for it: add   strictProperties: true  next to   build  and a typo such as   titel  is rejected with the list of properties supported in its place, instead of being silently ignored and generating a Riddle that does not have what you configured.   While the Riddle is generated.  Everything else is validated when the configuration is applied, which happens asynchronously after the AI has returned its content. If it fails, all changes to the Riddle are reverted so it stays usable with the generated content, and the error is stored on the AI prompt.  The error format and the exception types are the same as for the Riddle Builder API – see   Exception handling  for the full list.   Tip:  Build your configuration once with the   Riddle Builder API  before using it here. Its endpoint is synchronous, so you get validation errors instantly instead of having to wait for an AI generation to complete.  Next steps    Build Riddles from scratch with the Builder API   Result pages   Preset settings   Publish settings  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":486,"path":487,"dir":488,"title":489,"description":490,"keywords":491,"body":503},"content:15.Api:6.Question Banks:0.Getting started.md","/api/question-banks/getting-started","question-banks","Getting started - Question Banks","Learn how to create and manage question banks via API",[492,493,494,495,496,497,498,499,500,501,502,16],"Draft and published state","Create a bank","List your banks","Get a single bank","Rename a bank","Set the notes of a bank","Duplicate a bank","Publish a bank","Discard your changes","Delete a bank","Use a bank in a Riddle","  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:     Property  Required  Type  Description     riddleType  yes  string   Quiz  or   Poll  - cannot be changed later    title   string|null  The title of the bank; defaults to   \"New question bank\"    project   integer|null  The 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     {\n       \"riddleType\"  :   \"Quiz\"  ,\n       \"title\"  :   \"History questions\"\n   }\n  The response contains the new bank, including the   id  you need for every other call:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : {\n           \"id\"  :   4711  ,\n           \"riddleType\"  :   \"Quiz\"  ,\n           \"title\"  :   \"History questions\"  ,\n           \"user\"  :   \"abc123\"  ,\n           \"team\"  :   null  ,\n           \"notes\"  :   null  ,\n           \"tags\"  : [],\n           \"modifiedAt\"  :   \"2026-08-06 10:14:22\"  ,\n           \"createdAt\"  :   \"2026-08-06 10:14:22\"  ,\n           \"publishedAt\"  :   null  ,\n           \"itemCount\"  :   0  ,\n           \"draftItemCount\"  :   0  ,\n           \"riddleDependencies\"  : []\n       }\n   }\n     Property  Description     itemCount  The number of   published  items - i.e. the number of questions your Riddles can actually draw from    draftItemCount  The number of items in the draft state, including unpublished additions    publishedAt   null  until the bank was published for the first time    riddleDependencies  The Riddles that currently use this bank, as   {\"UUID\": ..., \"title\": ...}    tags  The   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:     Property  Type  Description     riddleType  string  Only return banks of this type:   Quiz  or   Poll    search  string  A search term matched against the bank title    tags  string  A JSON encoded array of tag IDs, e.g.   [123,456]  - only banks carrying these tags are returned    sortBy  string   createdAt  (default) or   modifiedAt    sortOrder  string   ASC  or   DESC  (default)    page  integer  The page to fetch (default 1)    pageSize  integer  How many banks per page (default 12, maximum 50)    project  integer|null  The 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\n  The response is a list response, i.e. the   data  object holds the   count  of returned banks and the banks themselves in   items :     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : {\n           \"count\"  :   1  ,\n           \"items\"  : [  \"... the banks ...\"  ]\n       }\n   }\n  Banks in this list carry a few additional properties on top of the shape above:     Property  Description     hasChanges   true  when the draft state differs from the published one, i.e. the bank has to be published again    isPublicTemplate  Whether this bank is a   template    categories  Every category used by the bank's items    blockTypeCategoryMap  Which 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):     {\n       \"title\"  :   \"History questions 2026\"\n   }\n  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:     {\n       \"notes\"  :   \"Sourced from our 2026 history course. Ask marketing before changing.\"\n   }\n  Duplicate a bank   /question-bank/{questionBank}/duplicate  copies a bank   and all of its items :     Property  Required  Type  Description     title  yes  string  The title of the copy    project   integer|null  The 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:     {\n       \"blocks\"  : [\n           {\n               \"type\"  :   \"QuestionBank\"  ,\n               \"questionBankId\"  :   4711  ,\n               \"questionBankBlocks\"  : [\n                   {\n                       \"blockType\"  :   \"SingleChoice\"  ,\n                       \"isEnabled\"  :   true  ,\n                       \"questionBankCriteria\"  : [\n                           {\n                               \"category\"  :   \"History\"  ,\n                               \"difficultyRange\"  : [  3  ,   7  ],\n                               \"maxNumberOfQuestions\"  :   5\n                           }\n                       ]\n                   }\n               ]\n           }\n       ]\n   }\n  See the   Quiz  and   Poll  block reference for every property of the block.  Next steps     Manage items : Add, update, list and delete the questions of a bank.    Manage tags : Organize your banks with tags and use them as list filters.    Templates : Start from a ready-made public bank instead of an empty one.    Look at the specification of all available API endpoints : Find out what you can do with the Riddle API.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":505,"path":506,"dir":488,"title":507,"description":508,"keywords":509,"body":517},"content:15.Api:6.Question Banks:1.Items.md","/api/question-banks/items","Items - Question Banks","Learn how to add, update, list and delete the questions of a question bank via API",[510,511,512,513,514,515,516],"Columns","Which columns does a block type have?","Add an item","Update an item","Delete an item","List the items of a bank","Check what a Riddle actually draws","  Manage items  The questions of a   question bank  are called   items . Every item is one question and carries four things:     Property  Type  Description     blockType  string  Which kind of block this question can be played as, e.g.   SingleChoice . It has to be a block type the bank's Riddle type supports and   cannot be changed  once the item exists    category  string  A free text label used to group questions, e.g.   History . This is what a Riddle draws by, so keep your categories consistent    difficulty  integer  How hard the question is, from   1  to   10 . A Riddle can draw a range of it    columns  object  The actual content of the question - see below  Columns  An item does not have a fixed set of fields; it has   columns , and which columns exist depends on its   blockType . A   SingleChoice  quiz question, for example, has a   QUESTION , at least one   CORRECT_CHOICE  and at least one   INCORRECT_CHOICE .   columns  is an object with the column names as keys. Each key holds the   ordered list  of that column's values, and every value is an object of exactly   {\"id\": int|null, \"value\": string} :     {\n       \"QUESTION\"  : [\n           {  \"id\"  :   null  ,   \"value\"  :   \"In which year did the Berlin Wall fall?\"  }\n       ],\n       \"CORRECT_CHOICE\"  : [\n           {  \"id\"  :   null  ,   \"value\"  :   \"1989\"  }\n       ],\n       \"INCORRECT_CHOICE\"  : [\n           {  \"id\"  :   null  ,   \"value\"  :   \"1987\"  },\n           {  \"id\"  :   null  ,   \"value\"  :   \"1991\"  },\n           {  \"id\"  :   null  ,   \"value\"  :   \"1993\"  }\n       ]\n   }\n  The   id  addresses a value in later updates:   Pass   \"id\": null  to   add  a value - an ID is assigned and returned to you.  Pass an ID the item already has to   update  that value. An ID that belongs to another item is rejected.  Leave a value out to   remove  it.   Note:  Values whose   value  is empty are dropped instead of stored, and duplicate IDs as well as duplicate choices within one item are rejected.   Note:  Text is stored without support for 4-byte characters, so emoji cannot be used in a question bank item.  Which columns does a block type have?   /question-bank/grid/block-type-columns/{riddleType}  returns every block type of a Riddle type together with its columns, so you do not have to hardcode them:   GET /question-bank/grid/block-type-columns/Quiz\n     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : [\n           {\n               \"blockType\"  :   \"SingleChoice\"  ,\n               \"columns\"  : {\n                   \"QUESTION\"  :   1  ,\n                   \"DESCRIPTION\"  :   0  ,\n                   \"CORRECT_CHOICE\"  :   1  ,\n                   \"INCORRECT_CHOICE\"  :   1  ,\n                   \"ANSWER_EXPLANATION_TITLE\"  :   0  ,\n                   \"ANSWER_EXPLANATION_DESCRIPTION\"  :   0\n               }\n           }\n       ]\n   }\n  The number is   how many values that column requires at minimum  –   0  means the column is optional,   1  means at least one value has to be sent. Sending a column that is not listed for the block type, or fewer values than required, is answered with   400  and the error code   QUESTION_BANK_UPDATE .  Add an item   /question-bank/{questionBank}/item  (POST) creates a new item. All four properties are required:     Property  Required  Type  Description     blockType  yes  string  The block type of the question, e.g.   SingleChoice    category  yes  string  The category of the question, at most 255 characters    difficulty  yes  integer   1  -   10    columns  yes  object  The columns of the question, at least one     {\n       \"blockType\"  :   \"SingleChoice\"  ,\n       \"category\"  :   \"History\"  ,\n       \"difficulty\"  :   4  ,\n       \"columns\"  : {\n           \"QUESTION\"  : [{  \"id\"  :   null  ,   \"value\"  :   \"In which year did the Berlin Wall fall?\"  }],\n           \"CORRECT_CHOICE\"  : [{  \"id\"  :   null  ,   \"value\"  :   \"1989\"  }],\n           \"INCORRECT_CHOICE\"  : [\n               {  \"id\"  :   null  ,   \"value\"  :   \"1987\"  },\n               {  \"id\"  :   null  ,   \"value\"  :   \"1991\"  }\n           ]\n       }\n   }\n  The response contains the created item, with the assigned value IDs:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : {\n           \"id\"  :   98765  ,\n           \"questionBank\"  : {  \"... the bank ...\"  },\n           \"blockType\"  :   \"SingleChoice\"  ,\n           \"category\"  :   \"History\"  ,\n           \"difficulty\"  :   4  ,\n           \"columns\"  : {\n               \"QUESTION\"  : [{  \"id\"  :   1  ,   \"value\"  :   \"In which year did the Berlin Wall fall?\"  }],\n               \"CORRECT_CHOICE\"  : [{  \"id\"  :   2  ,   \"value\"  :   \"1989\"  }],\n               \"INCORRECT_CHOICE\"  : [\n                   {  \"id\"  :   3  ,   \"value\"  :   \"1987\"  },\n                   {  \"id\"  :   4  ,   \"value\"  :   \"1991\"  }\n               ]\n           },\n           \"publishedColumns\"  :   null  ,\n           \"modifiedAt\"  :   \"2026-08-06 10:22:41\"  ,\n           \"createdAt\"  :   \"2026-08-06 10:22:41\"\n       }\n   }\n   columns  is the draft state,   publishedColumns  the state your Riddles actually draw from – it stays   null  until the bank is   published .  Update an item   /question-bank/{questionBank}/item/{questionBankItem}  (PUT) takes the same four properties, and all of them are required again – the request describes the   complete  item, so a column you leave out is removed.  The   blockType  has to stay the one the item already has; changing it is rejected with   QUESTION_BANK_UPDATE .   Note:  An item ID that does not exist is answered with   404  and   Question bank item not found. . An item ID that exists but belongs to a different bank than the one in the URL is answered with   403  and   This item does not belong to the specified question bank. .  Delete an item   /question-bank/{questionBank}/item/{questionBankItem}  (DELETE) removes an item from the bank. The response tells you whether the bank now has unpublished changes:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : {\n           \"hasChanges\"  :   true\n       }\n   }\n   Note:  Like every other write, a deletion only reaches your Riddles once the bank is published.  List the items of a bank   /question-bank/{questionBank}/items  returns the items of a bank. All parameters are optional   query  parameters:     Property  Type  Description     search  string  A search term matched against the column values, e.g. a question title or a choice    blockType  string  Only return items of this block type    category  string  Only return items of this category    difficulty  string  A range formatted as   min,max , e.g.   1,5    page  integer  The page to return, starting at 1.   Omit to return every matching item at once    pageSize  integer  Items per page, only used together with   page  (default 50, maximum 100)   GET /question-bank/4711/items?blockType=SingleChoice&category=History&difficulty=3,7\n   Note:    blockType  is validated against the block types the bank's Riddle type actually supports. An unsupported value is rejected with   400 , and the message names every allowed type, e.g.   \"blockType\" must be one of \"SingleChoice\", \"MultipleChoice\" for riddle type \"Quiz\", got \"Foo\". .   Note:    difficulty  must have   min  less than or equal to   max . A range the wrong way round is rejected with   400 , e.g.   \"difficulty\" range must have min \u003C= max (valid values: min and max between 1 and 10), got \"7,3\". .  The response holds the   count  of returned items and the items themselves:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : {\n           \"count\"  :   24  ,\n           \"items\"  : [  \"... the items ...\"  ]\n       }\n   }\n  Check what a Riddle actually draws  A   QuestionBank  block asks the bank for questions per block type and category. To see how many published items each of those criteria currently finds, use   /question-bank/riddle-items/{riddle}/{blockId}  with the Riddle UUID and the ID of the   QuestionBank  block:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : [\n           {  \"blockType\"  :   \"SingleChoice\"  ,   \"category\"  :   \"History\"  ,   \"count\"  :   24  },\n           {  \"blockType\"  :   \"MultipleChoice\"  ,   \"category\"  :   \"Sports\"  ,   \"count\"  :   3  }\n       ]\n   }\n   count  is a plain inventory count: it ignores the block's   maxNumberOfQuestions  entirely and reports every published item matching the criterion's   category ,   difficultyRange  and   blockType . It is not a preview of what a draw would actually pick, and it can be (and often is) higher than what the block shows once published, since an actual draw is capped at   maxNumberOfQuestions .  This is the endpoint to use when a Riddle plays fewer questions than you expected: a   count  below the block's   maxNumberOfQuestions  means the bank simply does not hold enough published items for that combination.   Note:  The block ID has to belong to a   QuestionBank  block of that Riddle – any other block type is answered with   400 .   Note:  Publishing is only blocked when every criterion of every   QuestionBank  block in the Riddle matches zero published items. A single criterion matching too few items, or none, while another criterion in the Riddle still matches something, publishes without any warning. Use this endpoint before publishing to check inventory per criterion yourself.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":519,"path":520,"dir":488,"title":521,"description":522,"keywords":523,"body":526},"content:15.Api:6.Question Banks:2.Tags.md","/api/question-banks/tags","Tags - Question Banks","Learn how to tag question banks via API",[53,524,525],"Add a tag to a bank","Remove a tag from a bank","  Manage tags  Tags help you organize your   question banks  – and they are the most reliable way to find a bank again programmatically, as you can   filter the bank list by tag IDs .  Question bank tags and   Riddle tags  are the same set, not two separate ones: a tag you created for a Riddle can be applied to a bank as well, and it keeps the same   id  on both sides. The   count  returned here only counts question banks, though, so   count: 0  means no bank uses the tag, not that the tag is unused overall: it may still be applied to Riddles.  List all tags   /question-bank/tag/list  returns every tag that is applied to at least one question bank, together with how many banks carry it:     Property  Required  Type  Description     project   integer|null  The project you want the tags of; pass an empty value to get your personal ones. If the parameter is omitted, the project of the API key is used     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : [\n           {  \"id\"  :   123  ,   \"name\"  :   \"history\"  ,   \"count\"  :   4  },\n           {  \"id\"  :   456  ,   \"name\"  :   \"onboarding\"  ,   \"count\"  :   1  }\n       ]\n   }\n  Add a tag to a bank   /question-bank/{questionBank}/tag  (POST) applies a tag. Send   either    tagName    or    tagId :     Property  Required  Type  Description     tagName  (one of the two)  string  Creates a new tag with this name and applies it to the bank    tagId  (one of the two)  integer  Applies an already existing tag to the bank     {\n       \"tagName\"  :   \"history\"\n   }\n  Sending neither is answered with   400 . The response contains the bank with its updated   tags .  Remove a tag from a bank   /question-bank/{questionBank}/tag/{tagId}  (DELETE) removes a tag from a bank, where   tagId  is the ID of the tag. The response contains the bank with its remaining   tags .  The tag itself survives as long as it is still applied to another bank or a Riddle. Once nothing uses it any more it is deleted outright, so recreating a tag with the same name later gets a new   id .  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":528,"path":529,"dir":488,"title":530,"description":531,"keywords":532,"body":536},"content:15.Api:6.Question Banks:3.Templates.md","/api/question-banks/templates","Templates - Question Banks","Learn how to use public question bank templates via API",[533,534,535],"List the templates","Preview a template","Start from a template","  Templates  Next to your own   question banks , Riddle maintains a set of   public template banks  – ready-made pools of questions you can start from instead of an empty bank.  Templates are readable by every account: you can list them, read a single one and read its items to preview what is inside. To actually use one,   duplicate  it – the copy is an ordinary bank of yours that you can extend and publish.  List the templates   /question-bank/template-list  returns every public template:     Property  Type  Description     riddleType  string  Only return templates of this type:   Quiz  or   Poll   GET /question-bank/template-list?riddleType=Quiz\n  Because a template belongs to Riddle and not to you, it is returned in a   reduced shape  – without owner, team, notes, tags and dependent Riddles:     {\n       \"success\"  :   true  ,\n       \"code\"  :   200  ,\n       \"data\"  : {\n           \"count\"  :   1  ,\n           \"items\"  : [\n               {\n                   \"id\"  :   42  ,\n                   \"riddleType\"  :   \"Quiz\"  ,\n                   \"title\"  :   \"General knowledge\"  ,\n                   \"modifiedAt\"  :   \"2026-05-04 09:00:00\"  ,\n                   \"createdAt\"  :   \"2026-01-02 09:00:00\"  ,\n                   \"publishedAt\"  :   \"2026-05-04 09:10:00\"  ,\n                   \"itemCount\"  :   120  ,\n                   \"draftItemCount\"  :   120  ,\n                   \"riddleDependencies\"  : [],\n                   \"isPublicTemplate\"  :   true  ,\n                   \"hasChanges\"  :   false  ,\n                   \"categories\"  : [  \"Geography\"  ,   \"History\"  ,   \"Science\"  ],\n                   \"blockTypeCategoryMap\"  : {\n                       \"SingleChoice\"  : [  \"Geography\"  ,   \"History\"  ,   \"Science\"  ]\n                   }\n               }\n           ]\n       }\n   }\n  Use   categories  and   blockTypeCategoryMap  to see which categories a template offers – those are the values you later put into the   questionBankCriteria  of a   QuestionBank  block.  Preview a template  Both   /question-bank/{questionBank}  and   /question-bank/{questionBank}/items  work with a template ID, so you can inspect its questions before duplicating it. The bank inside each returned item is reduced in the same way as above.  Start from a template   /question-bank/{questionBank}/duplicate  copies a template and all of its items into your own project:     {\n       \"title\"  :   \"General knowledge (our version)\"  ,\n       \"project\"  :   123\n   }\n  The copy is a normal bank: it is not a template, you own it, and you can   add items , tag it and publish it like any other.   Note:  All writing endpoints – renaming, notes, items, tags, publishing, deleting – only work on banks you own. Duplicating is the only way to make a template's questions yours.  html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"id":538,"path":539,"dir":21,"title":540,"description":7,"keywords":541,"body":542},"content:15.Api:7.Docs.md","/api/docs","API Docs",[]," ",1787303994469]