---
title: "Get Perspective Sleep Report"
method: GET
path: "/api/mind/v2/perspective/{identity_id}/sleep-report"
tags: ["mind-v2"]
---

# Get Perspective Sleep Report

`GET /api/mind/v2/perspective/{identity_id}/sleep-report`

## Request

- Base URL: `https://app.thinqos.com` (the document declares no server; this is the origin it was published from)
- URL: `https://app.thinqos.com/api/mind/v2/perspective/{identity_id}/sleep-report`
- Auth: none declared

TOS-2532 Phase 2: the smartwatch-style sleep report - one session's
full stage timeline plus the trailing session series the report UI's
trend strip plots. TOS-2265: same CHAT-ENTITLED access check as
`/sleep-status` (`check_chat_entitled_access`) - the widening this
docstring originally anticipated landing automatically via
`_check_perspective_access` instead landed as its own dedicated check
(see that function's docstring for why), so this call site was updated
to match explicitly rather than silently staying owner-only.

TOS-2777: optional ``?session_id=`` selects a PRIOR night's timeline so
the report UI can page backward through history. Omitted (the default)
is the unchanged Phase 2 behavior - the most recent session. The id is
always re-scoped to this Mind, so it can only ever address a night this
caller was already entitled to read.

TOS-2777 Gate C: the report's ``learning_narrative`` field carries real
proposition/retrospect content, not status - narrower than this route's
own chat-entitled gate, so it is independently withheld from a
non-owner caller (see ``_learning_narrative_for_session``).

## Path parameters

- `identity_id` string, uuid, required

## Query parameters

- `session_id` string, uuid, nullable

## Headers

- `x-impersonate-identity-id` string, nullable

## Response `200`

Successful Response

- V2SleepReport: TOS-2532 Phase 2: GET .../perspective/{identity_id}/sleep-report. ``last_session`` is ``None`` iff this Mind has never had a ``mind_sleep_sessions`` row - the "hasn't slept yet" honest empty state. ``recent_sessions`` is the trailing series (most-recent-first, capped at :data:`~thinqos.api.cognitive_v2.SLEEP_REPORT_SESSION_LIMIT`) the trend strip renders; slicing its first 7 entries is the 7-session sparkline, the full list is the 30-session one - one bounded query instead of two.
  - `last_session` V2SleepReportSession, required: TOS-2532 Phase 2: the most recent ``mind_sleep_sessions`` row, with its full per-stage timeline attached - the "last night" report card's data.
    - `session_id` string, uuid, required
    - `started_at` string, date-time, required
    - `ended_at` string, date-time, nullable, required
    - `outcome` 'completed' | 'abandoned', nullable, required
    - `lifecycle_state` 'running' | 'paused' | 'waiting_to_resume' | 'stopped' | 'completed' | 'completed_with_errors' | 'abandoned', required
    - `worker_active` boolean, required
    - `stage_error_count` integer, required
    - `incomplete_stage_count` integer, required
    - `active_duration_ms` integer, nullable, required
    - `interruption_count` integer, required
    - `quality` number, nullable, required
    - `pressure_at_start` number, nullable, required
    - `pressure_at_end` number, nullable, required
    - `sleep_period_key` string, date, nullable, required
    - `period_timezone` string, nullable, required
    - `trigger_reason` 'scheduled' | 'work_pressure' | 'administrative', nullable, required
    - `resume_count` integer, required
    - `last_resumed_at` string, date-time, nullable, required
    - `last_interrupted_at` string, date-time, nullable, required
    - `last_interruption_reason` string, nullable, required
    - `is_legacy` boolean, required
    - `legacy_reason` string, nullable, required
    - `work_measured` boolean, required
    - `learning_narrative` V2LearningNarrative, required: TOS-2777: the report's PRIMARY output, per the ticket - "the report must not reduce sleep to counts... the primary output is a truthful, plain-language What your Mind learned narrative." ``supported=False`` means no safe summary could be built (a legacy session, an open session, or a completed session whose event log had nothing narratable). Clients must render an explanation drawn from ``unsupported_reason`` in that case, never an empty section or a count-based substitute.
      - `supported` boolean, required
      - `takeaways` V2LearningTakeaway[], required
        - `text` string, required
        - `category` 'strengthened' | 'proposed' | 'rejected' | 'unresolved', required
        - `source_event_seq` string, required
        - `source_sleep_stage` string, nullable, required
        - `source_event_kind` string, required
        - `item_id` string, uuid, nullable
      - `unsupported_reason` 'legacy' | 'in_progress' | 'resumed' | 'no_narratable_activity', nullable
    - `recall_calibration` V2RecallCalibration, required: TOS-2777: post-wake calibration's ONE implemented outcome - retrievability. See ``services.cognitive_v2.sleep_calibration`` for the honest account of why this is the only calibration outcome measured so far (the others need infrastructure this codebase does not have yet). ``checked=0`` means genuinely not-yet-measurable (no prior session, or the prior session published nothing) - render "Awaiting waking evidence", never a fabricated 100%.
      - `checked` integer, required
      - `still_retrievable` integer, required
    - `stages` V2SleepReportStageRun[], required
      - `stage` 'settle' | 'replay_select' | 'decay' | 'consolidate' | 'prior_seed' | 'dormancy' | 'feedback' | 'retrospect' | 'rem_integrate' | 'waking_validate', required
      - `started_at` string, date-time, required
      - `ended_at` string, date-time, nullable, required
      - `outcome` 'running' | 'ok' | 'error' | 'skipped_unfunded' | 'deferred' | 'interrupted', required
      - `work` object, required
  - `recent_sessions` V2SleepReportTrendPoint[], required
    - `session_id` string, uuid, required
    - `started_at` string, date-time, required
    - `ended_at` string, date-time, nullable, required
    - `outcome` 'completed' | 'abandoned', nullable, required
    - `lifecycle_state` 'running' | 'paused' | 'waiting_to_resume' | 'stopped' | 'completed' | 'completed_with_errors' | 'abandoned', required
    - `worker_active` boolean, required
    - `stage_error_count` integer, required
    - `incomplete_stage_count` integer, required
    - `active_duration_ms` integer, nullable, required
    - `quality` number, nullable, required
    - `interruption_count` integer, required
    - `sleep_period_key` string, date, nullable, required
    - `period_timezone` string, nullable, required
    - `trigger_reason` 'scheduled' | 'work_pressure' | 'administrative', nullable, required
    - `resume_count` integer, required
    - `is_legacy` boolean, required
  - `state_contract` V2SleepStateContract, required: The versioned five-state contract shared by API, UI, docs and telemetry. ``version`` changes when a state's identity, order or mechanism membership changes - not on rewording. A client holding its own copy should compare versions and defer to the server's text on a mismatch rather than silently rendering stale definitions.
    - `version` integer, required
    - `states` V2SleepStateDefinition[], required
      - `key` 'settling' | 'light' | 'deep' | 'rem' | 'waking', required
      - `order` integer, required
      - `label` string, required
      - `function` string, required
      - `mechanisms` string[], required
      - `human_parallel` string, required
      - `analogy_boundary` string, required
      - `required_measurements` string[], required
      - `implemented` boolean, required
  - `capability_recommendations` V2CapabilityRecommendation[]
    - `kind` 'integration_add' | 'skill_add' | 'permission_review', required
    - `gap_class` 'missing_tool' | 'unconnected_account' | 'denied_permission' | 'transient_failure' | 'insufficient_context', required
    - `target` string, required
    - `requested_outcome` string, required
    - `verified_reason` 'credential_not_working' | 'registration_not_authorized' | 'tool_not_offered' | 'mcp_discovery_timed_out' | 'no_upstream_server_responded', required
    - `occurrence_count` integer, required
    - `first_seen_at` string, date-time, required
    - `last_seen_at` string, date-time, required
    - `evidence_chat_id` string, uuid, nullable, required

## Other responses

- `422`: Validation Error

---

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