Contents
On this page
Update Question - Plugixa Exam
PUT /plugixa-exam/v1/questions/{id}
Change some or all of a question’s fields. Fields you leave out keep their stored values.
Scope questions:write; the token’s user needs the questions:edit permission, or questions:edit.own when the question was created by that user.
Request
PUT https://your-site.example/wp-json/plugixa-exam/v1/questions/12
Path parameters
| Name | Type | Description |
|---|---|---|
id |
integer |
The question’s id |
Request body
Content type: application/json
The same fields as Create Question, with the same rules. None is required: send only what changes.
| Field | Type | Required | Description |
|---|---|---|---|
title |
string |
No | Must not be blank when sent. |
question_type |
string |
No | Changes the type only to a registered type. An unregistered value keeps the stored type. |
options |
object[] |
No | When sent, replaces the whole option list: an option carrying the id of an existing option is updated in place, one without an id is added, and existing options you leave out are deleted. |
answer_key |
object |
No | Cleaned per type, as on create. See Answer key by type. |
published |
boolean |
No | Publish or unpublish. |
tag_ids |
integer[] |
No | With the Tags app on: replaces the question’s tags. |
| Any other create field | No | slug, subject_id, stem, explanation, difficulty, default_points, shuffle_options, approval_status, rubric, render_hint, custom_fields PRO. |
The stored question, options included, is overlaid with the fields you send, and the result is checked like a new question. Every successful update raises version by one and saves the new version to the question’s history, even when nothing changed.
Note. Unlike Update Subject, which replaces the whole subject, this endpoint merges: an omitted
publishedkeeps its value. Sendingoptions, though, replaces the list, so include theidof every option you want to keep.
{
"difficulty": 3,
"options": [
{ "id": 41, "option_text": "Paris", "is_correct": true },
{ "id": 42, "option_text": "Lyon", "is_correct": false },
{ "option_text": "Toulouse", "is_correct": false }
]
}
Responses
200 OK. data is the updated question.
{
"success": true,
"data": {
"id": 12,
"subject_id": 4,
"question_type": "mcq_single",
"title": "Capital of France",
"slug": "capital-of-france",
"stem": "<p>What is the capital of France?</p>",
"difficulty": 3,
"default_points": 1,
"answer_key": { "negative_marking": false, "min_score": 0 },
"explanation": "<p>Paris is the capital of France.</p>",
"shuffle_options": true,
"published": true,
"version": 4,
"approval_status": "approved",
"rubric": null,
"custom_fields": null,
"render_hint": null,
"created_at": "2026-11-10 14:05:00",
"modified_at": "2026-11-12 09:30:00",
"created_by": 1,
"modified_by": 1,
"deleted_at": null,
"options": [
{ "id": 41, "question_id": 12, "ordering": 1, "option_text": "Paris", "is_correct": true, "match_key": null, "feedback": null },
{ "id": 42, "question_id": 12, "ordering": 2, "option_text": "Lyon", "is_correct": false, "match_key": null, "feedback": null },
{ "id": 44, "question_id": 12, "ordering": 3, "option_text": "Toulouse", "is_correct": false, "match_key": null, "feedback": null }
],
"tag_ids": [5, 8]
}
}
| Field | Type | Meaning |
|---|---|---|
data.version |
integer |
The new version number, one higher than before |
data.options |
object[] |
The option list after the update |
data.modified_at |
string |
UTC datetime of this update |
data.modified_by |
integer |
WordPress user id of the token’s user |
The other fields are as in Get Question.
Errors
| Status | Code | When |
|---|---|---|
403 |
plugixa_exam_forbidden |
The user only has questions:edit.own and the question is not theirs, or does not exist: in that case you get 403, not 404, by design. |
404 |
plugixa_exam_not_found |
The question does not exist (for a user with full questions:edit). |
400 |
plugixa_exam_title_required, plugixa_exam_needs_options, plugixa_exam_needs_one_correct, plugixa_exam_needs_correct, plugixa_exam_needs_accepted, and the module type checks |
The merged question fails the same checks as Create Question. |
Plus the errors every endpoint can return.
Examples
curl -s -X PUT "https://your-site.example/wp-json/plugixa-exam/v1/questions/12" \
-H "Authorization: Bearer $PLUGIXA_EXAM_TOKEN" \
-H "Content-Type: application/json" \
-d '{"difficulty":3,"published":false}'
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-exam/v1/questions/12');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('PLUGIXA_EXAM_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'difficulty' => 3,
'published' => false,
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.example/wp-json/plugixa-exam/v1/questions/12', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${process.env.PLUGIXA_EXAM_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ difficulty: 3, published: false }),
});
const { data } = await response.json();
Quick Links
Share