Skip to main content
Questions live on an interview as an ordered list, and you edit them by reading that list, changing the array, and sending the whole thing back. Both speak the same question format that POST /job-interview-create-from-array accepts, so a definition read from one endpoint can be edited and written back to the other, or used to seed a copy of the interview.
questions is optional on job-interview-update. Omit it and the question list is left completely alone — the endpoint only touches questions when you send the array. Everything else on the endpoint (name, scoring, tags…) works exactly as before.

The loop

1

Read the interview

The response’s questions array is ordered exactly as candidates are asked:
Each id is the question’s real identifier. Keep the ids of questions you did not mean to change — that is how the update recognises them.
2

Edit the array

Work on the array you just read:
  • Change a question — edit its text (or any field) and keep its id.
  • Remove one — delete the entry.
  • Add one — append an entry with no id.
  • Reorder — move entries around.
3

Send the whole list back

Send the complete list you want the interview to end up with — there is no way to change a single question on its own. An empty array is rejected: an interview needs at least one question.
4

Check what it decided

The response tells you exactly what happened, so you never have to guess. questions_diff is present only when you sent questions — it is absent from the response otherwise:

How your array is matched

The array is applied as a diff, not a replace. Each entry is matched against what is stored, trying in order:
  1. external_id — your own stable identifier, when both sides carry one. This lets an ATS send its own array without ever storing our ids.
  2. id — the question id job-interview-get returned.
  3. Identical content — so an array regenerated without ids still recognises the questions that did not actually change.
Then, per entry:
Resending the array you just read changes nothing. If the diff finds nothing to do, no write happens at all — updated_fields comes back without questions, and the interview’s updated_at is not even bumped. That makes the read → edit → write loop safe to run repeatedly, and safe for an agent to run when it is not sure whether anything changed.

Why editing replaces a question

Questions are shared records: the same question can be used by more than one interview. So this endpoint never edits one in place — that would silently rewrite the question inside every other interview using it. Instead it unlinks the old record and creates a new one, exactly like Duplicate & Edit in the admin. Two consequences worth knowing:
  • Nothing is ever deleted. Removing a question only unlinks it from this interview; the record itself survives, and so do the results that reference it.
  • Keeping a question keeps everything attached to it — its answer rules, its rendered avatar video, and the fields this API does not expose (coach keywords, categories, and so on). That is the real reason to send back the ids: a question you keep costs nothing and loses nothing, while a replaced one starts fresh.
Fields you leave out of an edited entry are carried over from the question you are replacing — so { "id": "3f2a…", "question": "New wording" } keeps the old duration, label and external_id rather than clearing them.

Editing a live interview

On the interactive templates there is no video to render, so the interview is re-published for you and the new questions go live immediately (questions_diff.reactivated is true). The offline templates pre-render a video per question, so a live one has to go back to draft before its questions can change:
Changing the questions of an interview candidates have already completed does not rewrite their results — those still refer to the questions that were asked at the time. If you need a clean comparison across candidates, create a new interview instead of editing a live one.

What this does not change

  • The welcome and thank-you messages, and the instructional-video screen. They are stored as steps rather than questions, are not part of the questions array, and are left in place. Set them at creation with welcome_message and thank_you_message.
  • The language. mojito_language_code is fixed after creation — the existing questions and any rendered videos are already in it. Create a new interview to change language. (An individual question may still override it.)
  • Multi-stage positions. A position has no question list of its own; fetch and update its interview stages individually.

Re-deriving the scoring rubric

The interview-level candidate_expectations_json rubric is derived from the questions, so a big change to the list can leave it out of date. Pass regenerate_candidate_expectations: true alongside questions to re-derive it from the resulting list, the way creation does:
It applies only to type: "interview", and sending your own candidate_expectations_json in the same call wins over the regeneration.

Next steps

Create an interview

Start from a job description, your own questions, or a role-play persona.

Invite candidates

Turn your interview into links or email invitations.