> ## Documentation Index
> Fetch the complete documentation index at: https://help.gowindmill.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Export cycle packets

> Export every performance-review packet for a cycle in a single call, so you can ingest review data into your own systems.

Returns the full set of [performance-review packets](/features/performance-reviews) for one cycle: the manager reviews, self review, peer feedback, and upward feedback collected about each reviewee, in a single structured JSON response. Use it to load review data into an HRIS, data warehouse, or analytics tool.

```
POST /api/v2/c/{companySlug}/cycles/{cycleId}/packets/export
```

The endpoint works on any cycle that isn't archived, including both in-progress (`ACTIVE`) and `COMPLETED` cycles. Exporting a non-terminal cycle is supported by design and returns a point-in-time snapshot of the cycle as it stands at the moment of the call. `ARCHIVED` cycles cannot be exported. A single call returns everything for the cycle, with no pagination.

## Authorization

This endpoint enforces two rules beyond a valid [API key](/api-reference/overview#authentication):

<Warning>
  **Cycle admin only.** The member who created the API key must be an admin of the cycle being exported. A valid key without cycle-admin access on that cycle returns `403 Forbidden`. Cycle admin is granted per cycle. It is not company-wide role.
</Warning>

<Warning>
  **In-progress or completed cycles.** The export works on any cycle that isn't archived, including both `ACTIVE` and `COMPLETED` status. Exporting a non-terminal cycle is supported by design as it returns a point-in-time snapshot of the cycle as it stands at that moment. **Archived cycles cannot be exported**, and return `400 Bad Request`.
</Warning>

The export returns the same content the cycle admin already sees in the Dashboard. The platform's [visibility rules](/features/performance-reviews/visibility) still apply, including self-redaction on the admin's own packet, and the response never includes draft (unsubmitted) answer content.

## Path parameters

<ParamField path="companySlug" type="string" required>
  Your company's slug. Find it in your Dashboard URL, right after `/s/`:

  `https://app.gowindmill.com/s/{companySlug}/home`
</ParamField>

<ParamField path="cycleId" type="string" required>
  The id of the cycle to export. Open the cycle in the Dashboard and take the last segment of the URL:

  `https://app.gowindmill.com/s/{companySlug}/performance/cycles/{cycleId}`
</ParamField>

## Body parameters

The body is optional. Send an empty body `{}` to export every reviewee with all of their reviews.

<ParamField body="filter" type="object">
  Limit the export to matching reviewees. Manager and reporting-line filters use the org chart as it was when the cycle started, not the live org chart. The filter only applies within the cycle, so it can't include people who aren't part of it. Omit it to export every reviewee.

  <Expandable title="filter properties">
    <ParamField body="filter.employeeIds" type="string[]">Include only these employees.</ParamField>
    <ParamField body="filter.excludedEmployeeIds" type="string[]">Exclude these employees.</ParamField>
    <ParamField body="filter.employeeGroupIds" type="string[]">Include only employees in any of these groups.</ParamField>
    <ParamField body="filter.jobTitles" type="string[]">Include only employees whose job title is one of these.</ParamField>
    <ParamField body="filter.managerIds" type="string[]">Include only the **direct** reports (depth 1) of any of these managers.</ParamField>
    <ParamField body="filter.ancestorManagerIds" type="string[]">Include all direct and indirect reports of any of these managers.</ParamField>
    <ParamField body="filter.indirectManagerIds" type="string[]">Include only the **indirect** reports (depth ≥2) of any of these managers, excluding their direct reports.</ParamField>
    <ParamField body="filter.hasManager" type="boolean">If set, include only employees who have (`true`) or lack (`false`) a manager.</ParamField>
    <ParamField body="filter.hasDirectReports" type="boolean">If set, include only employees who have (`true`) or lack (`false`) direct reports.</ParamField>
    <ParamField body="filter.isMember" type="boolean">If set, include only employees who are (`true`) or aren't (`false`) workspace members.</ParamField>
    <ParamField body="filter.query" type="string">Free-text search matched against employee name, email, and job title.</ParamField>
    <ParamField body="filter.status" type="string" default="CURRENT">Employment status to include: `CURRENT`, `FORMER`, or `ALL`. Defaults to `CURRENT`, which excludes former employees.</ParamField>
    <ParamField body="filter.startDate" type="object">A date-range object restricting to employees whose start date falls within the range.</ParamField>
  </Expandable>
</ParamField>

<ParamField body="submittedOnly" type="boolean" default="false">
  When `true`, include only submitted/finalized reviews and omit ones that weren't completed. When `false` (the default), include every review so incomplete work stays visible via each review's `status` and `submittedAt`. Draft answer content is never returned either way.
</ParamField>

## Response

<ResponseField name="cycle" type="object" required>
  Summary of the exported cycle.

  <Expandable title="properties">
    <ResponseField name="id" type="string" required>The cycle's id.</ResponseField>
    <ResponseField name="name" type="string" required>The cycle's display name.</ResponseField>
    <ResponseField name="status" type="string" required>The cycle's lifecycle status: `ACTIVE`, `PAUSED`, or `COMPLETED`. Never `ARCHIVED`, since archived cycles can't be exported.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="stages" type="object[]" required>
  The cycle's stages, including type, timing, completion stats, and the question sets used in each. Questions live here **once** (deduplicated, nested under their stage); each review references its set via `questionSetId`, and each answer references its question version via `questionId`.

  <Expandable title="stage properties">
    <ResponseField name="type" type="string" required>
      The stage direction: `MANAGER_REVIEW`, `SELF_REVIEW`, `PEER_FEEDBACK`, or `UPWARD_FEEDBACK`.
    </ResponseField>

    <ResponseField name="stageTaskId" type="string" required>Stable id for this stage within the cycle.</ResponseField>
    <ResponseField name="name" type="string" required>The stage's display name as configured in the cycle.</ResponseField>
    <ResponseField name="status" type="string" required>The stage's lifecycle status: `ACTIVE`, `PAUSED`, `COMPLETED`, or `ARCHIVED`.</ResponseField>

    <ResponseField name="schedule" type="object | null" required>
      The stage's open/close window; `null` if the stage was never scheduled.

      <Expandable title="properties">
        <ResponseField name="startAt" type="string | null">ISO-8601 time the stage opened; `null` if unscheduled.</ResponseField>
        <ResponseField name="endAt" type="string | null">ISO-8601 deadline for the stage; `null` if no deadline was set.</ResponseField>
        <ResponseField name="timezone" type="string | null">IANA timezone the schedule was configured in; `null` if unset.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="stats" type="object" required>
      Completion counts for the review assignments in this stage, over the in-scope reviewees (respects the `filter`; not affected by `submittedOnly`, so completion gaps stay visible).

      <Expandable title="properties">
        <ResponseField name="expected" type="integer">Expected review sessions in this stage.</ResponseField>
        <ResponseField name="notStarted" type="integer">Of those, how many have not been started.</ResponseField>
        <ResponseField name="inProgress" type="integer">Of those, how many were started but not submitted.</ResponseField>
        <ResponseField name="completed" type="integer">Of those, how many were submitted.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="questionSets" type="object[]" required>
      The question set(s) used by sessions in this stage. There can be more than one when sessions were pointed at different sets.

      <Expandable title="properties">
        <ResponseField name="id" type="string" required>Stable id of the set. Reviews reference the set they were answered against via `questionSetId`.</ResponseField>

        <ResponseField name="questions" type="object[]" required>
          Every question **version** referenced by any answer against this set across the cycle, not only the latest. Resolve an answer via `answer.questionId === question.id`; trace edits via `question.previousVersionId`.

          <Expandable title="question properties">
            <ResponseField name="id" type="string" required>Identifier of this specific question version. Questions are immutable and copy-on-write, so an edit produces a new id.</ResponseField>
            <ResponseField name="previousVersionId" type="string | null">The id of the version this question was edited from; `null` for the original.</ResponseField>
            <ResponseField name="type" type="string" required>Question type: `TEXT`, `SINGLE_SELECT`, `MULTI_SELECT`, `BOOLEAN`, `SCALE`, `NPS`, or `RATING`. Determines the shape of `options` and of matching answers' `value`.</ResponseField>
            <ResponseField name="label" type="string" required>The question prompt shown to the respondent.</ResponseField>
            <ResponseField name="description" type="string" required>Supporting context shown beneath the prompt; empty string when none.</ResponseField>
            <ResponseField name="helpText" type="string | null">Optional tooltip/help text; `null` when none.</ResponseField>
            <ResponseField name="required" type="boolean" required>Whether the respondent had to answer this question to submit.</ResponseField>
            <ResponseField name="formattingInstructions" type="string | null">**`TEXT` questions only.** Optional formatting guidance shown to the respondent; `null` when none.</ResponseField>
            <ResponseField name="options" type="object">Type-specific configuration. Present for everything except `TEXT`. For `SCALE`: bounds, step, and labels. For `NPS`: labels only. For `SINGLE_SELECT`/`MULTI_SELECT`: the choices. For `BOOLEAN`: `{ "defaultValue": boolean, "freeTextIfTrue": boolean, "freeTextIfFalse": boolean }`. For `RATING`: `{ "points": [{ "value": number, "label": string | null }] }`.</ResponseField>
            <ResponseField name="questionSetId" type="string" required>Id of the question set this question belongs to.</ResponseField>
            <ResponseField name="order" type="number" required>0-based position of the question within its set.</ResponseField>
            <ResponseField name="createdAt" type="string" required>ISO-8601 time this question version was created.</ResponseField>
            <ResponseField name="visibleToEmployee" type="boolean | null">For manager-review questions, whether the reviewed employee can see this question/answer once released. `null` for self/peer/upward stages, where the concept doesn't apply.</ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="feedbackCollectionStartTime" type="string | null">
      **Peer stages only.** ISO-8601 time peer-feedback collection opened; `null` if unset.
    </ResponseField>

    <ResponseField name="requestStats" type="object">
      **Peer stages only.** Completion counts for peer-feedback **requests** (nomination → response), distinct from the response `stats`. Same shape as `stats`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="packets" type="object[]" required>
  One packet per reviewee included in the response: every reviewee, or the filtered subset.

  <Expandable title="packet properties">
    <ResponseField name="employee" type="object" required>
      The employee this packet is about (the reviewee).

      <Expandable title="properties">
        <ResponseField name="id" type="string" required>Windmill employee id; the stable key to join this person to other records.</ResponseField>
        <ResponseField name="primaryEmail" type="string | null">The employee's primary work email; `null` if none is on file. Useful for matching to an external HRIS.</ResponseField>
        <ResponseField name="name" type="string" required>The employee's display name.</ResponseField>
        <ResponseField name="jobTitle" type="string | null">The employee's job title at export time; `null` if none on file.</ResponseField>
        <ResponseField name="managerId" type="string | null">Employee id of this person's manager at export time; `null` if unmanaged.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="reviewPeriod" type="object" required>
      The time window this cycle evaluated for the employee.

      <Expandable title="properties">
        <ResponseField name="reviewPeriodStart" type="string" required>ISO-8601 date for the start of the period.</ResponseField>
        <ResponseField name="reviewPeriodEnd" type="string" required>ISO-8601 date for the end of the period.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="managerReviews" type="object[]" required>
      The manager reviews of the employee; empty if no manager review applied.

      <Expandable title="properties">
        <ResponseField name="questionSetId" type="string | null" required>Id of the question set (in the stage's `questionSets`) this review was answered against; `null` when the review has no associated question set.</ResponseField>
        <ResponseField name="status" type="string" required>Status of the manager review: `PENDING`, `IN_PROGRESS`, `SUBMITTED`, or `LOCKED`.</ResponseField>
        <ResponseField name="manager" type="object" required>The manager who authored the review (same shape as `employee`).</ResponseField>
        <ResponseField name="deadlineAt" type="string | null">ISO-8601 due date; `null` if none.</ResponseField>
        <ResponseField name="submittedAt" type="string | null">ISO-8601 time the manager submitted; `null` if not yet submitted.</ResponseField>
        <ResponseField name="answers" type="object[]" required>The manager's answers (see [Answer shape](#answer-shape)).</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="selfReview" type="object | null" required>
      The employee's self review; `null` if self review didn't apply.

      <Expandable title="properties">
        <ResponseField name="questionSetId" type="string | null" required>Id of the question set this self review was answered against; `null` when the review has no associated question set.</ResponseField>
        <ResponseField name="status" type="string" required>Submission progress: `NOT_STARTED`, `IN_PROGRESS`, or `COMPLETED`.</ResponseField>
        <ResponseField name="submittedAt" type="string | null">ISO-8601 time the employee submitted; `null` if not submitted.</ResponseField>
        <ResponseField name="answers" type="object[]" required>The employee's self-review answers (see [Answer shape](#answer-shape)).</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="peerReviews" type="object[]" required>
      All peer feedback received about the employee; empty if none.

      <Expandable title="properties">
        <ResponseField name="id" type="string" required>Stable id of this individual peer feedback.</ResponseField>
        <ResponseField name="questionSetId" type="string | null" required>Id of the question set this peer feedback was answered against; `null` when the review has no associated question set.</ResponseField>
        <ResponseField name="fromEmployee" type="object | null">The peer who gave the feedback (same shape as `employee`). Mirrors platform visibility, and is populated for a cycle admin.</ResponseField>
        <ResponseField name="status" type="string" required>Submission progress: `NOT_STARTED`, `IN_PROGRESS`, or `COMPLETED`.</ResponseField>
        <ResponseField name="answers" type="object[]" required>This peer's answers (see [Answer shape](#answer-shape)).</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="upwardReviews" type="object[]" required>
      All upward feedback received about the employee from reports; empty if none.

      <Expandable title="properties">
        <ResponseField name="questionSetId" type="string | null" required>Id of the question set this upward feedback was answered against; `null` when the review has no associated question set.</ResponseField>
        <ResponseField name="fromEmployee" type="object | null">The report who gave upward feedback (same shape as `employee`). Mirrors platform visibility, and is populated for a cycle admin.</ResponseField>
        <ResponseField name="status" type="string" required>Submission progress: `NOT_STARTED`, `IN_PROGRESS`, or `COMPLETED`.</ResponseField>
        <ResponseField name="answers" type="object[]" required>This report's answers (see [Answer shape](#answer-shape)).</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="count" type="integer" required>
  Number of packets returned (equals `packets.length`).
</ResponseField>

### Answer shape

Every answer in a review has the same shape:

<ResponseField name="questionId" type="string" required>
  Id of the exact question **version** answered. Resolve it inside the review's question set: `stages[].questionSets[].questions[]` where `id === questionId`.
</ResponseField>

<ResponseField name="value" type="object | null" required>
  The submitted, finalized answer. `null` when the question wasn't answered or wasn't submitted. Draft content is never returned. The inner shape depends on the question's `type`:

  * **`TEXT`** → `{ "value": string | null }`
  * **`SINGLE_SELECT`** → `{ "value": string | null, "freeText": string | null }` (`value` matches an option's `value`)
  * **`MULTI_SELECT`** → `{ "value": string[] | null }`
  * **`BOOLEAN`** → `{ "value": boolean, "freeText": string | null }`
  * **`SCALE`** / **`NPS`** / **`RATING`** → `{ "value": number | null }`
</ResponseField>

<ResponseField name="submittedAt" type="string | null" required>
  ISO-8601 time the answer was submitted; `null` if never submitted (in which case `value` is `null`).
</ResponseField>

<Note>
  AI and authoring internals are intentionally excluded from answers. The export contains only finalized, human-submitted content.
</Note>

## Errors

| Status             | When                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request`  | The cycle is archived: `Cannot export an archived performance review cycle`.                                                                                               |
| `401 Unauthorized` | The API key is missing, malformed, expired, or revoked, or an OAuth bearer token was used. Only API keys are supported today; OAuth bearer tokens are explicitly rejected. |
| `403 Forbidden`    | The key is valid but its creator isn't an admin of this cycle. This also covers an unknown or cross-company `cycleId`, since the admin check runs first.                   |

The error response body is always shaped like this:

```json theme={null}
{
  "error": {
    "code": "FORBIDDEN",
    "message": "You don't have permission to access this resource",
    "requestId": "019f2986-8ea9-79ff-8ac2-612072b7cca6"
  }
}
```

<RequestExample>
  ```bash All reviewees theme={null}
  curl -X POST \
    'https://api.gowindmill.com/api/v2/c/acme/cycles/cyc_8f2a1c/packets/export' \
    -H 'Authorization: Bearer wm_api_xxxxxxxxxxxxxxxxxxxx' \
    -H 'Content-Type: application/json' \
    -d '{}'
  ```

  ```bash Filtered + submitted only theme={null}
  curl -X POST \
    'https://api.gowindmill.com/api/v2/c/acme/cycles/cyc_8f2a1c/packets/export' \
    -H 'Authorization: Bearer wm_api_xxxxxxxxxxxxxxxxxxxx' \
    -H 'Content-Type: application/json' \
    -d '{
      "filter": { "managerIds": ["emp_charles"] },
      "submittedOnly": true
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "cycle": {
      "id": "cyc_8f2a1c",
      "name": "H1 2026 Performance Review",
      "status": "COMPLETED"
    },
    "stages": [
      {
        "type": "SELF_REVIEW",
        "stageTaskId": "stg_self_01",
        "name": "Self review",
        "status": "COMPLETED",
        "schedule": {
          "startAt": "2026-03-02T00:00:00.000Z",
          "endAt": "2026-03-16T23:59:59.000Z",
          "timezone": "America/New_York"
        },
        "stats": { "expected": 1, "notStarted": 0, "inProgress": 0, "completed": 1 },
        "questionSets": [
          {
            "id": "qset_self_v1",
            "questions": [
              {
                "id": "q_accomplishments_v1",
                "previousVersionId": null,
                "type": "TEXT",
                "label": "What are you most proud of this half?",
                "description": "",
                "helpText": null,
                "required": true,
                "questionSetId": "qset_self_v1",
                "order": 0,
                "createdAt": "2026-02-20T14:11:00.000Z",
                "visibleToEmployee": null
              },
              {
                "id": "q_self_rating_v1",
                "previousVersionId": null,
                "type": "SCALE",
                "label": "How would you rate your overall impact this half?",
                "description": "1 = below expectations, 5 = far exceeds.",
                "helpText": null,
                "required": true,
                "options": {
                  "min": 1,
                  "max": 5,
                  "step": 1,
                  "integer": true,
                  "labels": { "low": "Below expectations", "high": "Far exceeds" }
                },
                "questionSetId": "qset_self_v1",
                "order": 1,
                "createdAt": "2026-02-20T14:11:00.000Z",
                "visibleToEmployee": null
              },
              {
                "id": "q_enps_v1",
                "previousVersionId": null,
                "type": "NPS",
                "label": "How likely are you to recommend Acme as a place to work?",
                "description": "",
                "helpText": null,
                "required": false,
                "options": {
                  "labels": { "low": "Not at all likely", "high": "Extremely likely" }
                },
                "questionSetId": "qset_self_v1",
                "order": 2,
                "createdAt": "2026-02-20T14:11:00.000Z",
                "visibleToEmployee": null
              }
            ]
          }
        ]
      },
      {
        "type": "MANAGER_REVIEW",
        "stageTaskId": "stg_mgr_01",
        "name": "Manager review",
        "status": "COMPLETED",
        "schedule": {
          "startAt": "2026-03-17T00:00:00.000Z",
          "endAt": "2026-03-31T23:59:59.000Z",
          "timezone": "America/New_York"
        },
        "stats": { "expected": 1, "notStarted": 0, "inProgress": 0, "completed": 1 },
        "questionSets": [
          {
            "id": "qset_mgr_v1",
            "questions": [
              {
                "id": "q_overall_rating_v1",
                "previousVersionId": null,
                "type": "SINGLE_SELECT",
                "label": "Overall performance rating",
                "description": "Select the rating that best reflects this half.",
                "helpText": null,
                "required": true,
                "options": {
                  "options": [
                    { "value": "exceeds", "label": "Exceeds expectations", "description": null },
                    { "value": "meets", "label": "Meets expectations", "description": null },
                    { "value": "below", "label": "Below expectations", "description": null }
                  ],
                  "enableFreeText": false
                },
                "questionSetId": "qset_mgr_v1",
                "order": 0,
                "createdAt": "2026-02-20T14:11:00.000Z",
                "visibleToEmployee": true
              },
              {
                "id": "q_strengths_v1",
                "previousVersionId": null,
                "type": "MULTI_SELECT",
                "label": "Which strengths stood out this half?",
                "description": "Select up to three.",
                "helpText": null,
                "required": false,
                "options": {
                  "choices": [
                    { "value": "execution", "label": "Execution" },
                    { "value": "collaboration", "label": "Collaboration" },
                    { "value": "leadership", "label": "Leadership" },
                    { "value": "craft", "label": "Technical craft" }
                  ],
                  "minSelections": null,
                  "maxSelections": 3
                },
                "questionSetId": "qset_mgr_v1",
                "order": 1,
                "createdAt": "2026-02-20T14:11:00.000Z",
                "visibleToEmployee": true
              },
              {
                "id": "q_promotion_ready_v1",
                "previousVersionId": null,
                "type": "BOOLEAN",
                "label": "Is this person ready for promotion?",
                "description": "",
                "helpText": "Visible only to calibration admins until released.",
                "required": true,
                "options": {
                  "defaultValue": false,
                  "freeTextIfTrue": true,
                  "freeTextIfFalse": false
                },
                "questionSetId": "qset_mgr_v1",
                "order": 2,
                "createdAt": "2026-02-20T14:11:00.000Z",
                "visibleToEmployee": false
              },
              {
                "id": "q_summary_v1",
                "previousVersionId": null,
                "type": "TEXT",
                "label": "Overall summary for the employee",
                "description": "",
                "helpText": null,
                "required": true,
                "questionSetId": "qset_mgr_v1",
                "order": 3,
                "createdAt": "2026-02-20T14:11:00.000Z",
                "visibleToEmployee": true
              }
            ]
          }
        ]
      }
    ],
    "packets": [
      {
        "employee": {
          "id": "emp_ada",
          "primaryEmail": "ada@acme.com",
          "name": "Ada Lovelace",
          "jobTitle": "Staff Engineer",
          "managerId": "emp_charles"
        },
        "reviewPeriod": {
          "reviewPeriodStart": "2026-01-01",
          "reviewPeriodEnd": "2026-06-30"
        },
        "managerReviews": [
          {
            "questionSetId": "qset_mgr_v1",
            "status": "SUBMITTED",
            "manager": {
              "id": "emp_charles",
              "primaryEmail": "charles@acme.com",
              "name": "Charles Babbage",
              "jobTitle": "Engineering Manager",
              "managerId": null
            },
            "deadlineAt": "2026-03-31T23:59:59.000Z",
            "submittedAt": "2026-03-29T19:42:00.000Z",
            "answers": [
              {
                "questionId": "q_overall_rating_v1",
                "value": { "value": "exceeds", "freeText": null },
                "submittedAt": "2026-03-29T19:42:00.000Z"
              },
              {
                "questionId": "q_strengths_v1",
                "value": { "value": ["execution", "collaboration"] },
                "submittedAt": "2026-03-29T19:42:00.000Z"
              },
              {
                "questionId": "q_promotion_ready_v1",
                "value": { "value": true, "freeText": "Ready for the senior level this cycle." },
                "submittedAt": "2026-03-29T19:42:00.000Z"
              },
              {
                "questionId": "q_summary_v1",
                "value": { "value": "A standout half with strong delivery and a great teammate." },
                "submittedAt": "2026-03-29T19:42:00.000Z"
              }
            ]
          }
        ],
        "selfReview": {
          "questionSetId": "qset_self_v1",
          "status": "COMPLETED",
          "submittedAt": "2026-03-14T11:05:00.000Z",
          "answers": [
            {
              "questionId": "q_accomplishments_v1",
              "value": { "value": "Shipped the analytics pipeline ahead of schedule." },
              "submittedAt": "2026-03-14T11:05:00.000Z"
            },
            {
              "questionId": "q_self_rating_v1",
              "value": { "value": 4 },
              "submittedAt": "2026-03-14T11:05:00.000Z"
            },
            {
              "questionId": "q_enps_v1",
              "value": { "value": 9 },
              "submittedAt": "2026-03-14T11:05:00.000Z"
            }
          ]
        },
        "peerReviews": [
          {
            "id": "peer_001",
            "questionSetId": "qset_self_v1",
            "fromEmployee": {
              "id": "emp_grace",
              "primaryEmail": "grace@acme.com",
              "name": "Grace Hopper",
              "jobTitle": "Senior Engineer",
              "managerId": "emp_charles"
            },
            "status": "COMPLETED",
            "answers": []
          }
        ],
        "upwardReviews": []
      }
    ],
    "count": 1
  }
  ```

  ```json 403 Forbidden theme={null}
  {
    "error": {
      "code": "FORBIDDEN",
      "message": "You don't have permission to access this resource",
      "requestId": "019f2986-8ea9-79ff-8ac2-612072b7cca6"
    }
  }
  ```
</ResponseExample>
