---
title: "Get Class Evaluations"
method: GET
path: "/teacher/assignments/{assignment_id}/v2-evaluations"
tags: ["v2_evaluations"]
---

# Get Class Evaluations

`GET /teacher/assignments/{assignment_id}/v2-evaluations`

Class-wide evaluation snapshot. Heavy payload (~1MB for a 30×10
class), so we let the client conditionally short-circuit with
`If-None-Match` against a weak ETag derived from the latest session
`updated_at`. A teacher who keeps the results page open and re-fetches
on a route change gets a 304 with empty body when nothing has moved.

## Path parameters

- `assignment_id` string, required

## Headers

- `if-none-match` string, nullable

## Response `200`

Successful Response

- ClassEvaluationsResponse
  - `assignment_id` string, required
  - `exercises` ExerciseSummary[], required
    - `exercise_id` string, required
    - `statement` string, required
    - `rubric` RubricResponse, required — Minimal: drops `exercise_id` (lives in the URL) and `exercise_collection` / `created_at` (frontend doesn't read them today). `author` is flattened to a Literal to avoid leaking prompt ids / user ids.
      - `id` string, required
      - `questions` RubricQuestion[], required
        - `question_text` string, required
        - `skills` SkillRef[], required
          - `savoir_faire_id` string, required
          - `name` string, required
          - `description` string, required
        - `criteria` string[], required
      - `author_type` 'ai' | 'human', required
  - `rows` EvaluationRow[], required
    - `student_id` string, required
    - `student_display_name` string, required
    - `exercise_id` string, required
    - `latest_evaluation` RubricEvaluationResponse, required
      - `rubric_id` string, required
      - `author_type` 'ai' | 'human', required
      - `author_model` string, nullable
      - `feedback` string, required
      - `questions` RubricQuestionEvaluation[], 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.
              - …
        - `criterion_outcomes` CriterionOutcome[], 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.
              - …
        - `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.
              - …
          - `categories` ErrorCategory[], nullable
      - `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
      - `computed_grade` number, required
      - `max_grade` number, required
      - `evaluated_at` string, date-time, required
    - `submission_attempt_index` integer, nullable, required
  - `student_breakdowns` StudentSessionBreakdownResponse[], required
    - `student_id` string, required
    - `breakdown` SessionGradeBreakdownResponse, required — Canonical per-session grade payload — read by every résultats surface so the displayed note matches across teacher and student views.
      - `total` number, nullable, required
      - `cells` WeightedExerciseCellResponse[], required
        - `grade` number, nullable, required
        - `max_grade` number, required
      - `total_max` number, required
  - `legacy_submissions` LegacySubmissionRefResponse[], required
    - `session_id` string, required
    - `exercise_id` string, required

## Other responses

- `400` — Malformed identifier
- `403` — Not authorized for this resource
- `404` — Resource not found
- `422` — Validation Error

## Changes

- **2026-09-07** `0ccba2913cca` — 1 info
  - added the optional property `rows/items/latest_evaluation/anyOf[subschema #1: RubricEvaluationResponse]/author_model` to the response with the `200` status
- **2026-09-03** `ef67479ed898` — 1 info
  - added the optional property `rows/items/latest_evaluation/anyOf[subschema #1: RubricEvaluationResponse]/questions/items/errors/items/categories` to the response with the `200` status

[Change history](https://skmtc.dev/excellence-ai/apis/excellence-learning/changes/teacher/assignments/:assignment_id/v2-evaluations/get.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/2a0c1636fd3b?raw)
