---
title: "Api Learning Mastery Summary"
method: GET
path: "/api/learning/mastery/summary"
tags: ["Education"]
---

# Api Learning Mastery Summary

`GET /api/learning/mastery/summary`

## Request

- Base URL: `https://www.oxfordledge.com` (the document declares no server; this is the origin it was published from)
- URL: `https://www.oxfordledge.com/api/learning/mastery/summary`
- Auth: none declared

LEARN Mastery Definition plan §5 — per-layer rollup for the
Dashboard panel + /learn/mastery-map page.

Self-only (OWNER #4 ratified 2026-04-17). Reads `user_concept_mastery`
(v46, live) joined with `learn_concepts` (v46), runs each row
through learn.mastery.layer.compute_layer, and aggregates
by layer + by domain.

Schema state (updated 2026-07-19, S50 flip): the dormant v51/v52
migrations landed as v136 (mastery-layer fields on
user_concept_mastery) + v137 (user_mastery_transitions), APPLIED
2026-06-29 (LR-B4 Phase 0+2). first_mastered_at +
calibration_passes flow through layer_state_from_row below, and
the Phase-9b calibration serve/submit path now records passes —
so Mastered/Enduring counts are live here with no further code
changes. Legacy rows (calibration_passes=0) still cap at
Proficient, which matches their reality.

Response shape (stable across pre/post v136):
  {
    "by_layer": {"attempted": N, "familiar": N, "proficient": N,
                 "mastered": N, "enduring": N},
    "decaying_count": N,           # subset of proficient/mastered/enduring
    "by_domain": [
      {"domain": str, "title": str,
       "by_layer": {...}, "total": N, "attempted_count": N},
      ...
    ],
    "total_attempted": N,           # concepts the user has touched
    "total_concepts": N,            # full taxonomy size
    "version": 1
  }

## Response `200`

Successful Response

- MasterySummaryResponse: `GET /api/learning/mastery/summary` — per-layer rollup for the dashboard panel + /learn/mastery-map page. Pre-v51 only attempted/familiar/proficient counts populate; mastered/enduring stay 0 until v51/v52 land + post-window activation wires first_mastered_at + calibration_passes.
  - `by_layer` object, required: {layer_slug -> count} across every layer in services.learn_mastery_layer.LAYERS.
  - `decaying_count` integer, required: Subset of proficient+mastered+enduring with stale last_practice_at.
  - `by_domain` MasteryDomainBreakdown[], required: Per-domain rollups sorted by attempted_count DESC.
    - `domain` string, required: Domain slug.
    - `title` string, required: Display title.
    - `by_layer` object, required: {layer_slug -> count} for this domain's concepts.
    - `total` integer, required: Concepts in this domain the user has touched.
    - `attempted_count` integer, required: Attempted concepts (== total today; reserved for future divergence).
  - `concepts` MasteryConceptRow[], required: Per-concept rows feeding the dormant module-level mastery markers.
    - `slug` string, nullable: Concept slug.
    - `title` string, nullable: Concept display title.
    - `domain` string, required: Domain slug.
    - `layer` string, required: Computed layer: attempted | familiar | proficient | mastered | enduring.
    - `is_decaying` boolean, required: True when last_practice_at is older than the layer's decay window.
    - `score` number, nullable: EMA score (1dp); null when no score recorded yet.
    - `attempts` integer, required: Total attempts logged for this concept.
  - `total_attempted` integer, required: sum(by_layer.values()) — concepts the user has touched.
  - `total_concepts` integer, required: Full taxonomy size (denominator for coverage).
  - `version` integer, required: Schema version; bumped when a non-additive change ships.

---

[API](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api.md) · [All operations](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/llms.txt) · [OpenAPI document](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/revisions/e832a1260f0b?raw)
