Get Question
GET /v1/nextexams/questions/{id}
Get a question
The whole question: options with their stable ids, answer key, tags and
where it is used. The body of this response is a valid PUT body.
Scope questions:read.
Request
GET https://your-site.example/api/index.php/v1/nextexams/questions/{id}
Parameters
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
integer |
path |
Yes | The record's id. (min 1) |
Responses
200 — The question.
{
"data": {
"id": 1,
"subject_id": 1,
"question_type": "string",
"title": "string",
"alias": "string",
"stem": "string",
"explanation": "string",
"difficulty": 1,
"default_points": 1.5,
"answer_key": {},
"shuffle_options": true,
"published": true,
"version": 1,
"approval_status": "string",
"owner_exam_id": 1,
"created": "2026-01-01T12:00:00Z",
"modified": "2026-01-01T12:00:00Z",
"options": [
{
"id": 1,
"ordering": 1,
"option_text": "string",
"is_correct": true,
"match_key": "string",
"feedback": "string"
}
],
"tags": [
{
"id": 1,
"title": "string"
}
],
"usage": {
"exam_count": 1,
"answered": true
}
}
}
| Field | Type | Meaning |
|---|---|---|
data.id |
integer |
|
data.subject_id |
integer |
|
data.question_type |
string |
|
data.title |
string |
|
data.alias |
string |
|
data.stem |
string |
|
data.explanation |
string|null |
|
data.difficulty |
integer |
|
data.default_points |
number |
|
data.answer_key |
object|null |
|
data.shuffle_options |
boolean |
|
data.published |
boolean |
|
data.version |
integer |
|
data.approval_status |
string |
|
data.owner_exam_id |
integer |
|
data.created |
string|null |
ISO 8601 in UTC, or null when not set. (date-time) |
data.modified |
string|null |
ISO 8601 in UTC, or null when not set. (date-time) |
data.options[].id |
integer |
Stable across saves when sent back. |
data.options[].ordering |
integer |
|
data.options[].option_text |
string |
|
data.options[].is_correct |
boolean |
|
data.options[].match_key |
string|null |
The partner of a matching pair, or an image-choice option's picture. |
data.options[].feedback |
string|null |
|
data.tags[].id |
integer |
|
data.tags[].title |
string |
|
data.usage.exam_count |
integer |
Exams that use it. |
data.usage.answered |
boolean |
Whether any attempt has answered it — then answer-affecting changes need a new version. |
Errors
| Status | Code | When |
|---|---|---|
401 |
INVALID_TOKEN |
No token (MISSING_TOKEN), or one that is wrong, expired, revoked, or whose owner can no longer sign in (INVALID_TOKEN). |
403 |
MISSING_SCOPE |
The token is valid but this request is not allowed, and code says why: MISSING_SCOPE (the token lacks the scope), FORBIDDEN (the owner's role does not allow it), ACCESS_DENIED (the owner cannot manage Next Exams), API_DISABLED (the API Tokens app is off), APP_DISABLED (the feature's app is off — meta.app names it), ACCOUNT_UNUSABLE (the owner is blocked or must reset their password), DEMO_LOCKED (a demo site). |
404 |
NOT_FOUND |
No record has this id. |
Examples
curl
curl -s "https://your-site.example/api/index.php/v1/nextexams/questions/1" \
-H "Authorization: Bearer $API_TOKEN"
PHP
<?php
$ch = curl_init('https://your-site.example/api/index.php/v1/nextexams/questions/1');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('API_TOKEN'),
],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
JavaScript
const API_TOKEN = process.env.API_TOKEN;
const response = await fetch("https://your-site.example/api/index.php/v1/nextexams/questions/1", {
headers: {
"Authorization": `Bearer ${API_TOKEN}`,
},
});
const data = await response.json();