---
title: "Override Evaluation"
method: PUT
path: "/teacher/sessions/{session_id}/exercises/{exercise_id}/v2-evaluation"
tags: ["v2_evaluations"]
---

# Override Evaluation

`PUT /teacher/sessions/{session_id}/exercises/{exercise_id}/v2-evaluation`

## Request

- Base URL: `https://api.excellence-ai.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.excellence-ai.com/teacher/sessions/{session_id}/exercises/{exercise_id}/v2-evaluation`
- Auth: OAuth 2 (password, token URL `api/login`)

## Path parameters

- `session_id` string, required
- `exercise_id` string, required

## Request body

- EvaluationOverrideRequest
  - `questions` OverrideQuestion[], required
    - `skill_outcomes` OverrideSkillOutcome[], required
      - `savoir_faire_id` string, required
      - `outcome` 'correct' | 'partial' | 'wrong' | 'unanswered', required
      - `note` string, required
      - `evidence` OverrideEvidence[], required
        - `block_id` string, required
        - `excerpt` string, required
    - `criterion_outcomes` OverrideCriterionOutcome[]
      - `criterion_index` integer, required
      - `outcome` 'correct' | 'partial' | 'wrong' | 'unanswered', required
      - `note` string, required
      - `evidence` OverrideEvidence[], required
        - `block_id` string, required
        - `excerpt` string, required
    - `question_outcome` OverrideQuestionOutcome: Points shape of a teacher override: what the question earned, plus what the student is told. `points_awarded` is the one number a teacher has an opinion about — « 2,5 sur 3 » is what they write on a copy, and it is what the editor sends (EXC-765). The ladder `score` stays on the wire because a client may still send only a rung (and every EXC-759 client does), but when a mark is present it wins: `apply_teacher_awards` clamps it to the question's allocation, quantizes it to the quarter-point, and re-derives the rung from it so the label under the mark agrees with it. The cap here is absolute, for incident control. The real bound is the question's own allocation, which the boundary cannot see — the rubric is resolved a layer down, and that is where the clamp happens.
      - `score` integer, required
      - `unanswered` boolean
      - `note` string, required
      - `evidence` OverrideEvidence[]
        - `block_id` string, required
        - `excerpt` string, required
      - `alternative_method` boolean
      - `points_awarded` number, nullable
    - `errors` OverrideFlaggedError[], required
      - `description` string, required
      - `evidence` OverrideEvidence[], required
        - `block_id` string, required
        - `excerpt` string, required
      - `categories` ErrorCategory[], nullable
  - `feedback` string, nullable, required

## Response `200`

Successful Response

