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
typeand 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: <value>, 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/*oraudio/*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 (<url>), 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:
{
"type": "SingleChoice",
"title": "What is the capital of France?",
"items": [
{ "title": "Berlin", "isCorrect": false },
{ "title": "Madrid", "isCorrect": false },
{ "title": "Paris", "isCorrect": true }
],
"media": "https://httpbin.io/image/png"
}
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:
{
"type": "SingleChoice",
"title": "What is the capital of France?",
"items": [
{ "title": "Berlin", "isCorrect": false },
{ "title": "Madrid", "isCorrect": false },
{ "title": "Paris", "isCorrect": true }
],
"media": {
"type": "Image",
"url": "https://httpbin.io/image/jpeg",
"altTag": "An image showing the Eiffel Tower in Paris",
"attributionText": "Photo by John Doe",
"attributionUrl": "https://johndoe.com",
"backgroundColor": "#000000",
"overlayColor": "rgba(0,0,0,0.5)"
}
}
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:
{
"type": "SingleChoice",
"title": "What is the capital of France?",
"items": [
{ "title": "Berlin", "isCorrect": false },
{ "title": "Madrid", "isCorrect": false },
{ "title": "Paris", "isCorrect": true }
],
"media": {
"type": "Video",
"url": "https://www.w3schools.com/html/mov_bbb.mp4",
"previewImageUrl": "https://httpbin.io/image/webp",
"autoplay": false,
"loop": true,
"controls": true
}
}
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:
{
"type": "SingleChoice",
"title": "What is the capital of France?",
"items": [
{ "title": "Berlin", "isCorrect": false },
{ "title": "Madrid", "isCorrect": false },
{ "title": "Paris", "isCorrect": true }
],
"media": {
"type": "Audio",
"url": "https://www.w3schools.com/html/horse.mp3",
"previewImage": "https://httpbin.io/image/svg",
"autoplay": false,
"loop": true
}
}
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:
{
"type": "Content",
"title": "Welcome to the quiz",
"description": "This quiz will test your knowledge about France",
"media": {
"type": "YouTube",
"videoId": "dQw4w9WgXcQ",
"autoplay": false,
"loop": true,
"controls": false
}
}
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:
{
"type": "Content",
"title": "Welcome to the quiz",
"description": "This quiz will test your knowledge about France",
"media": {
"type": "Vimeo",
"videoId": "76979871",
"autoplay": false,
"loop": true,
"controls": false
}
}
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:
{
"type": "Content",
"title": "Welcome to the quiz",
"description": "This quiz will test your knowledge about France",
"media": {
"type": "X",
"url": "https://x.com/username/status/1234567890"
}
}
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
typeandurl. A video or embedded video also returnsautoplay,loopandcontrolswhen they were changed, an image itsaltTag, attribution and colors, and audio itsautoplay/loop. - A video's
previewImageUrland an audio file'spreviewImageare not returned - the preview image generated during the upload stays in place when you rebuild.

