PHP2Shell: Is Your Joomla Site Safe? What to Do Today Introducing Next Boards: Kanban project and task boards for Joomla Next Exams 6.2.0: Exam Studio, six visual question types, exam embeds and six new languages Building the Future of Joomla Extensions
NextSoftware

Replace Question

PUT /v1/nextexams/questions/{id}

Replace a question

A question is saved whole: options, answer key and tags you leave out are removed. Read it, change what you need, send it back. A body with no options key is refused with 422 OPTIONS_REQUIRED while the question has options — send [] to remove them deliberately.

Option ids survive a save: send each option's id back and answers already given to it keep grading. A change that would alter how existing answers are graded is refused with 409 ANSWERED_NEEDS_VERSION unless the body carries new_version. Send expected_version to be refused with 409 STALE if someone saved in between.

Scope questions:write; the role needs questions.edit.

Request

PUT 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)

Request body

Content type: application/json

Field Type Required Description
title string No
question_type string No
stem string No
explanation string No
subject_id integer No
difficulty integer No (min 1, max 5)
default_points number No
shuffle_options boolean|integer No
published boolean|integer No
options object[] No
options.id integer No Send it back to keep the option (and the answers given to it).
options.option_text string No
options.is_correct boolean|integer No
options.match_key string|null No
options.feedback string|null No
answer_key object No
tags array No Tag ids, tag titles, or {id, title} objects; a new title creates the tag.
owner_exam_id integer No Create the question private to this exam. Needs exams:write too.
expected_version integer No Refuse with 409 STALE if the stored version differs.
new_version object No Save as a new version, swapped into the listed exams.
new_version.exam_ids integer[] No
{
    "title": "string",
    "question_type": "string",
    "stem": "string",
    "explanation": "string",
    "subject_id": 1,
    "difficulty": 1,
    "default_points": 1.5,
    "shuffle_options": true,
    "published": true,
    "options": [
        {
            "id": 1,
            "option_text": "string",
            "is_correct": true,
            "match_key": "string",
            "feedback": "string"
        }
    ],
    "answer_key": {},
    "tags": [
        "string"
    ],
    "owner_exam_id": 1,
    "expected_version": 1,
    "new_version": {
        "exam_ids": [
            1
        ]
    }
}

Responses

200 — Saved.

{
    "data": {
        "id": 1
    }
}
Field Type Meaning
data.id integer

Errors

Status Code When
400 BAD_REQUEST The body failed validation, or is not a JSON object (INVALID_JSON).
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.
409 The save or delete would break something that depends on the record: QUESTION_IN_USE, ANSWERED_NEEDS_VERSION, TYPE_LOCKED, STALE. meta carries the details (for example the exams that use a question).
422 The request is well formed but would lose data (OPTIONS_REQUIRED).

Examples

curl

curl -s -X PUT "https://your-site.example/api/index.php/v1/nextexams/questions/1" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"string","question_type":"string","stem":"string","explanation":"string","subject_id":1,"difficulty":1,"default_points":1.5,"shuffle_options":true,"published":true,"options":[{"id":1,"option_text":"string","is_correct":true,"match_key":"string","feedback":"string"}],"answer_key":{},"tags":["string"],"owner_exam_id":1,"expected_version":1,"new_version":{"exam_ids":[1]}}'

PHP

<?php
$ch = curl_init('https://your-site.example/api/index.php/v1/nextexams/questions/1');

curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => '{"title":"string","question_type":"string","stem":"string","explanation":"string","subject_id":1,"difficulty":1,"default_points":1.5,"shuffle_options":true,"published":true,"options":[{"id":1,"option_text":"string","is_correct":true,"match_key":"string","feedback":"string"}],"answer_key":{},"tags":["string"],"owner_exam_id":1,"expected_version":1,"new_version":{"exam_ids":[1]}}',
]);

$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", {
  method: 'PUT',
  headers: {
    "Authorization": `Bearer ${API_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "title": "string",
    "question_type": "string",
    "stem": "string",
    "explanation": "string",
    "subject_id": 1,
    "difficulty": 1,
    "default_points": 1.5,
    "shuffle_options": true,
    "published": true,
    "options": [
      {
        "id": 1,
        "option_text": "string",
        "is_correct": true,
        "match_key": "string",
        "feedback": "string"
      }
    ],
    "answer_key": {},
    "tags": [
      "string"
    ],
    "owner_exam_id": 1,
    "expected_version": 1,
    "new_version": {
      "exam_ids": [
        1
      ]
    }
  }),
});
const data = await response.json();

All Extensions