# Assessment

Exams, recorded results, and progress reports.

Generated from `apps/api/openapi.json`. HTML version: https://docs.institflow.com/en/reference/assessment

15 operations.

## DELETE /api/v1/exams/{id}

Delete an exam. Only allowed when it has no results yet (409 otherwise).

- Operation id: `ExamsController_remove_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — The exam was deleted.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `ok` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X DELETE "https://your-institute.example/api/v1/exams/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## PATCH /api/v1/exams/{id}

Update an exam.

- Operation id: `ExamsController_update_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `title` | string | no | 1–200 chars |
| `kind` | enum: "quiz" \| "exam" \| "homework" \| "project" \| "final" | no |  |
| `maxScore` | number | no | ≥0 |
| `weight` | number | no | ≥0 · default: 1 |
| `heldAt` | string \| string (date) | no |  |

```json
{
  "title": "Midterm Exam",
  "kind": "quiz",
  "maxScore": 0,
  "weight": 1,
  "heldAt": "string"
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `groupId` | string (uuid) | yes |  |
| `title` | string | yes |  |
| `kind` | enum: "quiz" \| "exam" \| "homework" \| "project" \| "final" | yes |  |
| `maxScore` | number | yes |  |
| `weight` | number | yes |  |
| `heldAt` | string (date) \| null | yes |  |
| `publishedAt` | string (date-time) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X PATCH "https://your-institute.example/api/v1/exams/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "title": "Midterm Exam",
    "kind": "quiz",
    "maxScore": 0,
    "weight": 1,
    "heldAt": "string"
  }'
```

## POST /api/v1/exams/{id}/publish

Publish an exam (once only — 409 on re-publish). Emits `exam.published`.

- Operation id: `ExamsController_publish_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `groupId` | string (uuid) | yes |  |
| `title` | string | yes |  |
| `kind` | enum: "quiz" \| "exam" \| "homework" \| "project" \| "final" | yes |  |
| `maxScore` | number | yes |  |
| `weight` | number | yes |  |
| `heldAt` | string (date) \| null | yes |  |
| `publishedAt` | string (date-time) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/exams/37386ae0-3738-7738-8386-37386ae03738/publish" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## PUT /api/v1/exams/{id}/results

Bulk upsert an exam's results roster.

- Operation id: `ExamsController_upsertResults_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `results` | array<object> | yes |  |

```json
{
  "results": [
    {
      "studentId": "a4a70332-a4a7-74a7-8a70-a4a70332a4a7",
      "score": 0,
      "isAbsent": false,
      "remarks": "string"
    }
  ]
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X PUT "https://your-institute.example/api/v1/exams/37386ae0-3738-7738-8386-37386ae03738/results" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "results": [
      {
        "studentId": "a4a70332-a4a7-74a7-8a70-a4a70332a4a7",
        "score": 0,
        "isAbsent": false,
        "remarks": "string"
      }
    ]
  }'
```

## GET /api/v1/groups/{groupId}/exams

List a group's exams.

- Operation id: `GroupExamsController_list_v1`
- Permission: `assessment.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `groupId` | path | string | yes |  |
| `cursor` | query | string | no |  |
| `limit` | query | integer | no | 1–100 · default: 25 |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/groups/6dc7fce6-6dc7-7dc7-8c7f-6dc7fce66dc7/exams" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/groups/{groupId}/exams

Create an exam for this group.

- Operation id: `GroupExamsController_create_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `groupId` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `title` | string | yes | 1–200 chars |
| `kind` | enum: "quiz" \| "exam" \| "homework" \| "project" \| "final" | yes |  |
| `maxScore` | number | yes | ≥0 |
| `weight` | number | no | ≥0 · default: 1 |
| `heldAt` | string \| string (date) | no |  |

```json
{
  "title": "Midterm Exam",
  "kind": "quiz",
  "maxScore": 0,
  "weight": 1,
  "heldAt": "string"
}
```

### Responses

**201** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `groupId` | string (uuid) | yes |  |
| `title` | string | yes |  |
| `kind` | enum: "quiz" \| "exam" \| "homework" \| "project" \| "final" | yes |  |
| `maxScore` | number | yes |  |
| `weight` | number | yes |  |
| `heldAt` | string (date) \| null | yes |  |
| `publishedAt` | string (date-time) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/groups/6dc7fce6-6dc7-7dc7-8c7f-6dc7fce66dc7/exams" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "title": "Midterm Exam",
    "kind": "quiz",
    "maxScore": 0,
    "weight": 1,
    "heldAt": "string"
  }'
```

## GET /api/v1/me/grades

Own grades (student), or a linked child’s grades via `?studentId` (guardian). Published exams only.

- Operation id: `MeGradesController_getMine_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `studentId` | query | string (uuid) | no |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `studentId` | string (uuid) | yes |  |
| `groups` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/me/grades" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/me/progress-reports

My own (or my children’s) published progress reports, newest first. Drafts are never returned.