- RubricEvaluationResponse
  - `rubric_id` string, required
  - `author_type` 'ai' | 'human', required
  - `author_model` string, nullable
  - `feedback` string, required
  - `questions` RubricQuestionEvaluationResponse[], required
    - `skill_outcomes` SkillOutcome[], required
      - `savoir_faire_id` string, required
      - `outcome` 'correct' | 'partial' | 'wrong' | 'unanswered', required
      - `note` string, required
      - `evidence` EvidenceSpan[], required
        - `excerpt` string, required
        - `span` TextSpan, required: Resolved char offsets into a `SubmissionAttempt.solution_blocks[i].transcribed_text`. Backend computes start/end at write time.
          - `block_id` string, required
          - `start` integer, required
          - `end` integer, required
    - `criterion_outcomes` CriterionOutcomeResponse[], required
      - `criterion_index` integer, required
      - `outcome` 'correct' | 'partial' | 'wrong' | 'unanswered', required
      - `note` string, required
      - `evidence` EvidenceSpan[], required
        - `excerpt` string, required
        - `span` TextSpan, required: Resolved char offsets into a `SubmissionAttempt.solution_blocks[i].transcribed_text`. Backend computes start/end at write time.
          - `block_id` string, required
          - `start` integer, required
          - `end` integer, required
    - `errors` FlaggedError[], required
      - `description` string, required
      - `evidence` EvidenceSpan[], required
        - `excerpt` string, required
        - `span` TextSpan, required: Resolved char offsets into a `SubmissionAttempt.solution_blocks[i].transcribed_text`. Backend computes start/end at write time.
          - `block_id` string, required
          - `start` integer, required
          - `end` integer, required
      - `categories` ErrorCategory[], nullable
    - `question_outcome` QuestionOutcomeResponse: The grader's verdict on one question of a points rubric. `max_score` travels so a client never hardcodes the ladder's top rung, and `points_awarded` / `points_available` are computed **here**, by the backend, through the one domain rule (`question_award`: the ladder, or a teacher's own mark when one was written). No client recomputes a grade from outcomes: the per-question awards sum to `computed_grade` exactly, which is what lets EXC-764 delete the frontend's duplicate weight table rather than extend it. Both point fields are `None` only when the response was built without the rubric in hand (see `RubricEvaluationResponse.from_domain`).
      - `score` integer, nullable, required
      - `max_score` integer, required
      - `unanswered` boolean, required
      - `note` string, required
      - `evidence` EvidenceSpan[], required
        - `excerpt` string, required
        - `span` TextSpan, required: Resolved char offsets into a `SubmissionAttempt.solution_blocks[i].transcribed_text`. Backend computes start/end at write time.
          - `block_id` string, required
          - `start` integer, required
          - `end` integer, required
      - `alternative_method` boolean, required
      - `points_awarded` number, nullable, required
      - `points_available` number, nullable, required
    - `carried_from_attempt` integer, nullable
    - `verdict` 'correct' | 'to_review'
  - `question_zones` QuestionZone[], required
    - `question_indexes` integer[], required
    - `boxes` PhotoBBox[], required
      - `photo_index` integer, required
      - `x` number, required
      - `y` number, required
      - `width` number, required
      - `height` number, required
  - `carried_photo_urls` string[]
  - `computed_grade` number, nullable, required
  - `max_grade` number, nullable, required
  - `evaluated_at` string, date-time, required

## Other responses

- `400`: Malformed identifier
- `403`: Not authorized for this resource
- `404`: Resource not found
- `409`: Business rule violated
- `422`: Validation Error

## Changes

> 55 revisions in range; 1 not diffed.

- **2026-10-13** `60775565116f`: 3 breaking, 1 info
  - response property `computed_grade` list-of-types was widened by adding types `null` to media type `application/json` of response `200`
  - response property `max_grade` list-of-types was widened by adding types `null` to media type `application/json` of response `200`
  - response property `questions/items/question_outcome/anyOf[subschema #1: QuestionOutcomeResponse]/score` list-of-types was widened by adding types `null` to media type `application/json` of response `200`
  - added the optional property `questions/items/verdict` to the response with the `200` status
- **2026-09-25** `a8ae0e0c0570`: 2 info
  - added the optional property `carried_photo_urls` to the response with the `200` status
  - added the optional property `questions/items/carried_from_attempt` to the response with the `200` status
- **2026-09-22** `05e048df94c6`: 3 info
  - added the new optional request property `questions/items/question_outcome`
  - the request property `questions/items/criterion_outcomes` became optional
  - added the optional property `questions/items/question_outcome` to the response with the `200` status
- **2026-09-07** `0ccba2913cca`: 1 info
  - added the optional property `author_model` to the response with the `200` status
- …earlier changes not shown

[Operation history](https://skmtc.dev/excellence-ai/apis/excellence-learning/changes/teacher/sessions/:session_id/exercises/:exercise_id/v2-evaluation/put.md)

---

[API](https://skmtc.dev/excellence-ai/apis/excellence-learning.md) - [All operations](https://skmtc.dev/excellence-ai/apis/excellence-learning/llms.txt) - [OpenAPI document](https://skmtc.dev/excellence-ai/apis/excellence-learning/revisions/379e4a57dee8?raw)
