Contents
On this page
Update Exam - Plugixa Exam
PUT /plugixa-exam/v1/exams/{id}
Change an exam. Send only the fields you want to change: the rest keep their stored values.
Scope exams:write; the token’s user needs the exams:edit permission.
Note. A user who may only edit their own exams cannot edit exams with a token at all: that permission is not reachable by any scope, so the request answers
403even for an exam the user created. Changingpublished, to publish or to unpublish, also needs theexams:publishscope and the user’sexams:publishpermission (since 1.4.1). Sending the value the exam already has needs nothing extra, so a full form save still works.
Request
PUT https://your-site.example/wp-json/plugixa-exam/v1/exams/7
Path parameters
| Name | Type | Description |
|---|---|---|
id |
integer |
The exam’s id |
Request body
Content type: application/json
The same fields as Create Exam, all optional.
What you send is laid over the stored exam, and the result is checked as a whole, as on create:
- A field you leave out keeps its stored value. To clear a date such as
open_until, send it asnullor"". sectionsreplaces the whole paper, but only when the field is in the body. Leave it out to keep the sections and their questions as they are. Every save ofsectionsgives the sections, question placements and rules new ids.settings, when sent, replaces every stored flag with the ones you send. Leave it out to keep them.access_codechanges only when the field is in the body. An empty value clears the code, except on an exam whoseaccess_typeiscode.titlemay be left out, but not sent blank.- The opening window is checked after merging, so an
open_untilearlier than the storedopen_fromis refused.
{
"pass_mark": 65,
"published": true
}
Responses
200 OK. data is the updated exam, with its sections.
{
"success": true,
"data": {
"id": 7,
"title": "Algebra Midterm",
"slug": "algebra-midterm",
"description": "Linear equations and inequalities.",
"intro": "<p>You have 45 minutes. Calculators are allowed.</p>",
"subject_id": 12,
"time_limit": 45,
"max_attempts": 2,
"cooldown_minutes": 60,
"open_from": "2026-11-16 08:00:00",
"open_until": "2026-11-20 18:00:00",
"pass_mark": 65,
"shuffle_questions": true,
"shuffle_options": false,
"access_type": "code",
"access_level": null,
"result_release": "after_close",
"release_at": null,
"show_answers": true,
"pass_message": "<p>Well done, you passed.</p>",
"fail_message": "",
"lock_policy": "auto",
"attempt_mode": "exam",
"practice_reveal": "on_submit",
"layout": "one_per_page",
"review_before_submit": true,
"allow_early_finish": true,
"fullscreen_mode": "off",
"require_answer": "off",
"allow_pause": false,
"max_pauses": 0,
"max_pause_minutes": 0,
"auto_close_action": "submit",
"idle_timeout_minutes": 1440,
"window_close_action": "close",
"auto_close_held": false,
"auto_close_time_spent": "capped",
"auto_close_notify": "auto",
"track_integrity": true,
"certificate_template_id": 0,
"settings": null,
"custom_fields": null,
"published": true,
"created_at": "2026-11-12 09:30:00",
"modified_at": "2026-11-12 10:15:00",
"created_by": 1,
"modified_by": 1,
"deleted_at": null,
"sections": [
{
"id": 21,
"exam_id": 7,
"title": "Part A",
"description": "",
"ordering": 1,
"section_type": "fixed",
"points_per_question": null,
"questions": [
{ "id": 101, "exam_id": "7", "section_id": 21, "question_id": 41, "ordering": 1, "points": null },
{ "id": 102, "exam_id": "7", "section_id": 21, "question_id": 42, "ordering": 2, "points": 2 }
],
"rules": []
},
{
"id": 22,
"exam_id": 7,
"title": "Part B",
"description": "",
"ordering": 2,
"section_type": "pool",
"points_per_question": 1,
"questions": [],
"rules": [
{
"id": 9,
"section_id": 22,
"subject_id": 15,
"difficulty": null,
"question_type": "mcq_single",
"draw_count": 5,
"points_per_question": null,
"tag_ids": []
}
]
}
],
"has_access_code": true
}
}
| Field | Type | Meaning |
|---|---|---|
data.pass_mark |
number |
The new pass mark |
data.published |
boolean |
Whether the exam is now published |
data.modified_at |
string |
UTC datetime of this change |
data.modified_by |
integer |
The token’s user |
data.sections |
object[] |
Unchanged here, because sections was not sent |
data.has_access_code |
boolean |
Whether an access code is set. The code itself is never returned |
The full set of fields is described on Get Exam.
Errors
| Status | Code | When |
|---|---|---|
403 |
plugixa_exam_forbidden |
The token’s user may only edit their own exams, or the request changes published without exams:publish. |
404 |
plugixa_exam_not_found |
No exam has this id, or the exam is in the trash. |
400 |
plugixa_exam_title_required |
title was sent blank. |
400 |
plugixa_exam_bad_window |
open_until is not after open_from, after merging with the stored values. |
400 |
plugixa_exam_lms_link_invalid |
PRO settings link to an LMS provider, course or step that is unknown, inactive or invalid. |
Plus the errors every endpoint can return.
Examples
curl -s -X PUT "https://your-site.example/wp-json/plugixa-exam/v1/exams/7" \
-H "Authorization: Bearer $PLUGIXA_EXAM_TOKEN" \
-H "Content-Type: application/json" \
-d '{"pass_mark":65,"published":true}'
<?php
$ch = curl_init('https://your-site.example/wp-json/plugixa-exam/v1/exams/7');
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([
'pass_mark' => 65,
'published' => true,
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.example/wp-json/plugixa-exam/v1/exams/7', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${process.env.PLUGIXA_EXAM_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ pass_mark: 65, published: true }),
});
const { data } = await response.json();
Quick Links
Share