Command Palette
Search for a command to run...
GET /v1/questions/random#
GET
/api/v1/questions/random API key required Returns up to 50 random questions in the requested language. This is the killer endpoint for quiz apps — one request, one JSON array, ready to render.
Parameters#
| Parameter | Type | Default | Description |
|---|---|---|---|
| amount | integer | 10 | How many questions to return (1–50). |
| lang | enum | en | Supported: `en`, `pl`. Strict — any other value returns `400`. If we have no questions matching your filters in that language, you get an empty array, not English. |
| category | integer or slug | — | Filter by category. Accepts internal id (1-24), OpenTDB ids (9-32), or canonical slugs like `geography`. |
| difficulty | enum | — | One of: `easy`, `medium`, `hard`. |
| type | enum | — | Default response includes `multiple` and `boolean` only. Pass `?type=text_input` to opt into open-ended questions explicitly. |
| tags | CSV kebab-case | — | All-of match (AND). Example: `tags=capitals,europe`. |
| tags_any | CSV kebab-case | — | Any-of match (OR), max 10. |
| topic | kebab-case | — | Curated topic slug — see [GET /v1/topics](/docs/api/topics). |
| topics_any | CSV kebab-case | — | Any-of match (OR) on curated topics, max 10. |
| subcategory | kebab-case | — | Raw subcategory slug. |
| quality | `high` | — | Pass `quality=high` to exclude questions flagged by distractor validation. |
| regions | CSV ISO 3166-1 | — | All-of match (AND), lowercase 2-letter codes. Example: `regions=pl,de`. |
| source | enum | — | Restrict to one import source: `opentdb`, `opentriviaqa`, `mkqa`, `mintaka`, `nq-open`, `kqa-pro`, `entityq`, `quizbase`. |
| license | SPDX | — | e.g. `CC-BY-SA-4.0`, `MIT`. |
| exclude | CSV UUIDs | — | Up to 250 ids to skip. Useful for de-duplicating within a game session. |
Examples#
Response#
{
"data": [
{
"id": "0193f8b5-7e5c-7c24-9f7a-3d1e1c2a5f10",
"text": "Jaka jest stolica Polski?",
"correctAnswer": "Warszawa",
"incorrectAnswers": ["Kraków", "Gdańsk", "Wrocław"],
"type": "multiple",
"difficulty": "easy",
"language": "pl",
"category": { "id": 14, "slug": "geography", "name": "Geografia" },
"subcategories": [
{ "slug": "european-capitals", "label": "Stolice europejskie" }
],
"tags": [
{ "slug": "capitals", "label": "Stolice" },
{ "slug": "europe", "label": "Europa" }
],
"regions": ["pl"],
"attribution": {
"author": "community",
"source": "opentriviaqa",
"license": "CC-BY-SA-4.0",
"licenseVersion": "4.0",
"licenseUrl": "https://creativecommons.org/licenses/by-sa/4.0/",
"sourceId": "otq:12345",
"url": "https://opentriviaqa.example/q/12345",
"modifications": ["translated_pl"],
"lastModified": "2026-04-24T10:00:00Z"
},
"translationOf": "0193f8b5-7e5c-7c24-9f7a-000000000001",
"rootQuestionId": "0193f8b5-7e5c-7c24-9f7a-000000000001",
"translator": "machine",
"explanation": null,
"extensions": {
"subcategories": ["european-capitals"]
},
"createdAt": "2026-04-24T10:00:00Z",
"updatedAt": "2026-04-24T10:00:00Z"
}
],
"meta": { "count": 5, "language": "pl", "requestId": "req_01HZABC123DEF" }
}{
"type": "https://quizbase.runriva.com/errors/missing_api_key",
"title": "API key required",
"status": 401,
"detail": "Include your API key in the X-API-Key header (or Authorization: Bearer <key>). Get a key at https://quizbase.runriva.com/dashboard/keys.",
"instance": "/api/v1/questions/random?amount=5&lang=pl",
"code": "missing_api_key"
}{
"type": "https://quizbase.runriva.com/errors/rate-limit-exceeded",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit exceeded on requests per day. Limit: 100/day on Free tier. Current: 101/day. Retry after: 3600s.",
"instance": "/api/v1/questions/random",
"code": "rate_limit_exceeded",
"retryAfter": 3600,
"upgradeUrl": "https://quizbase.runriva.com/pricing"
}{
"type": "https://quizbase.runriva.com/errors/invalid_query_param",
"title": "Invalid query parameters",
"status": 400,
"detail": "amount: amount must be between 1 and 50",
"instance": "/api/v1/questions/random?amount=999",
"code": "invalid_query_param",
"errors": [
{ "path": "amount", "message": "amount must be between 1 and 50" }
]
}Rate limits#
Every response carries RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset. On 429 also Retry-After. See Errors and retries for the full picture.
Performance#
- Broad filter (no
tags/topic/subcategory): p50 138ms, p95 158ms (sustained 50 RPS). - Narrow filter (any of
tags,tags_any,topic,topics_any,subcategory): p50 ~110ms, p95 ~180ms (sustained 30 RPS). - p99 ≤ ~280ms across both paths.
- Last measured: 2026-05-07. Burst-tested at 200 RPS without degradation.
- SLO: p95 < 800ms (broad) / < 1500ms (narrow), error rate < 1%.
See also#
- GET /v1/questions — browse with cursor pagination and
updated_since - Languages & translations — language coverage and
is_translationflag - Migrating from OpenTDB — how to port existing code