- Operation id: `MeProgressReportsController_list_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `cursor` | query | string | no |  |
| `limit` | query | integer | no | 1–100 · default: 25 |
| `studentId` | query | string (uuid) | no |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/me/progress-reports" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/progress-reports

List progress reports, filterable by studentId, groupId, and/or status.

- Operation id: `ProgressReportsController_list_v1`
- Permission: `assessment.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `cursor` | query | string | no |  |
| `limit` | query | integer | no | 1–100 · default: 25 |
| `studentId` | query | string (uuid) | no |  |
| `groupId` | query | string (uuid) | no |  |
| `status` | query | enum: "draft" \| "published" \| "sent" | no |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/progress-reports" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/progress-reports/{id}

Get one progress report.

- Operation id: `ProgressReportsController_get_v1`
- Permission: `assessment.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `studentId` | string (uuid) | yes |  |
| `groupId` | string (uuid) \| null | yes |  |
| `periodStart` | string (date) | yes |  |
| `periodEnd` | string (date) | yes |  |
| `summary` | object | yes |  |
| `teacherComment` | string \| null | yes | 0–2000 chars |
| `status` | enum: "draft" \| "published" \| "sent" | yes |  |
| `generatedAt` | string (date-time) | yes |  |
| `sentAt` | string (date-time) \| null | yes |  |
| `fileId` | string (uuid) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/progress-reports/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## PATCH /api/v1/progress-reports/{id}

Set a progress report's teacher comment.

- Operation id: `ProgressReportsController_patch_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `teacherComment` | string | yes | 1–2000 chars |

```json
{
  "teacherComment": "string"
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `studentId` | string (uuid) | yes |  |
| `groupId` | string (uuid) \| null | yes |  |
| `periodStart` | string (date) | yes |  |
| `periodEnd` | string (date) | yes |  |
| `summary` | object | yes |  |
| `teacherComment` | string \| null | yes | 0–2000 chars |
| `status` | enum: "draft" \| "published" \| "sent" | yes |  |
| `generatedAt` | string (date-time) | yes |  |
| `sentAt` | string (date-time) \| null | yes |  |
| `fileId` | string (uuid) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X PATCH "https://your-institute.example/api/v1/progress-reports/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "teacherComment": "string"
  }'
```

## POST /api/v1/progress-reports/{id}/publish

Publish a draft progress report (409 if not currently draft).

- Operation id: `ProgressReportsController_publish_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `studentId` | string (uuid) | yes |  |
| `groupId` | string (uuid) \| null | yes |  |
| `periodStart` | string (date) | yes |  |
| `periodEnd` | string (date) | yes |  |
| `summary` | object | yes |  |
| `teacherComment` | string \| null | yes | 0–2000 chars |
| `status` | enum: "draft" \| "published" \| "sent" | yes |  |
| `generatedAt` | string (date-time) | yes |  |
| `sentAt` | string (date-time) \| null | yes |  |
| `fileId` | string (uuid) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/progress-reports/37386ae0-3738-7738-8386-37386ae03738/publish" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/progress-reports/{id}/send

Send a published progress report to its guardians (409 unless currently published). Emits `progress_report.sent`.

- Operation id: `ProgressReportsController_send_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `studentId` | string (uuid) | yes |  |
| `groupId` | string (uuid) \| null | yes |  |
| `periodStart` | string (date) | yes |  |
| `periodEnd` | string (date) | yes |  |
| `summary` | object | yes |  |
| `teacherComment` | string \| null | yes | 0–2000 chars |
| `status` | enum: "draft" \| "published" \| "sent" | yes |  |
| `generatedAt` | string (date-time) | yes |  |
| `sentAt` | string (date-time) \| null | yes |  |
| `fileId` | string (uuid) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/progress-reports/37386ae0-3738-7738-8386-37386ae03738/send" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/progress-reports/generate

Enqueue progress-report generation for a group (one draft per enrolled student) or a single student.

- Operation id: `ProgressReportsController_generate_v1`
- Permission: `assessment.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `groupId` | string (uuid) | no |  |
| `studentId` | string (uuid) | no |  |
| `periodStart` | string (date) | yes |  |
| `periodEnd` | string (date) | yes |  |

```json
{
  "groupId": "6dc7fce6-6dc7-7dc7-8c7f-6dc7fce66dc7",
  "studentId": "a4a70332-a4a7-74a7-8a70-a4a70332a4a7",
  "periodStart": "2026-03-02",
  "periodEnd": "2026-03-02"
}
```

### Responses

**202** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `queued` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/progress-reports/generate" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "groupId": "6dc7fce6-6dc7-7dc7-8c7f-6dc7fce66dc7",
    "studentId": "a4a70332-a4a7-74a7-8a70-a4a70332a4a7",
    "periodStart": "2026-03-02",
    "periodEnd": "2026-03-02"
  }'
```

## GET /api/v1/students/{id}/grades

Per-exam scores and per-group weighted average (scaled via `grading.scale`) for one student.

- Operation id: `StudentGradesController_get_v1`
- Permission: `assessment.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |
| `groupId` | query | string (uuid) | no |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `studentId` | string (uuid) | yes |  |
| `groups` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/students/37386ae0-3738-7738-8386-37386ae03738/grades" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```
